+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 { getTopic } from './topics';
+
+const internals = {
+ provider: null
+};
+
+describe('Topics 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('GetTopic', () => {
+
+ beforeAll(async () => {
+
+ const topicQuery = new GraphQLInteraction()
+ .given('there\'s data')
+ .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: {
+ data: {
+ topic: {
+ id: like('0b58959d-d448-4a4e-84b6-35e5ac0028d1'),
+ title: like('The pacty topic of the day'),
+ updated_at: like(1619979888906),
+ ttl: like(3399),
+ forum: {
+ id: like('cucumber'),
+ glyph: like('✽'),
+ label: like('test_forums.cucumber')
+ },
+ tags: eachLike({
+ id: like('skunk'),
+ weight: like(44)
+ }),
+ posts: eachLike({
+ id: like('ed93530e-6f9c-4701-91ef-14f9e0ed3e26'),
+ text: like('The content of this post is very relevant'),
+ created_at: like(1619979889798),
+ author: like({
+ id: like('07fb2ba0-0945-464a-b215-873296710c8c'),
+ handle: like('cucumber_fan92')
+ })
+ })
+ }
+ }
+ }
+ });
+ return await internals.provider.addInteraction(topicQuery);
+ });
+
+ test('it returns the topic', 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).toEqual({
+ 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'
+ }
+ }]
+ });
+ expect(response.loading).toBe(false);
+ expect(response.error).toBe(undefined);
+ });
+ });
+ });
+
+ describe('When there\'s no data', () => {
+
+ describe('GetTopic', () => {
+
+ beforeAll(async () => {
+
+ const topicQuery = new GraphQLInteraction()
+ .given('there\'s no data')
+ .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: {
+ data: {
+ topic: null
+ }
+ }
+ });
+ return await internals.provider.addInteraction(topicQuery);
+ });
+
+ test('it returns the topic', 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).toBe(undefined);
+ });
+ });
+ });
+
+ describe('When there\'s an error', () => {
+
+ describe('GetTopic', () => {
+
+ beforeAll(async () => {
+
+ const topicQuery = new GraphQLInteraction()
+ .given('there\'s an error')
+ .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: 500
+ });
+ 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).toBeInstanceOf(Error);
+ });
+ });
+ });
+});