import { GraphQLInteraction, Pact, Matchers } from '@pact-foundation/pact'; import { resolve } from 'path'; import { resolveAfter } from '$lib/utils/resolve_after'; const { eachLike, like } = Matchers; jest.mock('$lib/config/config.ts'); import { post } from './posts'; const internals = { provider: null }; describe('post', () => { 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: '8f75eba5-6989-4dd3-b466-e464546ce374' }) .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 = post('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).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: '8f75eba5-6989-4dd3-b466-e464546ce374' }) .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 = post('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).toBe(undefined); }); }); }); describe("When there's a server error", () => { describe('GetPost', () => { beforeAll(async () => { const postQuery = new GraphQLInteraction() .given("there's a server 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: '8f75eba5-6989-4dd3-b466-e464546ce374' }) .willRespondWith({ status: 500 }); return await internals.provider.addInteraction(postQuery); }); test('it returns the error', async () => { const post = post('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).toBeInstanceOf(Error); }); }); }); 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 = post('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' } ]) ); }); }); }); });