]> git.r.bdr.sh - rbdr/forum/blob - src/stores/topics.test.js
Add tests for actions + pacts for graphql errrors
[rbdr/forum] / src / stores / topics.test.js
1 import { GraphQLInteraction, Pact, Matchers } from '@pact-foundation/pact';
2 import { resolve } from 'path';
3
4 import { resolveAfter } from '$/utils/resolve_after';
5
6 const { eachLike, like } = Matchers;
7
8 jest.mock('$/config/config.js');
9
10 import { getTopic } from './topics';
11
12 const internals = {
13 provider: null
14 };
15
16 describe('Topics store pact', () => {
17
18 beforeAll(async () => {
19
20 internals.provider = new Pact({
21 port: 1234,
22 dir: resolve(process.cwd(), 'pacts'),
23 consumer: 'ForumClient',
24 provider: 'ForumServer',
25 pactfileWriteMode: 'update'
26 });
27
28 await internals.provider.setup();
29 });
30
31 afterEach(() => internals.provider.verify());
32 afterAll(() => internals.provider.finalize());
33
34 describe('When there\'s data', () => {
35
36 describe('GetTopic', () => {
37
38 beforeAll(async () => {
39
40 const topicQuery = new GraphQLInteraction()
41 .given('there\'s data')
42 .uponReceiving('a request to get a single topic')
43 .withRequest({
44 path: '/graphql',
45 method: 'POST'
46 })
47 .withOperation('GetTopic')
48 .withQuery(
49 `query GetTopic($id: ID!) {
50 topic(id: $id) {
51 id
52 title
53 updated_at
54 ttl
55 forum {
56 id
57 glyph
58 label
59 __typename
60 }
61 tags {
62 id
63 weight
64 __typename
65 }
66 posts {
67 id
68 text
69 created_at
70 author {
71 id
72 handle
73 __typename
74 }
75 __typename
76 }
77 __typename
78 }
79 }`
80 )
81 .withVariables({
82 id: '0b58959d-d448-4a4e-84b6-35e5ac0028d1'
83 })
84 .willRespondWith({
85 status: 200,
86 headers: {
87 'Content-Type': 'application/json; charset=utf-8'
88 },
89 body: {
90 data: {
91 topic: {
92 id: like('0b58959d-d448-4a4e-84b6-35e5ac0028d1'),
93 title: like('The pacty topic of the day'),
94 updated_at: like(1619979888906),
95 ttl: like(3399),
96 forum: {
97 id: like('cucumber'),
98 glyph: like('✽'),
99 label: like('test_forums.cucumber')
100 },
101 tags: eachLike({
102 id: like('skunk'),
103 weight: like(44)
104 }),
105 posts: eachLike({
106 id: like('ed93530e-6f9c-4701-91ef-14f9e0ed3e26'),
107 text: like('The content of this post is very relevant'),
108 created_at: like(1619979889798),
109 author: like({
110 id: like('07fb2ba0-0945-464a-b215-873296710c8c'),
111 handle: like('cucumber_fan92')
112 })
113 })
114 }
115 }
116 }
117 });
118 return await internals.provider.addInteraction(topicQuery);
119 });
120
121 test('it returns the topic', async () => {
122
123 const topic = getTopic('0b58959d-d448-4a4e-84b6-35e5ac0028d1');
124 const { counter, promise: resolveAfterTwo } = resolveAfter(2);
125 let response = null;
126 topic.subscribe((topicValue) => {
127
128 response = topicValue;
129 counter();
130 });
131 expect(response.data).toBe(null);
132 expect(response.loading).toBe(true);
133 expect(response.error).toBe(undefined);
134 await resolveAfterTwo;
135 expect(response.data).toEqual({
136 id: '0b58959d-d448-4a4e-84b6-35e5ac0028d1',
137 title: 'The pacty topic of the day',
138 updated_at: 1619979888906,
139 ttl: 3399,
140 forum: {
141 id: 'cucumber',
142 glyph: '✽',
143 label: 'test_forums.cucumber'
144 },
145 tags: [{
146 id: 'skunk',
147 weight: 44
148 }],
149 posts: [{
150 id: 'ed93530e-6f9c-4701-91ef-14f9e0ed3e26',
151 text: 'The content of this post is very relevant',
152 created_at: 1619979889798,
153 author: {
154 id: '07fb2ba0-0945-464a-b215-873296710c8c',
155 handle: 'cucumber_fan92'
156 }
157 }]
158 });
159 expect(response.loading).toBe(false);
160 expect(response.error).toBe(undefined);
161 });
162 });
163 });
164
165 describe('When there\'s no data', () => {
166
167 describe('GetTopic', () => {
168
169 beforeAll(async () => {
170
171 const topicQuery = new GraphQLInteraction()
172 .given('there\'s no data')
173 .uponReceiving('a request to get a single topic')
174 .withRequest({
175 path: '/graphql',
176 method: 'POST'
177 })
178 .withOperation('GetTopic')
179 .withQuery(
180 `query GetTopic($id: ID!) {
181 topic(id: $id) {
182 id
183 title
184 updated_at
185 ttl
186 forum {
187 id
188 glyph
189 label
190 __typename
191 }
192 tags {
193 id
194 weight
195 __typename
196 }
197 posts {
198 id
199 text
200 created_at
201 author {
202 id
203 handle
204 __typename
205 }
206 __typename
207 }
208 __typename
209 }
210 }`
211 )
212 .withVariables({
213 id: '0b58959d-d448-4a4e-84b6-35e5ac0028d1'
214 })
215 .willRespondWith({
216 status: 200,
217 headers: {
218 'Content-Type': 'application/json; charset=utf-8'
219 },
220 body: {
221 data: {
222 topic: null
223 }
224 }
225 });
226 return await internals.provider.addInteraction(topicQuery);
227 });
228
229 test('it returns the topic', async () => {
230
231 const topic = getTopic('0b58959d-d448-4a4e-84b6-35e5ac0028d1');
232 const { counter, promise: resolveAfterTwo } = resolveAfter(2);
233 let response = null;
234 topic.subscribe((topicValue) => {
235
236 response = topicValue;
237 counter();
238 });
239 expect(response.data).toBe(null);
240 expect(response.loading).toBe(true);
241 expect(response.error).toBe(undefined);
242 await resolveAfterTwo;
243 expect(response.data).toBe(null);
244 expect(response.loading).toBe(false);
245 expect(response.error).toBe(undefined);
246 });
247 });
248 });
249
250 describe('When there\'s a server error', () => {
251
252 describe('GetTopic', () => {
253
254 beforeAll(async () => {
255
256 const topicQuery = new GraphQLInteraction()
257 .given('there\'s a server error')
258 .uponReceiving('a request to get a single topic')
259 .withRequest({
260 path: '/graphql',
261 method: 'POST'
262 })
263 .withOperation('GetTopic')
264 .withQuery(
265 `query GetTopic($id: ID!) {
266 topic(id: $id) {
267 id
268 title
269 updated_at
270 ttl
271 forum {
272 id
273 glyph
274 label
275 __typename
276 }
277 tags {
278 id
279 weight
280 __typename
281 }
282 posts {
283 id
284 text
285 created_at
286 author {
287 id
288 handle
289 __typename
290 }
291 __typename
292 }
293 __typename
294 }
295 }`
296 )
297 .withVariables({
298 id: '0b58959d-d448-4a4e-84b6-35e5ac0028d1'
299 })
300 .willRespondWith({
301 status: 500
302 });
303 return await internals.provider.addInteraction(topicQuery);
304 });
305
306 test('it returns the error', async () => {
307
308 const topic = getTopic('0b58959d-d448-4a4e-84b6-35e5ac0028d1');
309 const { counter, promise: resolveAfterTwo } = resolveAfter(2);
310 let response = null;
311 topic.subscribe((topicValue) => {
312
313 response = topicValue;
314 counter();
315 });
316 expect(response.data).toBe(null);
317 expect(response.loading).toBe(true);
318 expect(response.error).toBe(undefined);
319 await resolveAfterTwo;
320 expect(response.data).toBe(null);
321 expect(response.loading).toBe(false);
322 expect(response.error).toBeInstanceOf(Error);
323 });
324 });
325 });
326
327 describe('When there\'s an error in the response', () => {
328
329 describe('GetTopic', () => {
330
331 beforeAll(async () => {
332
333 const topicQuery = new GraphQLInteraction()
334 .given('there\'s an error in the response')
335 .uponReceiving('a request to get a single topic')
336 .withRequest({
337 path: '/graphql',
338 method: 'POST'
339 })
340 .withOperation('GetTopic')
341 .withQuery(
342 `query GetTopic($id: ID!) {
343 topic(id: $id) {
344 id
345 title
346 updated_at
347 ttl
348 forum {
349 id
350 glyph
351 label
352 __typename
353 }
354 tags {
355 id
356 weight
357 __typename
358 }
359 posts {
360 id
361 text
362 created_at
363 author {
364 id
365 handle
366 __typename
367 }
368 __typename
369 }
370 __typename
371 }
372 }`
373 )
374 .withVariables({
375 id: '0b58959d-d448-4a4e-84b6-35e5ac0028d1'
376 })
377 .willRespondWith({
378 status: 200,
379 headers: {
380 'Content-Type': 'application/json; charset=utf-8'
381 },
382 body: {
383 errors: eachLike({
384 message: like('An error occurred when fetching the topic')
385 })
386 }
387 });
388 return await internals.provider.addInteraction(topicQuery);
389 });
390
391 test('it returns the error', async () => {
392
393 const topic = getTopic('0b58959d-d448-4a4e-84b6-35e5ac0028d1');
394 const { counter, promise: resolveAfterTwo } = resolveAfter(2);
395 let response = null;
396 topic.subscribe((topicValue) => {
397
398 response = topicValue;
399 counter();
400 });
401 expect(response.data).toBe(null);
402 expect(response.loading).toBe(true);
403 expect(response.error).toBe(undefined);
404 await resolveAfterTwo;
405 expect(response.data).toBe(null);
406 expect(response.loading).toBe(false);
407 expect(response.error.graphQLErrors).toEqual(expect.arrayContaining([{
408 message: 'An error occurred when fetching the topic'
409 }]));
410 });
411 });
412 });
413 });