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 { getForum, getForums } from './forums'; const internals = { provider: null }; describe('Forums 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('GetForums', () => { beforeAll(async () => { const forumQuery = new GraphQLInteraction() .given("there's data") .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: { data: { forums: eachLike({ id: like('butter'), glyph: like('⌘'), label: like('test_forums.butter'), position: like(1) }) } } }); return await internals.provider.addInteraction(forumQuery); }); test('it returns the forums', 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).toEqual( expect.arrayContaining([ { id: 'butter', glyph: '⌘', label: 'test_forums.butter', position: 1 } ]) ); expect(response.loading).toBe(false); expect(response.error).toBe(undefined); }); }); describe('GetForum', () => { beforeAll(async () => { const forumQuery = new GraphQLInteraction() .given("there's data") .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: { data: { forum: like({ id: 'freezer', glyph: like('✭'), label: like('test_forums.freezer'), position: like(3), topics: eachLike({ id: like('629de02c-151a-4db7-bb86-43b2add8a15a'), title: like('Very pacty topic'), updated_at: like(1619954611616), ttl: like(3601) }) }) } } }); return await internals.provider.addInteraction(forumQuery); }); test('it returns the forum', 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.id).toBe('freezer'); expect(response.data.glyph).toBe('✭'); expect(response.data.label).toBe('test_forums.freezer'); expect(response.data.position).toBe(3); expect(response.data.topics).toEqual( expect.arrayContaining([ { id: '629de02c-151a-4db7-bb86-43b2add8a15a', title: 'Very pacty topic', updated_at: 1619954611616, ttl: 3601 } ]) ); expect(response.loading).toBe(false); expect(response.error).toBe(undefined); }); }); }); describe("When there's no data", () => { describe('GetForums', () => { beforeAll(async () => { const forumQuery = new GraphQLInteraction() .given("there's no data") .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: { data: { forums: [] } } }); return await internals.provider.addInteraction(forumQuery); }); test('it returns the forums', 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).toBe(undefined); }); }); describe('GetForum', () => { beforeAll(async () => { const forumQuery = new GraphQLInteraction() .given("there's no data") .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: { data: { forum: null } } }); return await internals.provider.addInteraction(forumQuery); }); test('it returns the forum', 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).toBe(undefined); }); }); }); describe("When there's a server error", () => { describe('GetForums', () => { beforeAll(async () => { const forumQuery = new GraphQLInteraction() .given("there's a server error") .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: 500 }); 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).toBeInstanceOf(Error); }); }); describe('GetForum', () => { beforeAll(async () => { const forumQuery = new GraphQLInteraction() .given("there's a server error") .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: 500 }); 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).toBeInstanceOf(Error); }); }); }); 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' } ]) ); }); }); }); });