"build": "svelte-kit build",
"start": "svelte-kit start",
"lint": "eslint --fix .",
- "test": "jest src",
+ "test": "jest src --runInBand",
"test:watch": "npm run test -- --watch"
},
"devDependencies": {
{
"consumer": {
- "name": "ForumsStore"
+ "name": "ForumClient"
},
"provider": {
- "name": "ForumAPIServer"
+ "name": "ForumServer"
},
"interactions": [
+ {
+ "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": "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*\\}"
+ }
+ }
+ },
+ "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.post.id": {
+ "match": "type"
+ },
+ "$.body.data.post.text": {
+ "match": "type"
+ },
+ "$.body.data.post.created_at": {
+ "match": "type"
+ },
+ "$.body.data.post.author": {
+ "match": "type"
+ },
+ "$.body.data.post.author.id": {
+ "match": "type"
+ },
+ "$.body.data.post.author.handle": {
+ "match": "type"
+ },
+ "$.body.data.post.topic": {
+ "match": "type"
+ },
+ "$.body.data.post.topic.id": {
+ "match": "type"
+ },
+ "$.body.data.post.topic.title": {
+ "match": "type"
+ }
+ }
+ }
+ },
+ {
+ "description": "a request to get a single post",
+ "providerState": "there's no 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": "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*\\}"
+ }
+ }
+ },
+ "response": {
+ "status": 200,
+ "headers": {
+ "Content-Type": "application/json; charset=utf-8"
+ },
+ "body": {
+ "data": {
+ "post": null
+ }
+ }
+ }
+ },
+ {
+ "description": "a request to get a single post",
+ "providerState": "there's an error",
+ "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": "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*\\}"
+ }
+ }
+ },
+ "response": {
+ "status": 500,
+ "headers": {
+ }
+ }
+ },
{
"description": "a request to list the forums",
- "providerState": "there's forums",
+ "providerState": "there's data",
"request": {
"method": "POST",
"path": "/graphql",
},
{
"description": "a request to get a single forum",
- "providerState": "there's forums",
+ "providerState": "there's data",
"request": {
"method": "POST",
"path": "/graphql",
},
{
"description": "a request to list the forums",
- "providerState": "there's no forums",
+ "providerState": "there's no data",
"request": {
"method": "POST",
"path": "/graphql",
},
{
"description": "a request to get a single forum",
- "providerState": "there's no forums",
+ "providerState": "there's no data",
"request": {
"method": "POST",
"path": "/graphql",
internals.provider = new Pact({
port: 1234,
dir: resolve(process.cwd(), 'pacts'),
- consumer: 'ForumsStore',
- provider: 'ForumAPIServer'
+ consumer: 'ForumClient',
+ provider: 'ForumServer',
+ pactfileWriteMode: 'update'
});
await internals.provider.setup();
afterEach(() => internals.provider.verify());
afterAll(() => internals.provider.finalize());
- describe('When there\'s forums', () => {
+ describe('When there\'s data', () => {
describe('GetForums', () => {
beforeAll(async () => {
const forumQuery = new GraphQLInteraction()
- .given('there\'s forums')
+ .given('there\'s data')
.uponReceiving('a request to list the forums')
.withRequest({
path: '/graphql',
beforeAll(async () => {
const forumQuery = new GraphQLInteraction()
- .given('there\'s forums')
+ .given('there\'s data')
.uponReceiving('a request to get a single forum')
.withRequest({
path: '/graphql',
});
});
- describe('When there\'s no forums', () => {
+ describe('When there\'s no data', () => {
describe('GetForums', () => {
beforeAll(async () => {
const forumQuery = new GraphQLInteraction()
- .given('there\'s no forums')
+ .given('there\'s no data')
.uponReceiving('a request to list the forums')
.withRequest({
path: '/graphql',
beforeAll(async () => {
const forumQuery = new GraphQLInteraction()
- .given('there\'s no forums')
+ .given('there\'s no data')
.uponReceiving('a request to get a single forum')
.withRequest({
path: '/graphql',
--- /dev/null
+import { GraphQLInteraction, Pact, Matchers } from '@pact-foundation/pact';
+import { resolve } from 'path';
+
+import { resolveAfter } from '$/utils/resolve_after';
+
+const { eachLike, like } = Matchers;
+
+jest.mock('$/config/config.js');
+
+import { getPost } from './posts';
+
+const internals = {
+ provider: null
+};
+
+describe('Posts store pact', () => {
+
+ beforeAll(async () => {
+
+ internals.provider = new Pact({
+ port: 1234,
+ dir: resolve(process.cwd(), 'pacts'),
+ consumer: 'ForumClient',
+ provider: 'ForumServer',
+ pactfileWriteMode: 'update'
+ });
+
+ await internals.provider.setup();
+ });
+
+ afterEach(() => internals.provider.verify());
+ afterAll(() => internals.provider.finalize());
+
+ describe('When there\'s data', () => {
+
+ describe('GetPost', () => {
+
+ beforeAll(async () => {
+
+ const postQuery = new GraphQLInteraction()
+ .given('there\'s data')
+ .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: 'freezer'
+ })
+ .willRespondWith({
+ status: 200,
+ headers: {
+ 'Content-Type': 'application/json; charset=utf-8'
+ },
+ body: {
+ data: {
+ post: like({
+ id: like('8f75eba5-6989-4dd3-b466-e464546ce374'),
+ text: like('This is a very pacty post'),
+ created_at: like(1619976194937),
+ author: like({
+ id: like('a805b3de-cac4-451c-a1e6-f078869c9db9'),
+ handle: like('pacts_person')
+ }),
+ topic: like({
+ id: like('5c283ce1-0470-4b98-86f5-1fec9a22c9ac'),
+ title: like('The parent pacts topic')
+ })
+ })
+ }
+ }
+ });
+ return await internals.provider.addInteraction(postQuery);
+ });
+
+ test('it returns the post', async () => {
+
+ const post = getPost('freezer');
+ 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).toEqual({
+ 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'
+ }
+ });
+ expect(response.loading).toBe(false);
+ expect(response.error).toBe(undefined);
+ });
+ });
+ });
+
+ describe('When there\'s no data', () => {
+
+ describe('GetPost', () => {
+
+ beforeAll(async () => {
+
+ const postQuery = new GraphQLInteraction()
+ .given('there\'s no data')
+ .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: 'freezer'
+ })
+ .willRespondWith({
+ status: 200,
+ headers: {
+ 'Content-Type': 'application/json; charset=utf-8'
+ },
+ body: {
+ data: {
+ post: null
+ }
+ }
+ });
+ return await internals.provider.addInteraction(postQuery);
+ });
+
+ test('it returns the post', async () => {
+
+ const post = getPost('freezer');
+ 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).toBe(undefined);
+ });
+ });
+ });
+
+ describe('When there\'s an error', () => {
+
+ describe('GetPost', () => {
+
+ beforeAll(async () => {
+
+ const postQuery = new GraphQLInteraction()
+ .given('there\'s an error')
+ .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: 'freezer'
+ })
+ .willRespondWith({
+ status: 500
+ });
+ return await internals.provider.addInteraction(postQuery);
+ });
+
+ test('it returns the error', async () => {
+
+ const post = getPost('freezer');
+ 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).toBeInstanceOf(Error);
+ });
+ });
+ });
+});