diff options
| -rw-r--r-- | pacts/forumclient-forumserver.json | 657 | ||||
| -rw-r--r-- | src/stores/actions.js | 2 | ||||
| -rw-r--r-- | src/stores/actions.test.js | 32 | ||||
| -rw-r--r-- | src/stores/forums.test.js | 140 | ||||
| -rw-r--r-- | src/stores/posts.test.js | 80 | ||||
| -rw-r--r-- | src/stores/tags.test.js | 73 | ||||
| -rw-r--r-- | src/stores/topics.test.js | 91 |
7 files changed, 855 insertions, 220 deletions
diff --git a/pacts/forumclient-forumserver.json b/pacts/forumclient-forumserver.json index 337ff86..9ec37f8 100644 --- a/pacts/forumclient-forumserver.json +++ b/pacts/forumclient-forumserver.json @@ -7,7 +7,7 @@ }, "interactions": [ { - "description": "a request to get a single post", + "description": "a request to list the forums", "providerState": "there's data", "request": { "method": "POST", @@ -16,16 +16,15 @@ "content-type": "application/json" }, "body": { - "operationName": "GetPost", - "query": "query GetPost($id: ID!) {\n post(id: $id) {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n topic {\n id\n title\n __typename\n }\n __typename\n }\n }", + "operationName": "GetForums", + "query": "query GetForums {\n forums {\n id\n glyph\n label\n position\n __typename\n }\n }", "variables": { - "id": "8f75eba5-6989-4dd3-b466-e464546ce374" } }, "matchingRules": { "$.body.query": { "match": "regex", - "regex": "query\\s*GetPost\\(\\$id:\\s*ID!\\)\\s*\\{\\s*post\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*topic\\s*\\{\\s*id\\s*title\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + "regex": "query\\s*GetForums\\s*\\{\\s*forums\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*__typename\\s*\\}\\s*\\}" } } }, @@ -36,57 +35,120 @@ }, "body": { "data": { - "post": { - "id": "8f75eba5-6989-4dd3-b466-e464546ce374", - "text": "This is a very pacty post", - "created_at": 1619976194937, - "author": { - "id": "a805b3de-cac4-451c-a1e6-f078869c9db9", - "handle": "pacts_person" - }, - "topic": { - "id": "5c283ce1-0470-4b98-86f5-1fec9a22c9ac", - "title": "The parent pacts topic" + "forums": [ + { + "id": "butter", + "glyph": "⌘", + "label": "test_forums.butter", + "position": 1 } - } + ] } }, "matchingRules": { - "$.body.data.post": { + "$.body.data.forums": { + "min": 1 + }, + "$.body.data.forums[*].*": { "match": "type" }, - "$.body.data.post.id": { + "$.body.data.forums[*].id": { "match": "type" }, - "$.body.data.post.text": { + "$.body.data.forums[*].glyph": { "match": "type" }, - "$.body.data.post.created_at": { + "$.body.data.forums[*].label": { "match": "type" }, - "$.body.data.post.author": { + "$.body.data.forums[*].position": { + "match": "type" + } + } + } + }, + { + "description": "a request to get a single forum", + "providerState": "there's data", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetForum", + "query": "query GetForum($id: ID!) {\n forum(id: $id) {\n id\n glyph\n label\n position\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "freezer" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetForum\\(\\$id:\\s*ID!\\)\\s*\\{\\s*forum\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "data": { + "forum": { + "id": "freezer", + "glyph": "✭", + "label": "test_forums.freezer", + "position": 3, + "topics": [ + { + "id": "629de02c-151a-4db7-bb86-43b2add8a15a", + "title": "Very pacty topic", + "updated_at": 1619954611616, + "ttl": 3601 + } + ] + } + } + }, + "matchingRules": { + "$.body.data.forum": { "match": "type" }, - "$.body.data.post.author.id": { + "$.body.data.forum.glyph": { "match": "type" }, - "$.body.data.post.author.handle": { + "$.body.data.forum.label": { "match": "type" }, - "$.body.data.post.topic": { + "$.body.data.forum.position": { "match": "type" }, - "$.body.data.post.topic.id": { + "$.body.data.forum.topics": { + "min": 1 + }, + "$.body.data.forum.topics[*].*": { "match": "type" }, - "$.body.data.post.topic.title": { + "$.body.data.forum.topics[*].id": { + "match": "type" + }, + "$.body.data.forum.topics[*].title": { + "match": "type" + }, + "$.body.data.forum.topics[*].updated_at": { + "match": "type" + }, + "$.body.data.forum.topics[*].ttl": { "match": "type" } } } }, { - "description": "a request to get a single post", + "description": "a request to list the forums", "providerState": "there's no data", "request": { "method": "POST", @@ -95,16 +157,15 @@ "content-type": "application/json" }, "body": { - "operationName": "GetPost", - "query": "query GetPost($id: ID!) {\n post(id: $id) {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n topic {\n id\n title\n __typename\n }\n __typename\n }\n }", + "operationName": "GetForums", + "query": "query GetForums {\n forums {\n id\n glyph\n label\n position\n __typename\n }\n }", "variables": { - "id": "8f75eba5-6989-4dd3-b466-e464546ce374" } }, "matchingRules": { "$.body.query": { "match": "regex", - "regex": "query\\s*GetPost\\(\\$id:\\s*ID!\\)\\s*\\{\\s*post\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*topic\\s*\\{\\s*id\\s*title\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + "regex": "query\\s*GetForums\\s*\\{\\s*forums\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*__typename\\s*\\}\\s*\\}" } } }, @@ -115,14 +176,16 @@ }, "body": { "data": { - "post": null + "forums": [ + + ] } } } }, { - "description": "a request to get a single post", - "providerState": "there's an error", + "description": "a request to get a single forum", + "providerState": "there's no data", "request": { "method": "POST", "path": "/graphql", @@ -130,16 +193,79 @@ "content-type": "application/json" }, "body": { - "operationName": "GetPost", - "query": "query GetPost($id: ID!) {\n post(id: $id) {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n topic {\n id\n title\n __typename\n }\n __typename\n }\n }", + "operationName": "GetForum", + "query": "query GetForum($id: ID!) {\n forum(id: $id) {\n id\n glyph\n label\n position\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", "variables": { - "id": "8f75eba5-6989-4dd3-b466-e464546ce374" + "id": "freezer" } }, "matchingRules": { "$.body.query": { "match": "regex", - "regex": "query\\s*GetPost\\(\\$id:\\s*ID!\\)\\s*\\{\\s*post\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*topic\\s*\\{\\s*id\\s*title\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + "regex": "query\\s*GetForum\\(\\$id:\\s*ID!\\)\\s*\\{\\s*forum\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "data": { + "forum": null + } + } + } + }, + { + "description": "a request to list the forums", + "providerState": "there's a server error", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetForums", + "query": "query GetForums {\n forums {\n id\n glyph\n label\n position\n __typename\n }\n }", + "variables": { + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetForums\\s*\\{\\s*forums\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 500, + "headers": { + } + } + }, + { + "description": "a request to get a single forum", + "providerState": "there's a server error", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetForum", + "query": "query GetForum($id: ID!) {\n forum(id: $id) {\n id\n glyph\n label\n position\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "freezer" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetForum\\(\\$id:\\s*ID!\\)\\s*\\{\\s*forum\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" } } }, @@ -151,7 +277,7 @@ }, { "description": "a request to list the forums", - "providerState": "there's data", + "providerState": "there's an error in the response", "request": { "method": "POST", "path": "/graphql", @@ -177,34 +303,20 @@ "Content-Type": "application/json; charset=utf-8" }, "body": { - "data": { - "forums": [ - { - "id": "butter", - "glyph": "⌘", - "label": "test_forums.butter", - "position": 1 - } - ] - } + "errors": [ + { + "message": "An error occurred when fetching forums" + } + ] }, "matchingRules": { - "$.body.data.forums": { + "$.body.errors": { "min": 1 }, - "$.body.data.forums[*].*": { + "$.body.errors[*].*": { "match": "type" }, - "$.body.data.forums[*].id": { - "match": "type" - }, - "$.body.data.forums[*].glyph": { - "match": "type" - }, - "$.body.data.forums[*].label": { - "match": "type" - }, - "$.body.data.forums[*].position": { + "$.body.errors[*].message": { "match": "type" } } @@ -212,7 +324,7 @@ }, { "description": "a request to get a single forum", - "providerState": "there's data", + "providerState": "there's an error in the response", "request": { "method": "POST", "path": "/graphql", @@ -239,60 +351,28 @@ "Content-Type": "application/json; charset=utf-8" }, "body": { - "data": { - "forum": { - "id": "freezer", - "glyph": "✭", - "label": "test_forums.freezer", - "position": 3, - "topics": [ - { - "id": "629de02c-151a-4db7-bb86-43b2add8a15a", - "title": "Very pacty topic", - "updated_at": 1619954611616, - "ttl": 3601 - } - ] + "errors": [ + { + "message": "An error occurred when fetching the forum" } - } + ] }, "matchingRules": { - "$.body.data.forum": { - "match": "type" - }, - "$.body.data.forum.glyph": { - "match": "type" - }, - "$.body.data.forum.label": { - "match": "type" - }, - "$.body.data.forum.position": { - "match": "type" - }, - "$.body.data.forum.topics": { + "$.body.errors": { "min": 1 }, - "$.body.data.forum.topics[*].*": { + "$.body.errors[*].*": { "match": "type" }, - "$.body.data.forum.topics[*].id": { - "match": "type" - }, - "$.body.data.forum.topics[*].title": { - "match": "type" - }, - "$.body.data.forum.topics[*].updated_at": { - "match": "type" - }, - "$.body.data.forum.topics[*].ttl": { + "$.body.errors[*].message": { "match": "type" } } } }, { - "description": "a request to list the forums", - "providerState": "there's no data", + "description": "a request to get a single topic", + "providerState": "there's data", "request": { "method": "POST", "path": "/graphql", @@ -300,15 +380,16 @@ "content-type": "application/json" }, "body": { - "operationName": "GetForums", - "query": "query GetForums {\n forums {\n id\n glyph\n label\n position\n __typename\n }\n }", + "operationName": "GetTopic", + "query": "query GetTopic($id: ID!) {\n topic(id: $id) {\n id\n title\n updated_at\n ttl\n forum {\n id\n glyph\n label\n __typename\n }\n tags {\n id\n weight\n __typename\n }\n posts {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n __typename\n }\n __typename\n }\n }", "variables": { + "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1" } }, "matchingRules": { "$.body.query": { "match": "regex", - "regex": "query\\s*GetForums\\s*\\{\\s*forums\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*__typename\\s*\\}\\s*\\}" + "regex": "query\\s*GetTopic\\(\\$id:\\s*ID!\\)\\s*\\{\\s*topic\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*forum\\s*\\{\\s*id\\s*glyph\\s*label\\s*__typename\\s*\\}\\s*tags\\s*\\{\\s*id\\s*weight\\s*__typename\\s*\\}\\s*posts\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" } } }, @@ -319,15 +400,99 @@ }, "body": { "data": { - "forums": [ - - ] + "topic": { + "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1", + "title": "The pacty topic of the day", + "updated_at": 1619979888906, + "ttl": 3399, + "forum": { + "id": "cucumber", + "glyph": "✽", + "label": "test_forums.cucumber" + }, + "tags": [ + { + "id": "skunk", + "weight": 44 + } + ], + "posts": [ + { + "id": "ed93530e-6f9c-4701-91ef-14f9e0ed3e26", + "text": "The content of this post is very relevant", + "created_at": 1619979889798, + "author": { + "id": "07fb2ba0-0945-464a-b215-873296710c8c", + "handle": "cucumber_fan92" + } + } + ] + } + } + }, + "matchingRules": { + "$.body.data.topic.id": { + "match": "type" + }, + "$.body.data.topic.title": { + "match": "type" + }, + "$.body.data.topic.updated_at": { + "match": "type" + }, + "$.body.data.topic.ttl": { + "match": "type" + }, + "$.body.data.topic.forum.id": { + "match": "type" + }, + "$.body.data.topic.forum.glyph": { + "match": "type" + }, + "$.body.data.topic.forum.label": { + "match": "type" + }, + "$.body.data.topic.tags": { + "min": 1 + }, + "$.body.data.topic.tags[*].*": { + "match": "type" + }, + "$.body.data.topic.tags[*].id": { + "match": "type" + }, + "$.body.data.topic.tags[*].weight": { + "match": "type" + }, + "$.body.data.topic.posts": { + "min": 1 + }, + "$.body.data.topic.posts[*].*": { + "match": "type" + }, + "$.body.data.topic.posts[*].id": { + "match": "type" + }, + "$.body.data.topic.posts[*].text": { + "match": "type" + }, + "$.body.data.topic.posts[*].created_at": { + "match": "type" + }, + "$.body.data.topic.posts[*].author": { + "match": "type" + }, + "$.body.data.topic.posts[*].author.id": { + "match": "type" + }, + "$.body.data.topic.posts[*].author.handle": { + "match": "type" } } } }, { - "description": "a request to get a single forum", + "description": "a request to get a single topic", "providerState": "there's no data", "request": { "method": "POST", @@ -336,16 +501,16 @@ "content-type": "application/json" }, "body": { - "operationName": "GetForum", - "query": "query GetForum($id: ID!) {\n forum(id: $id) {\n id\n glyph\n label\n position\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", + "operationName": "GetTopic", + "query": "query GetTopic($id: ID!) {\n topic(id: $id) {\n id\n title\n updated_at\n ttl\n forum {\n id\n glyph\n label\n __typename\n }\n tags {\n id\n weight\n __typename\n }\n posts {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n __typename\n }\n __typename\n }\n }", "variables": { - "id": "freezer" + "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1" } }, "matchingRules": { "$.body.query": { "match": "regex", - "regex": "query\\s*GetForum\\(\\$id:\\s*ID!\\)\\s*\\{\\s*forum\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + "regex": "query\\s*GetTopic\\(\\$id:\\s*ID!\\)\\s*\\{\\s*topic\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*forum\\s*\\{\\s*id\\s*glyph\\s*label\\s*__typename\\s*\\}\\s*tags\\s*\\{\\s*id\\s*weight\\s*__typename\\s*\\}\\s*posts\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" } } }, @@ -356,14 +521,14 @@ }, "body": { "data": { - "forum": null + "topic": null } } } }, { - "description": "a request to list the forums", - "providerState": "there's an error", + "description": "a request to get a single topic", + "providerState": "there's a server error", "request": { "method": "POST", "path": "/graphql", @@ -371,15 +536,16 @@ "content-type": "application/json" }, "body": { - "operationName": "GetForums", - "query": "query GetForums {\n forums {\n id\n glyph\n label\n position\n __typename\n }\n }", + "operationName": "GetTopic", + "query": "query GetTopic($id: ID!) {\n topic(id: $id) {\n id\n title\n updated_at\n ttl\n forum {\n id\n glyph\n label\n __typename\n }\n tags {\n id\n weight\n __typename\n }\n posts {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n __typename\n }\n __typename\n }\n }", "variables": { + "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1" } }, "matchingRules": { "$.body.query": { "match": "regex", - "regex": "query\\s*GetForums\\s*\\{\\s*forums\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*__typename\\s*\\}\\s*\\}" + "regex": "query\\s*GetTopic\\(\\$id:\\s*ID!\\)\\s*\\{\\s*topic\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*forum\\s*\\{\\s*id\\s*glyph\\s*label\\s*__typename\\s*\\}\\s*tags\\s*\\{\\s*id\\s*weight\\s*__typename\\s*\\}\\s*posts\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" } } }, @@ -390,8 +556,8 @@ } }, { - "description": "a request to get a single forum", - "providerState": "there's an error", + "description": "a request to get a single topic", + "providerState": "there's an error in the response", "request": { "method": "POST", "path": "/graphql", @@ -399,22 +565,41 @@ "content-type": "application/json" }, "body": { - "operationName": "GetForum", - "query": "query GetForum($id: ID!) {\n forum(id: $id) {\n id\n glyph\n label\n position\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", + "operationName": "GetTopic", + "query": "query GetTopic($id: ID!) {\n topic(id: $id) {\n id\n title\n updated_at\n ttl\n forum {\n id\n glyph\n label\n __typename\n }\n tags {\n id\n weight\n __typename\n }\n posts {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n __typename\n }\n __typename\n }\n }", "variables": { - "id": "freezer" + "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1" } }, "matchingRules": { "$.body.query": { "match": "regex", - "regex": "query\\s*GetForum\\(\\$id:\\s*ID!\\)\\s*\\{\\s*forum\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*glyph\\s*label\\s*position\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + "regex": "query\\s*GetTopic\\(\\$id:\\s*ID!\\)\\s*\\{\\s*topic\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*forum\\s*\\{\\s*id\\s*glyph\\s*label\\s*__typename\\s*\\}\\s*tags\\s*\\{\\s*id\\s*weight\\s*__typename\\s*\\}\\s*posts\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" } } }, "response": { - "status": 500, + "status": 200, "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "errors": [ + { + "message": "An error occurred when fetching the topic" + } + ] + }, + "matchingRules": { + "$.body.errors": { + "min": 1 + }, + "$.body.errors[*].*": { + "match": "type" + }, + "$.body.errors[*].message": { + "match": "type" + } } } }, @@ -523,7 +708,7 @@ }, { "description": "a request to get a single tag", - "providerState": "there's an error", + "providerState": "there's a server error", "request": { "method": "POST", "path": "/graphql", @@ -551,8 +736,8 @@ } }, { - "description": "a request to get a single topic", - "providerState": "there's data", + "description": "a request to get a single tag", + "providerState": "there's an error in the response", "request": { "method": "POST", "path": "/graphql", @@ -560,16 +745,16 @@ "content-type": "application/json" }, "body": { - "operationName": "GetTopic", - "query": "query GetTopic($id: ID!) {\n topic(id: $id) {\n id\n title\n updated_at\n ttl\n forum {\n id\n glyph\n label\n __typename\n }\n tags {\n id\n weight\n __typename\n }\n posts {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n __typename\n }\n __typename\n }\n }", + "operationName": "GetTag", + "query": "query GetTag($id: ID!) {\n tag(id: $id) {\n id\n topics {\n id\n title\n updated_at\n ttl\n __typename\n }\n __typename\n }\n }", "variables": { - "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1" + "id": "pineapple" } }, "matchingRules": { "$.body.query": { "match": "regex", - "regex": "query\\s*GetTopic\\(\\$id:\\s*ID!\\)\\s*\\{\\s*topic\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*forum\\s*\\{\\s*id\\s*glyph\\s*label\\s*__typename\\s*\\}\\s*tags\\s*\\{\\s*id\\s*weight\\s*__typename\\s*\\}\\s*posts\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + "regex": "query\\s*GetTag\\(\\$id:\\s*ID!\\)\\s*\\{\\s*tag\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*topics\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" } } }, @@ -579,100 +764,106 @@ "Content-Type": "application/json; charset=utf-8" }, "body": { - "data": { - "topic": { - "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1", - "title": "The pacty topic of the day", - "updated_at": 1619979888906, - "ttl": 3399, - "forum": { - "id": "cucumber", - "glyph": "✽", - "label": "test_forums.cucumber" - }, - "tags": [ - { - "id": "skunk", - "weight": 44 - } - ], - "posts": [ - { - "id": "ed93530e-6f9c-4701-91ef-14f9e0ed3e26", - "text": "The content of this post is very relevant", - "created_at": 1619979889798, - "author": { - "id": "07fb2ba0-0945-464a-b215-873296710c8c", - "handle": "cucumber_fan92" - } - } - ] + "errors": [ + { + "message": "An error occurred when fetching the tag" } - } + ] }, "matchingRules": { - "$.body.data.topic.id": { - "match": "type" - }, - "$.body.data.topic.title": { - "match": "type" - }, - "$.body.data.topic.updated_at": { - "match": "type" - }, - "$.body.data.topic.ttl": { - "match": "type" + "$.body.errors": { + "min": 1 }, - "$.body.data.topic.forum.id": { + "$.body.errors[*].*": { "match": "type" }, - "$.body.data.topic.forum.glyph": { + "$.body.errors[*].message": { "match": "type" - }, - "$.body.data.topic.forum.label": { - "match": "type" - }, - "$.body.data.topic.tags": { - "min": 1 - }, - "$.body.data.topic.tags[*].*": { + } + } + } + }, + { + "description": "a request to get a single post", + "providerState": "there's data", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetPost", + "query": "query GetPost($id: ID!) {\n post(id: $id) {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n topic {\n id\n title\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "8f75eba5-6989-4dd3-b466-e464546ce374" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetPost\\(\\$id:\\s*ID!\\)\\s*\\{\\s*post\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*topic\\s*\\{\\s*id\\s*title\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "data": { + "post": { + "id": "8f75eba5-6989-4dd3-b466-e464546ce374", + "text": "This is a very pacty post", + "created_at": 1619976194937, + "author": { + "id": "a805b3de-cac4-451c-a1e6-f078869c9db9", + "handle": "pacts_person" + }, + "topic": { + "id": "5c283ce1-0470-4b98-86f5-1fec9a22c9ac", + "title": "The parent pacts topic" + } + } + } + }, + "matchingRules": { + "$.body.data.post": { "match": "type" }, - "$.body.data.topic.tags[*].id": { + "$.body.data.post.id": { "match": "type" }, - "$.body.data.topic.tags[*].weight": { + "$.body.data.post.text": { "match": "type" }, - "$.body.data.topic.posts": { - "min": 1 - }, - "$.body.data.topic.posts[*].*": { + "$.body.data.post.created_at": { "match": "type" }, - "$.body.data.topic.posts[*].id": { + "$.body.data.post.author": { "match": "type" }, - "$.body.data.topic.posts[*].text": { + "$.body.data.post.author.id": { "match": "type" }, - "$.body.data.topic.posts[*].created_at": { + "$.body.data.post.author.handle": { "match": "type" }, - "$.body.data.topic.posts[*].author": { + "$.body.data.post.topic": { "match": "type" }, - "$.body.data.topic.posts[*].author.id": { + "$.body.data.post.topic.id": { "match": "type" }, - "$.body.data.topic.posts[*].author.handle": { + "$.body.data.post.topic.title": { "match": "type" } } } }, { - "description": "a request to get a single topic", + "description": "a request to get a single post", "providerState": "there's no data", "request": { "method": "POST", @@ -681,16 +872,16 @@ "content-type": "application/json" }, "body": { - "operationName": "GetTopic", - "query": "query GetTopic($id: ID!) {\n topic(id: $id) {\n id\n title\n updated_at\n ttl\n forum {\n id\n glyph\n label\n __typename\n }\n tags {\n id\n weight\n __typename\n }\n posts {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n __typename\n }\n __typename\n }\n }", + "operationName": "GetPost", + "query": "query GetPost($id: ID!) {\n post(id: $id) {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n topic {\n id\n title\n __typename\n }\n __typename\n }\n }", "variables": { - "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1" + "id": "8f75eba5-6989-4dd3-b466-e464546ce374" } }, "matchingRules": { "$.body.query": { "match": "regex", - "regex": "query\\s*GetTopic\\(\\$id:\\s*ID!\\)\\s*\\{\\s*topic\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*forum\\s*\\{\\s*id\\s*glyph\\s*label\\s*__typename\\s*\\}\\s*tags\\s*\\{\\s*id\\s*weight\\s*__typename\\s*\\}\\s*posts\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + "regex": "query\\s*GetPost\\(\\$id:\\s*ID!\\)\\s*\\{\\s*post\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*topic\\s*\\{\\s*id\\s*title\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" } } }, @@ -701,14 +892,14 @@ }, "body": { "data": { - "topic": null + "post": null } } } }, { - "description": "a request to get a single topic", - "providerState": "there's an error", + "description": "a request to get a single post", + "providerState": "there's a server error", "request": { "method": "POST", "path": "/graphql", @@ -716,16 +907,16 @@ "content-type": "application/json" }, "body": { - "operationName": "GetTopic", - "query": "query GetTopic($id: ID!) {\n topic(id: $id) {\n id\n title\n updated_at\n ttl\n forum {\n id\n glyph\n label\n __typename\n }\n tags {\n id\n weight\n __typename\n }\n posts {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n __typename\n }\n __typename\n }\n }", + "operationName": "GetPost", + "query": "query GetPost($id: ID!) {\n post(id: $id) {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n topic {\n id\n title\n __typename\n }\n __typename\n }\n }", "variables": { - "id": "0b58959d-d448-4a4e-84b6-35e5ac0028d1" + "id": "8f75eba5-6989-4dd3-b466-e464546ce374" } }, "matchingRules": { "$.body.query": { "match": "regex", - "regex": "query\\s*GetTopic\\(\\$id:\\s*ID!\\)\\s*\\{\\s*topic\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*title\\s*updated_at\\s*ttl\\s*forum\\s*\\{\\s*id\\s*glyph\\s*label\\s*__typename\\s*\\}\\s*tags\\s*\\{\\s*id\\s*weight\\s*__typename\\s*\\}\\s*posts\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + "regex": "query\\s*GetPost\\(\\$id:\\s*ID!\\)\\s*\\{\\s*post\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*topic\\s*\\{\\s*id\\s*title\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" } } }, @@ -734,6 +925,54 @@ "headers": { } } + }, + { + "description": "a request to get a single post", + "providerState": "there's an error in the response", + "request": { + "method": "POST", + "path": "/graphql", + "headers": { + "content-type": "application/json" + }, + "body": { + "operationName": "GetPost", + "query": "query GetPost($id: ID!) {\n post(id: $id) {\n id\n text\n created_at\n author {\n id\n handle\n __typename\n }\n topic {\n id\n title\n __typename\n }\n __typename\n }\n }", + "variables": { + "id": "8f75eba5-6989-4dd3-b466-e464546ce374" + } + }, + "matchingRules": { + "$.body.query": { + "match": "regex", + "regex": "query\\s*GetPost\\(\\$id:\\s*ID!\\)\\s*\\{\\s*post\\(id:\\s*\\$id\\)\\s*\\{\\s*id\\s*text\\s*created_at\\s*author\\s*\\{\\s*id\\s*handle\\s*__typename\\s*\\}\\s*topic\\s*\\{\\s*id\\s*title\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json; charset=utf-8" + }, + "body": { + "errors": [ + { + "message": "An error occurred when fetching the post" + } + ] + }, + "matchingRules": { + "$.body.errors": { + "min": 1 + }, + "$.body.errors[*].*": { + "match": "type" + }, + "$.body.errors[*].message": { + "match": "type" + } + } + } } ], "metadata": { diff --git a/src/stores/actions.js b/src/stores/actions.js index ae01906..f7fbc28 100644 --- a/src/stores/actions.js +++ b/src/stores/actions.js @@ -4,7 +4,7 @@ import { derived, writable } from 'svelte/store'; * This is a store to set the actions in the top header. */ -export const actions = writable({}); +const actions = writable({}); export const enableTopicActions = (id) => { diff --git a/src/stores/actions.test.js b/src/stores/actions.test.js new file mode 100644 index 0000000..c650536 --- /dev/null +++ b/src/stores/actions.test.js @@ -0,0 +1,32 @@ +import { enableTopicActions, disableTopicActions, topicActions } from './actions'; + +describe('Topic actions and state', () => { + + test('There should be no topic actions by default', () => { + + topicActions.subscribe((actions) => { + + expect(actions).toBe(undefined); + })(); + }); + + test('enableTopicActions should set the topic id', () => { + + enableTopicActions('free_hat'); + topicActions.subscribe((actions) => { + + expect(actions).toEqual({ + id: 'free_hat' + }); + })(); + }); + + test('disableTopicActions should unset the topic id', () => { + + disableTopicActions(); + topicActions.subscribe((actions) => { + + expect(actions).toEqual(undefined); + })(); + }); +}); diff --git a/src/stores/forums.test.js b/src/stores/forums.test.js index eb4bc07..732964f 100644 --- a/src/stores/forums.test.js +++ b/src/stores/forums.test.js @@ -320,14 +320,14 @@ describe('Forums store pact', () => { }); }); - describe('When there\'s an error', () => { + describe('When there\'s a server error', () => { describe('GetForums', () => { beforeAll(async () => { const forumQuery = new GraphQLInteraction() - .given('there\'s an error') + .given('there\'s a server error') .uponReceiving('a request to list the forums') .withRequest({ path: '/graphql', @@ -379,7 +379,7 @@ describe('Forums store pact', () => { beforeAll(async () => { const forumQuery = new GraphQLInteraction() - .given('there\'s an error') + .given('there\'s a server error') .uponReceiving('a request to get a single forum') .withRequest({ path: '/graphql', @@ -433,4 +433,138 @@ describe('Forums store pact', () => { }); }); }); + + describe('When there\'s an error in the response', () => { + + describe('GetForums', () => { + + beforeAll(async () => { + + const forumQuery = new GraphQLInteraction() + .given('there\'s an error in the response') + .uponReceiving('a request to list the forums') + .withRequest({ + path: '/graphql', + method: 'POST' + }) + .withOperation('GetForums') + .withQuery( + `query GetForums { + forums { + id + glyph + label + position + __typename + } + }` + ) + .withVariables({}) + .willRespondWith({ + status: 200, + headers: { + 'Content-Type': 'application/json; charset=utf-8' + }, + body: { + errors: eachLike({ + message: like('An error occurred when fetching forums') + }) + } + }); + return await internals.provider.addInteraction(forumQuery); + }); + + test('it returns the error', async () => { + + const forums = getForums(); + const { counter, promise: resolveAfterTwo } = resolveAfter(2); + let response = null; + forums.subscribe((forumsValue) => { + + response = forumsValue; + counter(); + }); + expect(response.data).toBeInstanceOf(Array); + expect(response.data.length).toBe(0); + expect(response.loading).toBe(true); + expect(response.error).toBe(undefined); + await resolveAfterTwo; + expect(response.data).toBeInstanceOf(Array); + expect(response.data.length).toBe(0); + expect(response.loading).toBe(false); + expect(response.error.graphQLErrors).toEqual(expect.arrayContaining([{ + message: 'An error occurred when fetching forums' + }])); + }); + }); + + describe('GetForum', () => { + + beforeAll(async () => { + + const forumQuery = new GraphQLInteraction() + .given('there\'s an error in the response') + .uponReceiving('a request to get a single forum') + .withRequest({ + path: '/graphql', + method: 'POST' + }) + .withOperation('GetForum') + .withQuery( + `query GetForum($id: ID!) { + forum(id: $id) { + id + glyph + label + position + topics { + id + title + updated_at + ttl + __typename + } + __typename + } + }` + ) + .withVariables({ + id: 'freezer' + }) + .willRespondWith({ + status: 200, + headers: { + 'Content-Type': 'application/json; charset=utf-8' + }, + body: { + errors: eachLike({ + message: like('An error occurred when fetching the forum') + }) + } + }); + return await internals.provider.addInteraction(forumQuery); + }); + + test('it returns the error', async () => { + + const forum = getForum('freezer'); + const { counter, promise: resolveAfterTwo } = resolveAfter(2); + let response = null; + forum.subscribe((forumsValue) => { + + response = forumsValue; + counter(); + }); + expect(response.data).toBe(null); + expect(response.loading).toBe(true); + expect(response.error).toBe(undefined); + await resolveAfterTwo; + expect(response.data).toBe(null); + expect(response.loading).toBe(false); + expect(response.error.graphQLErrors).toEqual(expect.arrayContaining([{ + message: 'An error occurred when fetching the forum' + }])); + }); + }); + }); }); diff --git a/src/stores/posts.test.js b/src/stores/posts.test.js index 5d1fc05..ab17286 100644 --- a/src/stores/posts.test.js +++ b/src/stores/posts.test.js @@ -3,7 +3,7 @@ import { resolve } from 'path'; import { resolveAfter } from '$/utils/resolve_after'; -const { like } = Matchers; +const { eachLike, like } = Matchers; jest.mock('$/config/config.js'); @@ -199,14 +199,14 @@ describe('Posts store pact', () => { }); }); - describe('When there\'s an error', () => { + describe('When there\'s a server error', () => { describe('GetPost', () => { beforeAll(async () => { const postQuery = new GraphQLInteraction() - .given('there\'s an error') + .given('there\'s a server error') .uponReceiving('a request to get a single post') .withRequest({ path: '/graphql', @@ -262,4 +262,78 @@ describe('Posts store pact', () => { }); }); }); + + describe('When there\'s an error in the response', () => { + + describe('GetPost', () => { + + beforeAll(async () => { + + const postQuery = new GraphQLInteraction() + .given('there\'s an error in the response') + .uponReceiving('a request to get a single post') + .withRequest({ + path: '/graphql', + method: 'POST' + }) + .withOperation('GetPost') + .withQuery( + `query GetPost($id: ID!) { + post(id: $id) { + id + text + created_at + author { + id + handle + __typename + } + topic { + id + title + __typename + } + __typename + } + }` + ) + .withVariables({ + id: '8f75eba5-6989-4dd3-b466-e464546ce374' + }) + .willRespondWith({ + status: 200, + headers: { + 'Content-Type': 'application/json; charset=utf-8' + }, + body: { + errors: eachLike({ + message: like('An error occurred when fetching the post') + }) + } + }); + return await internals.provider.addInteraction(postQuery); + }); + + test('it returns the error', async () => { + + const post = getPost('8f75eba5-6989-4dd3-b466-e464546ce374'); + const { counter, promise: resolveAfterTwo } = resolveAfter(2); + let response = null; + post.subscribe((postValue) => { + + response = postValue; + counter(); + }); + expect(response.data).toBe(null); + expect(response.loading).toBe(true); + expect(response.error).toBe(undefined); + await resolveAfterTwo; + expect(response.data).toBe(null); + expect(response.loading).toBe(false); + expect(response.error.graphQLErrors).toEqual(expect.arrayContaining([{ + message: 'An error occurred when fetching the post' + }])); + }); + }); + }); }); diff --git a/src/stores/tags.test.js b/src/stores/tags.test.js index 177919b..bf4fa56 100644 --- a/src/stores/tags.test.js +++ b/src/stores/tags.test.js @@ -181,14 +181,14 @@ describe('Tags store pact', () => { }); }); - describe('When there\'s an error', () => { + describe('When there\'s a server error', () => { describe('GetTag', () => { beforeAll(async () => { const tagQuery = new GraphQLInteraction() - .given('there\'s an error') + .given('there\'s a server error') .uponReceiving('a request to get a single tag') .withRequest({ path: '/graphql', @@ -239,4 +239,73 @@ describe('Tags store pact', () => { }); }); }); + + describe('When there\'s an error in the response', () => { + + describe('GetTag', () => { + + beforeAll(async () => { + + const tagQuery = new GraphQLInteraction() + .given('there\'s an error in the response') + .uponReceiving('a request to get a single tag') + .withRequest({ + path: '/graphql', + method: 'POST' + }) + .withOperation('GetTag') + .withQuery( + `query GetTag($id: ID!) { + tag(id: $id) { + id + topics { + id + title + updated_at + ttl + __typename + } + __typename + } + }` + ) + .withVariables({ + id: 'pineapple' + }) + .willRespondWith({ + status: 200, + headers: { + 'Content-Type': 'application/json; charset=utf-8' + }, + body: { + errors: eachLike({ + message: like('An error occurred when fetching the tag') + }) + } + }); + return await internals.provider.addInteraction(tagQuery); + }); + + test('it returns the error', async () => { + + const tag = getTag('pineapple'); + const { counter, promise: resolveAfterTwo } = resolveAfter(2); + let response = null; + tag.subscribe((tagValue) => { + + response = tagValue; + counter(); + }); + expect(response.data).toBe(null); + expect(response.loading).toBe(true); + expect(response.error).toBe(undefined); + await resolveAfterTwo; + expect(response.data).toBe(null); + expect(response.loading).toBe(false); + expect(response.error.graphQLErrors).toEqual(expect.arrayContaining([{ + message: 'An error occurred when fetching the tag' + }])); + }); + }); + }); }); diff --git a/src/stores/topics.test.js b/src/stores/topics.test.js index 280bddb..7c3285b 100644 --- a/src/stores/topics.test.js +++ b/src/stores/topics.test.js @@ -247,14 +247,14 @@ describe('Topics store pact', () => { }); }); - describe('When there\'s an error', () => { + describe('When there\'s a server error', () => { describe('GetTopic', () => { beforeAll(async () => { const topicQuery = new GraphQLInteraction() - .given('there\'s an error') + .given('there\'s a server error') .uponReceiving('a request to get a single topic') .withRequest({ path: '/graphql', @@ -323,4 +323,91 @@ describe('Topics store pact', () => { }); }); }); + + describe('When there\'s an error in the response', () => { + + describe('GetTopic', () => { + + beforeAll(async () => { + + const topicQuery = new GraphQLInteraction() + .given('there\'s an error in the response') + .uponReceiving('a request to get a single topic') + .withRequest({ + path: '/graphql', + method: 'POST' + }) + .withOperation('GetTopic') + .withQuery( + `query GetTopic($id: ID!) { + topic(id: $id) { + id + title + updated_at + ttl + forum { + id + glyph + label + __typename + } + tags { + id + weight + __typename + } + posts { + id + text + created_at + author { + id + handle + __typename + } + __typename + } + __typename + } + }` + ) + .withVariables({ + id: '0b58959d-d448-4a4e-84b6-35e5ac0028d1' + }) + .willRespondWith({ + status: 200, + headers: { + 'Content-Type': 'application/json; charset=utf-8' + }, + body: { + errors: eachLike({ + message: like('An error occurred when fetching the topic') + }) + } + }); + return await internals.provider.addInteraction(topicQuery); + }); + + test('it returns the error', async () => { + + const topic = getTopic('0b58959d-d448-4a4e-84b6-35e5ac0028d1'); + const { counter, promise: resolveAfterTwo } = resolveAfter(2); + let response = null; + topic.subscribe((topicValue) => { + + response = topicValue; + counter(); + }); + expect(response.data).toBe(null); + expect(response.loading).toBe(true); + expect(response.error).toBe(undefined); + await resolveAfterTwo; + expect(response.data).toBe(null); + expect(response.loading).toBe(false); + expect(response.error.graphQLErrors).toEqual(expect.arrayContaining([{ + message: 'An error occurred when fetching the topic' + }])); + }); + }); + }); }); |