@khanacademy/wonder-blocks-testing 3.0.0 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/es/index.js +144 -316
- package/dist/index.js +271 -143
- package/package.json +4 -3
- package/src/{gql/__tests__/make-gql-mock-response.test.js → __tests__/make-mock-response.test.js} +196 -34
- package/src/__tests__/mock-requester.test.js +213 -0
- package/src/__tests__/response-impl.test.js +47 -0
- package/src/fetch/__tests__/__snapshots__/mock-fetch.test.js.snap +29 -0
- package/src/fetch/__tests__/fetch-request-matches-mock.test.js +99 -0
- package/src/fetch/__tests__/mock-fetch.test.js +84 -0
- package/src/fetch/fetch-request-matches-mock.js +43 -0
- package/src/fetch/mock-fetch.js +19 -0
- package/src/fetch/types.js +18 -0
- package/src/fixtures/__tests__/fixtures.test.js +32 -1
- package/src/fixtures/fixtures.js +15 -5
- package/src/gql/__tests__/mock-gql-fetch.test.js +24 -15
- package/src/gql/__tests__/wb-data-integration.test.js +7 -4
- package/src/gql/mock-gql-fetch.js +9 -80
- package/src/gql/types.js +11 -10
- package/src/index.js +9 -3
- package/src/make-mock-response.js +150 -0
- package/src/mock-requester.js +75 -0
- package/src/response-impl.js +9 -0
- package/src/types.js +39 -0
- package/src/gql/make-gql-mock-response.js +0 -124
package/src/{gql/__tests__/make-gql-mock-response.test.js → __tests__/make-mock-response.test.js}
RENAMED
|
@@ -1,65 +1,171 @@
|
|
|
1
1
|
// @flow
|
|
2
|
-
import {RespondWith,
|
|
2
|
+
import {RespondWith, makeMockResponse} from "../make-mock-response.js";
|
|
3
3
|
|
|
4
4
|
describe("RespondWith", () => {
|
|
5
|
-
describe("#
|
|
6
|
-
it("should have type
|
|
5
|
+
describe("#text", () => {
|
|
6
|
+
it("should have type text", () => {
|
|
7
7
|
// Arrange
|
|
8
8
|
|
|
9
9
|
// Act
|
|
10
|
-
const result = RespondWith.
|
|
10
|
+
const result = RespondWith.text("SOME TEXT");
|
|
11
11
|
|
|
12
12
|
// Assert
|
|
13
|
-
expect(result).toHaveProperty("type", "
|
|
13
|
+
expect(result).toHaveProperty("type", "text");
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
-
it("should
|
|
16
|
+
it("should provide the given text", () => {
|
|
17
|
+
// Arrange
|
|
18
|
+
|
|
19
|
+
// Act
|
|
20
|
+
const mockResponse = RespondWith.text("SOME TEXT");
|
|
21
|
+
// $FlowIgnore[incompatible-use]
|
|
22
|
+
const result = mockResponse.text;
|
|
23
|
+
|
|
24
|
+
// Assert
|
|
25
|
+
expect(result).toEqual("SOME TEXT");
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe("#json", () => {
|
|
30
|
+
it("should have type text", () => {
|
|
31
|
+
// Arrange
|
|
32
|
+
|
|
33
|
+
// Act
|
|
34
|
+
const result = RespondWith.json({});
|
|
35
|
+
|
|
36
|
+
// Assert
|
|
37
|
+
expect(result).toHaveProperty("type", "text");
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("should provide the given data in the text", () => {
|
|
41
|
+
// Arrange
|
|
42
|
+
const json = {
|
|
43
|
+
foo: "bar",
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Act
|
|
47
|
+
const mockResponse = RespondWith.json(json);
|
|
48
|
+
// $FlowIgnore[incompatible-use]
|
|
49
|
+
const result = mockResponse.text();
|
|
50
|
+
|
|
51
|
+
// Assert
|
|
52
|
+
expect(result).toEqual(JSON.stringify(json));
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe("#graphQLData", () => {
|
|
57
|
+
it("should have type text", () => {
|
|
58
|
+
// Arrange
|
|
59
|
+
|
|
60
|
+
// Act
|
|
61
|
+
const result = RespondWith.graphQLData({});
|
|
62
|
+
|
|
63
|
+
// Assert
|
|
64
|
+
expect(result).toHaveProperty("type", "text");
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("should provide the given data in the text", () => {
|
|
17
68
|
// Arrange
|
|
18
69
|
const data = {
|
|
19
70
|
foo: "bar",
|
|
20
71
|
};
|
|
21
72
|
|
|
22
73
|
// Act
|
|
23
|
-
const
|
|
74
|
+
const mockResponse = RespondWith.graphQLData(data);
|
|
75
|
+
// $FlowIgnore[incompatible-use]
|
|
76
|
+
const result = mockResponse.text();
|
|
24
77
|
|
|
25
78
|
// Assert
|
|
26
|
-
expect(result).
|
|
79
|
+
expect(result).toEqual(JSON.stringify({data}));
|
|
27
80
|
});
|
|
28
81
|
});
|
|
29
82
|
|
|
30
83
|
describe("#unparseableBody", () => {
|
|
31
|
-
it("should have type
|
|
84
|
+
it("should have type text", () => {
|
|
32
85
|
// Arrange
|
|
33
86
|
|
|
34
87
|
// Act
|
|
35
88
|
const result = RespondWith.unparseableBody();
|
|
36
89
|
|
|
37
90
|
// Assert
|
|
38
|
-
expect(result).toHaveProperty("type", "
|
|
91
|
+
expect(result).toHaveProperty("type", "text");
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("should have text that is unparseable json", () => {
|
|
95
|
+
// Arrange
|
|
96
|
+
|
|
97
|
+
// Act
|
|
98
|
+
const mockResponse = RespondWith.unparseableBody();
|
|
99
|
+
// $FlowIgnore[incompatible-use]
|
|
100
|
+
const underTest = () => JSON.parse(mockResponse.text);
|
|
101
|
+
|
|
102
|
+
// Assert
|
|
103
|
+
expect(underTest).toThrowErrorMatchingInlineSnapshot(
|
|
104
|
+
`"Unexpected token I in JSON at position 0"`,
|
|
105
|
+
);
|
|
39
106
|
});
|
|
40
107
|
});
|
|
41
108
|
|
|
42
109
|
describe("#abortedRequest", () => {
|
|
43
|
-
it("should have type
|
|
110
|
+
it("should have type reject", () => {
|
|
44
111
|
// Arrange
|
|
45
112
|
|
|
46
113
|
// Act
|
|
47
114
|
const result = RespondWith.abortedRequest();
|
|
48
115
|
|
|
49
116
|
// Assert
|
|
50
|
-
expect(result).toHaveProperty("type", "
|
|
117
|
+
expect(result).toHaveProperty("type", "reject");
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("should provide AbortError", () => {
|
|
121
|
+
// Arrange
|
|
122
|
+
|
|
123
|
+
// Act
|
|
124
|
+
const mockResponse = RespondWith.abortedRequest();
|
|
125
|
+
// $FlowIgnore[incompatible-use]
|
|
126
|
+
const result = mockResponse.error();
|
|
127
|
+
|
|
128
|
+
// Assert
|
|
129
|
+
expect(result).toMatchInlineSnapshot(
|
|
130
|
+
`[AbortError: Mock request aborted]`,
|
|
131
|
+
);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe("#reject", () => {
|
|
136
|
+
it("should have type reject", () => {
|
|
137
|
+
// Arrange
|
|
138
|
+
|
|
139
|
+
// Act
|
|
140
|
+
const result = RespondWith.reject(new Error("BOOM!"));
|
|
141
|
+
|
|
142
|
+
// Assert
|
|
143
|
+
expect(result).toHaveProperty("type", "reject");
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it("should have the given error", () => {
|
|
147
|
+
// Arrange
|
|
148
|
+
const error = new Error("BOOM!");
|
|
149
|
+
|
|
150
|
+
// Act
|
|
151
|
+
const mockResponse = RespondWith.reject(error);
|
|
152
|
+
// $FlowIgnore[incompatible-use]
|
|
153
|
+
const result = mockResponse.error;
|
|
154
|
+
|
|
155
|
+
// Assert
|
|
156
|
+
expect(result).toBe(error);
|
|
51
157
|
});
|
|
52
158
|
});
|
|
53
159
|
|
|
54
160
|
describe("#errorStatusCode", () => {
|
|
55
|
-
it("should have type
|
|
161
|
+
it("should have type text", () => {
|
|
56
162
|
// Arrange
|
|
57
163
|
|
|
58
164
|
// Act
|
|
59
165
|
const result = RespondWith.errorStatusCode(400);
|
|
60
166
|
|
|
61
167
|
// Assert
|
|
62
|
-
expect(result).toHaveProperty("type", "
|
|
168
|
+
expect(result).toHaveProperty("type", "text");
|
|
63
169
|
});
|
|
64
170
|
|
|
65
171
|
it("should include the given status code", () => {
|
|
@@ -93,19 +199,48 @@ describe("RespondWith", () => {
|
|
|
93
199
|
const result = RespondWith.nonGraphQLBody();
|
|
94
200
|
|
|
95
201
|
// Assert
|
|
96
|
-
expect(result).toHaveProperty("type", "
|
|
202
|
+
expect(result).toHaveProperty("type", "text");
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it("should have text that is valid json", () => {
|
|
206
|
+
// Arrange
|
|
207
|
+
|
|
208
|
+
// Act
|
|
209
|
+
const mockResponse = RespondWith.nonGraphQLBody();
|
|
210
|
+
// $FlowIgnore[incompatible-use]
|
|
211
|
+
const underTest = () => JSON.parse(mockResponse.text());
|
|
212
|
+
|
|
213
|
+
// Assert
|
|
214
|
+
expect(underTest).not.toThrow();
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it("should have text that is not a valid GraphQL response", () => {
|
|
218
|
+
// Arrange
|
|
219
|
+
|
|
220
|
+
// Act
|
|
221
|
+
const mockResponse = RespondWith.nonGraphQLBody();
|
|
222
|
+
// $FlowIgnore[incompatible-use]
|
|
223
|
+
const result = JSON.parse(mockResponse.text());
|
|
224
|
+
|
|
225
|
+
// Assert
|
|
226
|
+
expect(result).toMatchInlineSnapshot(`
|
|
227
|
+
Object {
|
|
228
|
+
"that": "is not a valid graphql response",
|
|
229
|
+
"valid": "json",
|
|
230
|
+
}
|
|
231
|
+
`);
|
|
97
232
|
});
|
|
98
233
|
});
|
|
99
234
|
|
|
100
235
|
describe("#graphQLErrors", () => {
|
|
101
|
-
it("should have type
|
|
236
|
+
it("should have type test", () => {
|
|
102
237
|
// Arrange
|
|
103
238
|
|
|
104
239
|
// Act
|
|
105
240
|
const result = RespondWith.graphQLErrors([]);
|
|
106
241
|
|
|
107
242
|
// Assert
|
|
108
|
-
expect(result).toHaveProperty("type", "
|
|
243
|
+
expect(result).toHaveProperty("type", "text");
|
|
109
244
|
});
|
|
110
245
|
|
|
111
246
|
it("should include the given error messages", () => {
|
|
@@ -113,10 +248,23 @@ describe("RespondWith", () => {
|
|
|
113
248
|
const errorMessages = ["foo", "bar"];
|
|
114
249
|
|
|
115
250
|
// Act
|
|
116
|
-
const
|
|
251
|
+
const mockResponse = RespondWith.graphQLErrors(errorMessages);
|
|
252
|
+
// $FlowIgnore[incompatible-use]
|
|
253
|
+
const result = JSON.parse(mockResponse.text());
|
|
117
254
|
|
|
118
255
|
// Assert
|
|
119
|
-
expect(result).
|
|
256
|
+
expect(result).toMatchInlineSnapshot(`
|
|
257
|
+
Object {
|
|
258
|
+
"errors": Array [
|
|
259
|
+
Object {
|
|
260
|
+
"message": "foo",
|
|
261
|
+
},
|
|
262
|
+
Object {
|
|
263
|
+
"message": "bar",
|
|
264
|
+
},
|
|
265
|
+
],
|
|
266
|
+
}
|
|
267
|
+
`);
|
|
120
268
|
});
|
|
121
269
|
});
|
|
122
270
|
});
|
|
@@ -127,7 +275,7 @@ describe("#makeGqlErrorResponse", () => {
|
|
|
127
275
|
|
|
128
276
|
// Act
|
|
129
277
|
const result = () =>
|
|
130
|
-
|
|
278
|
+
makeMockResponse(({type: "NOT A VALID TYPE"}: any));
|
|
131
279
|
|
|
132
280
|
// Assert
|
|
133
281
|
expect(result).toThrowErrorMatchingInlineSnapshot(
|
|
@@ -138,10 +286,10 @@ describe("#makeGqlErrorResponse", () => {
|
|
|
138
286
|
describe("data response", () => {
|
|
139
287
|
it("should resolve to have a successful status code", async () => {
|
|
140
288
|
// Arrange
|
|
141
|
-
const mockResponse = RespondWith.
|
|
289
|
+
const mockResponse = RespondWith.graphQLData({});
|
|
142
290
|
|
|
143
291
|
// Act
|
|
144
|
-
const result = await
|
|
292
|
+
const result = await makeMockResponse(mockResponse);
|
|
145
293
|
|
|
146
294
|
// Assert
|
|
147
295
|
expect(result.status).toBe(200);
|
|
@@ -152,10 +300,10 @@ describe("#makeGqlErrorResponse", () => {
|
|
|
152
300
|
const data = {
|
|
153
301
|
foo: "bar",
|
|
154
302
|
};
|
|
155
|
-
const mockResponse = RespondWith.
|
|
303
|
+
const mockResponse = RespondWith.graphQLData(data);
|
|
156
304
|
|
|
157
305
|
// Act
|
|
158
|
-
const response = await
|
|
306
|
+
const response = await makeMockResponse(mockResponse);
|
|
159
307
|
const result = await response.text();
|
|
160
308
|
|
|
161
309
|
// Assert
|
|
@@ -169,7 +317,7 @@ describe("#makeGqlErrorResponse", () => {
|
|
|
169
317
|
const mockResponse = RespondWith.unparseableBody();
|
|
170
318
|
|
|
171
319
|
// Act
|
|
172
|
-
const result = await
|
|
320
|
+
const result = await makeMockResponse(mockResponse);
|
|
173
321
|
|
|
174
322
|
// Assert
|
|
175
323
|
expect(result.status).toBe(200);
|
|
@@ -180,7 +328,7 @@ describe("#makeGqlErrorResponse", () => {
|
|
|
180
328
|
const mockResponse = RespondWith.unparseableBody();
|
|
181
329
|
|
|
182
330
|
// Act
|
|
183
|
-
const response = await
|
|
331
|
+
const response = await makeMockResponse(mockResponse);
|
|
184
332
|
const text = await response.text();
|
|
185
333
|
const act = () => JSON.parse(text);
|
|
186
334
|
|
|
@@ -195,7 +343,7 @@ describe("#makeGqlErrorResponse", () => {
|
|
|
195
343
|
const mockResponse = RespondWith.abortedRequest();
|
|
196
344
|
|
|
197
345
|
// Act
|
|
198
|
-
const act = () =>
|
|
346
|
+
const act = () => makeMockResponse(mockResponse);
|
|
199
347
|
|
|
200
348
|
// Assert
|
|
201
349
|
await expect(act).rejects.toBeInstanceOf(Error);
|
|
@@ -206,20 +354,34 @@ describe("#makeGqlErrorResponse", () => {
|
|
|
206
354
|
const mockResponse = RespondWith.abortedRequest();
|
|
207
355
|
|
|
208
356
|
// Act
|
|
209
|
-
const act =
|
|
357
|
+
const act = makeMockResponse(mockResponse);
|
|
210
358
|
|
|
211
359
|
// Assert
|
|
212
360
|
await expect(act).rejects.toHaveProperty("name", "AbortError");
|
|
213
361
|
});
|
|
214
362
|
});
|
|
215
363
|
|
|
364
|
+
describe("rejection", () => {
|
|
365
|
+
it("should reject with error", async () => {
|
|
366
|
+
// Arrange
|
|
367
|
+
const error = new Error("BOOM!");
|
|
368
|
+
const mockResponse = RespondWith.reject(error);
|
|
369
|
+
|
|
370
|
+
// Act
|
|
371
|
+
const act = () => makeMockResponse(mockResponse);
|
|
372
|
+
|
|
373
|
+
// Assert
|
|
374
|
+
await expect(act).rejects.toBe(error);
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
|
|
216
378
|
describe("error status code response", () => {
|
|
217
379
|
it("should resolve to have the given status code", async () => {
|
|
218
380
|
// Arrange
|
|
219
381
|
const mockResponse = RespondWith.errorStatusCode(400);
|
|
220
382
|
|
|
221
383
|
// Act
|
|
222
|
-
const result = await
|
|
384
|
+
const result = await makeMockResponse(mockResponse);
|
|
223
385
|
|
|
224
386
|
// Assert
|
|
225
387
|
expect(result.status).toBe(400);
|
|
@@ -230,7 +392,7 @@ describe("#makeGqlErrorResponse", () => {
|
|
|
230
392
|
const mockResponse = RespondWith.errorStatusCode(400);
|
|
231
393
|
|
|
232
394
|
// Act
|
|
233
|
-
const response = await
|
|
395
|
+
const response = await makeMockResponse(mockResponse);
|
|
234
396
|
const text = await response.text();
|
|
235
397
|
const act = () => JSON.parse(text);
|
|
236
398
|
|
|
@@ -245,7 +407,7 @@ describe("#makeGqlErrorResponse", () => {
|
|
|
245
407
|
const mockResponse = RespondWith.nonGraphQLBody();
|
|
246
408
|
|
|
247
409
|
// Act
|
|
248
|
-
const result = await
|
|
410
|
+
const result = await makeMockResponse(mockResponse);
|
|
249
411
|
|
|
250
412
|
// Assert
|
|
251
413
|
expect(result.status).toBe(200);
|
|
@@ -256,7 +418,7 @@ describe("#makeGqlErrorResponse", () => {
|
|
|
256
418
|
const mockResponse = RespondWith.nonGraphQLBody();
|
|
257
419
|
|
|
258
420
|
// Act
|
|
259
|
-
const response = await
|
|
421
|
+
const response = await makeMockResponse(mockResponse);
|
|
260
422
|
const text = await response.text();
|
|
261
423
|
const result = JSON.parse(text);
|
|
262
424
|
|
|
@@ -272,7 +434,7 @@ describe("#makeGqlErrorResponse", () => {
|
|
|
272
434
|
const mockResponse = RespondWith.graphQLErrors([]);
|
|
273
435
|
|
|
274
436
|
// Act
|
|
275
|
-
const result = await
|
|
437
|
+
const result = await makeMockResponse(mockResponse);
|
|
276
438
|
|
|
277
439
|
// Assert
|
|
278
440
|
expect(result.status).toBe(200);
|
|
@@ -284,7 +446,7 @@ describe("#makeGqlErrorResponse", () => {
|
|
|
284
446
|
const mockResponse = RespondWith.graphQLErrors(errorMessages);
|
|
285
447
|
|
|
286
448
|
// Act
|
|
287
|
-
const response = await
|
|
449
|
+
const response = await makeMockResponse(mockResponse);
|
|
288
450
|
const text = await response.text();
|
|
289
451
|
const result = JSON.parse(text);
|
|
290
452
|
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import {RespondWith} from "../make-mock-response.js";
|
|
3
|
+
import {mockRequester} from "../mock-requester.js";
|
|
4
|
+
|
|
5
|
+
describe("#mockRequester", () => {
|
|
6
|
+
it("should return a function", () => {
|
|
7
|
+
// Arrange
|
|
8
|
+
|
|
9
|
+
// Act
|
|
10
|
+
const result = mockRequester(jest.fn(), jest.fn());
|
|
11
|
+
|
|
12
|
+
// Assert
|
|
13
|
+
expect(result).toBeInstanceOf(Function);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("should provide mockOperation API", () => {
|
|
17
|
+
// Arrange
|
|
18
|
+
|
|
19
|
+
// Act
|
|
20
|
+
const result = mockRequester(jest.fn(), jest.fn());
|
|
21
|
+
|
|
22
|
+
// Assert
|
|
23
|
+
expect(result).toHaveProperty("mockOperation", expect.any(Function));
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("should provide mockOperationOnce API", () => {
|
|
27
|
+
// Arrange
|
|
28
|
+
|
|
29
|
+
// Act
|
|
30
|
+
const result = mockRequester(jest.fn(), jest.fn());
|
|
31
|
+
|
|
32
|
+
// Assert
|
|
33
|
+
expect(result).toHaveProperty(
|
|
34
|
+
"mockOperationOnce",
|
|
35
|
+
expect.any(Function),
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("should throw with helpful details formatted by operationToString if no matching mock is found", async () => {
|
|
40
|
+
// Arrange
|
|
41
|
+
const mockFn = mockRequester(
|
|
42
|
+
jest.fn(),
|
|
43
|
+
(...args) => `TEST FORMATTING: ${JSON.stringify(args)}`,
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
// Act
|
|
47
|
+
const underTest = mockFn("any", "arguments", {we: {want: 42}});
|
|
48
|
+
|
|
49
|
+
// Assert
|
|
50
|
+
await expect(underTest).rejects.toThrowErrorMatchingInlineSnapshot(`
|
|
51
|
+
"No matching mock response found for request:
|
|
52
|
+
TEST FORMATTING: [\\"any\\",\\"arguments\\",{\\"we\\":{\\"want\\":42}}]"
|
|
53
|
+
`);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe("mockOperation", () => {
|
|
57
|
+
it("should invoke matcher with mock for a request", async () => {
|
|
58
|
+
// Arrange
|
|
59
|
+
const matcher = jest.fn().mockReturnValue(true);
|
|
60
|
+
const operationToString = jest.fn();
|
|
61
|
+
const mockFn = mockRequester(matcher, operationToString);
|
|
62
|
+
|
|
63
|
+
// Act
|
|
64
|
+
mockFn.mockOperation(
|
|
65
|
+
"THE MOCK DESCRIPTION",
|
|
66
|
+
RespondWith.text("TADA!"),
|
|
67
|
+
);
|
|
68
|
+
await mockFn("any", "arguments", {we: {want: 42}});
|
|
69
|
+
|
|
70
|
+
// Assert
|
|
71
|
+
expect(matcher).toHaveBeenCalledWith(
|
|
72
|
+
"THE MOCK DESCRIPTION",
|
|
73
|
+
"any",
|
|
74
|
+
"arguments",
|
|
75
|
+
{
|
|
76
|
+
we: {want: 42},
|
|
77
|
+
},
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("should return mocked operation response if matcher returns true", async () => {
|
|
82
|
+
// Arrange
|
|
83
|
+
const matcher = jest.fn().mockReturnValue(true);
|
|
84
|
+
const operationToString = jest.fn();
|
|
85
|
+
const mockFn = mockRequester(matcher, operationToString);
|
|
86
|
+
|
|
87
|
+
// Act
|
|
88
|
+
mockFn.mockOperation(
|
|
89
|
+
"THE MOCK DESCRIPTION",
|
|
90
|
+
RespondWith.text("TADA!"),
|
|
91
|
+
);
|
|
92
|
+
const response = await mockFn("DO SOMETHING");
|
|
93
|
+
const result = response.text();
|
|
94
|
+
|
|
95
|
+
// Assert
|
|
96
|
+
await expect(result).resolves.toBe("TADA!");
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("should skip mock if matcher returns false and try more mocks", async () => {
|
|
100
|
+
// Arrange
|
|
101
|
+
const matcher = jest
|
|
102
|
+
.fn()
|
|
103
|
+
.mockReturnValueOnce(false)
|
|
104
|
+
.mockReturnValueOnce(true);
|
|
105
|
+
const operationToString = jest.fn();
|
|
106
|
+
const mockFn = mockRequester(matcher, operationToString);
|
|
107
|
+
|
|
108
|
+
// Act
|
|
109
|
+
mockFn.mockOperation(
|
|
110
|
+
"THE MOCK DESCRIPTION 1",
|
|
111
|
+
RespondWith.text("ONE"),
|
|
112
|
+
);
|
|
113
|
+
mockFn.mockOperation(
|
|
114
|
+
"THE MOCK DESCRIPTION 2",
|
|
115
|
+
RespondWith.text("TWO"),
|
|
116
|
+
);
|
|
117
|
+
const response = await mockFn("DO SOMETHING");
|
|
118
|
+
const result = response.text();
|
|
119
|
+
|
|
120
|
+
// Assert
|
|
121
|
+
await expect(result).resolves.toBe("TWO");
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
describe("mockOperationOnce", () => {
|
|
126
|
+
it("should invoke matcher with mock for a request", async () => {
|
|
127
|
+
// Arrange
|
|
128
|
+
const matcher = jest.fn().mockReturnValue(true);
|
|
129
|
+
const operationToString = jest.fn();
|
|
130
|
+
const mockFn = mockRequester(matcher, operationToString);
|
|
131
|
+
|
|
132
|
+
// Act
|
|
133
|
+
mockFn.mockOperationOnce(
|
|
134
|
+
"THE MOCK DESCRIPTION",
|
|
135
|
+
RespondWith.text("TADA!"),
|
|
136
|
+
);
|
|
137
|
+
await mockFn("any", "arguments", {we: {want: 42}});
|
|
138
|
+
|
|
139
|
+
// Assert
|
|
140
|
+
expect(matcher).toHaveBeenCalledWith(
|
|
141
|
+
"THE MOCK DESCRIPTION",
|
|
142
|
+
"any",
|
|
143
|
+
"arguments",
|
|
144
|
+
{
|
|
145
|
+
we: {want: 42},
|
|
146
|
+
},
|
|
147
|
+
);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("should match once", async () => {
|
|
151
|
+
// Arrange
|
|
152
|
+
const matcher = jest.fn().mockReturnValue(true);
|
|
153
|
+
const operationToString = jest.fn();
|
|
154
|
+
const mockFn = mockRequester(matcher, operationToString);
|
|
155
|
+
|
|
156
|
+
// Act
|
|
157
|
+
mockFn.mockOperationOnce(
|
|
158
|
+
"THE MOCK DESCRIPTION",
|
|
159
|
+
RespondWith.text("TADA!"),
|
|
160
|
+
);
|
|
161
|
+
const response = await mockFn("DO SOMETHING");
|
|
162
|
+
const result = response.text();
|
|
163
|
+
|
|
164
|
+
// Assert
|
|
165
|
+
await expect(result).resolves.toBe("TADA!");
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it("should only match once", async () => {
|
|
169
|
+
// Arrange
|
|
170
|
+
const matcher = jest.fn().mockReturnValue(true);
|
|
171
|
+
const operationToString = jest.fn();
|
|
172
|
+
const mockFn = mockRequester(matcher, operationToString);
|
|
173
|
+
|
|
174
|
+
// Act
|
|
175
|
+
mockFn.mockOperationOnce(
|
|
176
|
+
"THE MOCK DESCRIPTION",
|
|
177
|
+
RespondWith.text("TADA!"),
|
|
178
|
+
);
|
|
179
|
+
const result = Promise.all([
|
|
180
|
+
mockFn("DO SOMETHING"),
|
|
181
|
+
mockFn("DO SOMETHING"),
|
|
182
|
+
]);
|
|
183
|
+
|
|
184
|
+
// Assert
|
|
185
|
+
await expect(result).rejects.toThrowError();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("should skip mock if matcher returns false and try more mocks", async () => {
|
|
189
|
+
// Arrange
|
|
190
|
+
const matcher = jest
|
|
191
|
+
.fn()
|
|
192
|
+
.mockReturnValueOnce(false)
|
|
193
|
+
.mockReturnValueOnce(true);
|
|
194
|
+
const operationToString = jest.fn();
|
|
195
|
+
const mockFn = mockRequester(matcher, operationToString);
|
|
196
|
+
|
|
197
|
+
// Act
|
|
198
|
+
mockFn.mockOperationOnce(
|
|
199
|
+
"THE MOCK DESCRIPTION 1",
|
|
200
|
+
RespondWith.text("ONE"),
|
|
201
|
+
);
|
|
202
|
+
mockFn.mockOperationOnce(
|
|
203
|
+
"THE MOCK DESCRIPTION 2",
|
|
204
|
+
RespondWith.text("TWO"),
|
|
205
|
+
);
|
|
206
|
+
const response = await mockFn("DO SOMETHING");
|
|
207
|
+
const result = response.text();
|
|
208
|
+
|
|
209
|
+
// Assert
|
|
210
|
+
await expect(result).resolves.toBe("TWO");
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// flow
|
|
2
|
+
import * as wst from "@khanacademy/wonder-stuff-testing";
|
|
3
|
+
|
|
4
|
+
describe("ResponseImpl", () => {
|
|
5
|
+
const globalResponse = globalThis.Response;
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
if (globalResponse) {
|
|
9
|
+
delete globalThis.Response;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
if (globalResponse) {
|
|
15
|
+
globalThis.Response = globalResponse;
|
|
16
|
+
} else {
|
|
17
|
+
delete globalThis.Response;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("should use Response from node-fetch if Response does not exist", () => {
|
|
22
|
+
// Arrange
|
|
23
|
+
|
|
24
|
+
// Act
|
|
25
|
+
const {ResponseImpl: result, NodeFetchResponse} =
|
|
26
|
+
wst.jest.isolateModules(() => ({
|
|
27
|
+
ResponseImpl: require("../response-impl.js").ResponseImpl,
|
|
28
|
+
NodeFetchResponse: require("node-fetch").Response,
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
// Assert
|
|
32
|
+
expect(result).toBe(NodeFetchResponse);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("should return the existing Response type if it exists", () => {
|
|
36
|
+
// Arrange
|
|
37
|
+
globalThis.Response = class CustomResponse {};
|
|
38
|
+
|
|
39
|
+
// Act
|
|
40
|
+
const result = wst.jest.isolateModules(
|
|
41
|
+
() => require("../response-impl.js").ResponseImpl,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
// Assert
|
|
45
|
+
expect(result).toBe(globalThis.Response);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`#mockFetch should reject with a useful error when there are no matching mocks for %s 1`] = `
|
|
4
|
+
"No matching mock response found for request:
|
|
5
|
+
Input: http://example.com/foo
|
|
6
|
+
Options: None"
|
|
7
|
+
`;
|
|
8
|
+
|
|
9
|
+
exports[`#mockFetch should reject with a useful error when there are no matching mocks for %s 2`] = `
|
|
10
|
+
"No matching mock response found for request:
|
|
11
|
+
Input: \\"http://example.com/foo\\"
|
|
12
|
+
Options: {
|
|
13
|
+
\\"method\\": \\"GET\\"
|
|
14
|
+
}"
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
exports[`#mockFetch should reject with a useful error when there are no matching mocks for %s 3`] = `
|
|
18
|
+
"No matching mock response found for request:
|
|
19
|
+
Input: {
|
|
20
|
+
\\"size\\": 0,
|
|
21
|
+
\\"timeout\\": 0,
|
|
22
|
+
\\"follow\\": 20,
|
|
23
|
+
\\"compress\\": true,
|
|
24
|
+
\\"counter\\": 0
|
|
25
|
+
}
|
|
26
|
+
Options: {
|
|
27
|
+
\\"method\\": \\"POST\\"
|
|
28
|
+
}"
|
|
29
|
+
`;
|