+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);
+ });
+ });
+ });
+});