@khanacademy/wonder-blocks-testing 2.0.8 → 4.0.0
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 +22 -0
- package/dist/es/index.js +255 -140
- package/dist/index.js +304 -145
- package/package.json +2 -1
- 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 +66 -22
- package/src/fixtures/adapters/__tests__/adapter-group.test.js +24 -0
- package/src/fixtures/adapters/__tests__/adapter.test.js +6 -0
- package/src/fixtures/adapters/storybook.js +4 -1
- package/src/fixtures/fixtures.basic.stories.js +1 -1
- package/src/fixtures/fixtures.defaultwrapper.stories.js +1 -1
- package/src/fixtures/fixtures.js +47 -3
- package/src/fixtures/types.js +10 -1
- 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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-testing
|
|
2
2
|
|
|
3
|
+
## 4.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- fce91b39: Introduced `mockFetch` and expanded `RespondWith` options. `RespondWith` responses will now be real `Response` instances (needs node-fetch peer dependency if no other implementation exists). Breaking changes: `RespondWith.data` is now `RespondWith.graphQLData`.
|
|
8
|
+
|
|
9
|
+
## 3.0.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 6e4fbeed: Make sure simplified fixtures call copes with return values from React.forwardRef
|
|
14
|
+
|
|
15
|
+
## 3.0.0
|
|
16
|
+
|
|
17
|
+
### Major Changes
|
|
18
|
+
|
|
19
|
+
- 9a43cc06: Allow for autogenerating titles in Storybook
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- 222cb8db: Add simplified signature for common usage of `fixtures` function
|
|
24
|
+
|
|
3
25
|
## 2.0.8
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
package/dist/es/index.js
CHANGED
|
@@ -118,7 +118,10 @@ class Adapter {
|
|
|
118
118
|
*/
|
|
119
119
|
const getAdapter = (MountingComponent = null) => new Adapter("storybook", ({
|
|
120
120
|
title,
|
|
121
|
-
description: groupDescription
|
|
121
|
+
description: groupDescription,
|
|
122
|
+
// We don't use the default title in Storybook as storybook
|
|
123
|
+
// will generate titles for us if we pass a nullish title.
|
|
124
|
+
getDefaultTitle: _
|
|
122
125
|
}, adapterOptions, declaredFixtures) => {
|
|
123
126
|
const templateMap = new WeakMap();
|
|
124
127
|
|
|
@@ -262,6 +265,38 @@ const combineOptions = (...toBeCombined) => {
|
|
|
262
265
|
return combined;
|
|
263
266
|
};
|
|
264
267
|
|
|
268
|
+
const normalizeOptions = componentOrOptions => {
|
|
269
|
+
// To differentiate between a React component and a FixturesOptions object,
|
|
270
|
+
// we have to do some type checking.
|
|
271
|
+
//
|
|
272
|
+
// Alternatives I considered were:
|
|
273
|
+
// - Use an additional parameter for the options and then do an arg number
|
|
274
|
+
// check, but that always makes typing a function harder and often breaks
|
|
275
|
+
// types. I didn't want that battle today.
|
|
276
|
+
// - Use a tuple when providing component and options with the first element
|
|
277
|
+
// being the component and the second being the options. However that
|
|
278
|
+
// feels like an obscure API even though it's really easy to do the
|
|
279
|
+
// typing.
|
|
280
|
+
if ( // Most React components, whether functional or class-based, are
|
|
281
|
+
// inherently functions in JavaScript, so a check for functions is
|
|
282
|
+
// usually sufficient.
|
|
283
|
+
typeof componentOrOptions === "function" || // However, the return of React.forwardRef is not a function,
|
|
284
|
+
// so we also have to cope with that.
|
|
285
|
+
// A forwardRef has $$typeof = Symbol(react.forward_ref) and a
|
|
286
|
+
// render function.
|
|
287
|
+
// $FlowIgnore[prop-missing]
|
|
288
|
+
typeof componentOrOptions.render === "function") {
|
|
289
|
+
return {
|
|
290
|
+
// $FlowIgnore[incompatible-return]
|
|
291
|
+
component: componentOrOptions
|
|
292
|
+
};
|
|
293
|
+
} // We can't test for React.ComponentType at runtime.
|
|
294
|
+
// Let's assume our simple heuristic above is sufficient.
|
|
295
|
+
// $FlowIgnore[incompatible-return]
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
return componentOrOptions;
|
|
299
|
+
};
|
|
265
300
|
/**
|
|
266
301
|
* Describe a group of fixtures for a given component.
|
|
267
302
|
*
|
|
@@ -280,7 +315,9 @@ const combineOptions = (...toBeCombined) => {
|
|
|
280
315
|
* storybook, the popular framework, uses both default and named exports for
|
|
281
316
|
* its interface.
|
|
282
317
|
*/
|
|
283
|
-
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
const fixtures = (componentOrOptions, fn) => {
|
|
284
321
|
var _additionalAdapterOpt;
|
|
285
322
|
|
|
286
323
|
const {
|
|
@@ -293,11 +330,12 @@ const fixtures = (options, fn) => {
|
|
|
293
330
|
description: groupDescription,
|
|
294
331
|
defaultWrapper,
|
|
295
332
|
additionalAdapterOptions
|
|
296
|
-
} =
|
|
333
|
+
} = normalizeOptions(componentOrOptions); // 1. Create a new adapter group.
|
|
297
334
|
|
|
298
335
|
const group = adapter.declareGroup({
|
|
299
|
-
title
|
|
300
|
-
description: groupDescription
|
|
336
|
+
title,
|
|
337
|
+
description: groupDescription,
|
|
338
|
+
getDefaultTitle: () => component.displayName || component.name || "Component"
|
|
301
339
|
}); // 2. Invoke fn with a function that can add a new fixture.
|
|
302
340
|
|
|
303
341
|
const addFixture = (description, props, wrapper = null) => {
|
|
@@ -319,6 +357,215 @@ const fixtures = (options, fn) => {
|
|
|
319
357
|
return group.closeGroup(combinedAdapterOptions);
|
|
320
358
|
};
|
|
321
359
|
|
|
360
|
+
// We need a version of Response. When we're in Jest JSDOM environment or a
|
|
361
|
+
// version of Node that supports the fetch API (17 and up, possibly with
|
|
362
|
+
// --experimental-fetch flag), then we're good, but otherwise we need an
|
|
363
|
+
// implementation, so this uses node-fetch as a peer dependency and uses that
|
|
364
|
+
// to provide the implementation if we don't already have one.
|
|
365
|
+
const ResponseImpl = typeof Response === "undefined" ? require("node-fetch").Response : Response;
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Helper for creating a text-based mock response.
|
|
369
|
+
*/
|
|
370
|
+
const textResponse = (text, statusCode = 200) => ({
|
|
371
|
+
type: "text",
|
|
372
|
+
text,
|
|
373
|
+
statusCode
|
|
374
|
+
});
|
|
375
|
+
/**
|
|
376
|
+
* Helper for creating a rejected mock response.
|
|
377
|
+
*/
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
const rejectResponse = error => ({
|
|
381
|
+
type: "reject",
|
|
382
|
+
error
|
|
383
|
+
});
|
|
384
|
+
/**
|
|
385
|
+
* Helpers to define mock responses for mocked requests.
|
|
386
|
+
*/
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
const RespondWith = Object.freeze({
|
|
390
|
+
/**
|
|
391
|
+
* Response with text body and status code.
|
|
392
|
+
* Status code defaults to 200.
|
|
393
|
+
*/
|
|
394
|
+
text: (text, statusCode = 200) => textResponse(text, statusCode),
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Response with JSON body and status code 200.
|
|
398
|
+
*/
|
|
399
|
+
json: json => textResponse(() => JSON.stringify(json)),
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Response with GraphQL data JSON body and status code 200.
|
|
403
|
+
*/
|
|
404
|
+
graphQLData: data => textResponse(() => JSON.stringify({
|
|
405
|
+
data
|
|
406
|
+
})),
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Response with body that will not parse as JSON and status code 200.
|
|
410
|
+
*/
|
|
411
|
+
unparseableBody: () => textResponse("INVALID JSON"),
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Rejects with an AbortError to simulate an aborted request.
|
|
415
|
+
*/
|
|
416
|
+
abortedRequest: () => rejectResponse(() => {
|
|
417
|
+
const abortError = new Error("Mock request aborted");
|
|
418
|
+
abortError.name = "AbortError";
|
|
419
|
+
return abortError;
|
|
420
|
+
}),
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Rejects with the given error.
|
|
424
|
+
*/
|
|
425
|
+
reject: error => rejectResponse(error),
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* A non-200 status code with empty text body.
|
|
429
|
+
* Equivalent to calling `ResponseWith.text("", statusCode)`.
|
|
430
|
+
*/
|
|
431
|
+
errorStatusCode: statusCode => {
|
|
432
|
+
if (statusCode < 300) {
|
|
433
|
+
throw new Error(`${statusCode} is not a valid error status code`);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
return textResponse("{}", statusCode);
|
|
437
|
+
},
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Response body that is valid JSON but not a valid GraphQL response.
|
|
441
|
+
*/
|
|
442
|
+
nonGraphQLBody: () => textResponse(() => JSON.stringify({
|
|
443
|
+
valid: "json",
|
|
444
|
+
that: "is not a valid graphql response"
|
|
445
|
+
})),
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Response that is a GraphQL errors response with status code 200.
|
|
449
|
+
*/
|
|
450
|
+
graphQLErrors: errorMessages => textResponse(() => JSON.stringify({
|
|
451
|
+
errors: errorMessages.map(e => ({
|
|
452
|
+
message: e
|
|
453
|
+
}))
|
|
454
|
+
}))
|
|
455
|
+
});
|
|
456
|
+
/**
|
|
457
|
+
* Turns a MockResponse value to an actual Response that represents the mock.
|
|
458
|
+
*/
|
|
459
|
+
|
|
460
|
+
const makeMockResponse = response => {
|
|
461
|
+
switch (response.type) {
|
|
462
|
+
case "text":
|
|
463
|
+
const text = typeof response.text === "function" ? response.text() : response.text;
|
|
464
|
+
return Promise.resolve(new ResponseImpl(text, {
|
|
465
|
+
status: response.statusCode
|
|
466
|
+
}));
|
|
467
|
+
|
|
468
|
+
case "reject":
|
|
469
|
+
const error = response.error instanceof Error ? response.error : response.error();
|
|
470
|
+
return Promise.reject(error);
|
|
471
|
+
|
|
472
|
+
default:
|
|
473
|
+
throw new Error(`Unknown response type: ${response.type}`);
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Get the URL from the given RequestInfo.
|
|
479
|
+
*
|
|
480
|
+
* Since we could be running in Node or in JSDOM, we don't check instance
|
|
481
|
+
* types, but just use a heuristic so that this works without knowing what
|
|
482
|
+
* was polyfilling things.
|
|
483
|
+
*/
|
|
484
|
+
const getHref = input => {
|
|
485
|
+
if (typeof input === "string") {
|
|
486
|
+
return input;
|
|
487
|
+
} else if (typeof input.url === "string") {
|
|
488
|
+
return input.url;
|
|
489
|
+
} else if (typeof input.href === "string") {
|
|
490
|
+
return input.href;
|
|
491
|
+
} else {
|
|
492
|
+
throw new Error(`Unsupported input type`);
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
/**
|
|
496
|
+
* Determines if a given fetch invocation matches the given mock.
|
|
497
|
+
*/
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
const fetchRequestMatchesMock = (mock, input, init) => {
|
|
501
|
+
// Currently, we only match on the input portion.
|
|
502
|
+
// This can be a Request, a URL, or a string.
|
|
503
|
+
const href = getHref(input); // Our mock operation is either a string for an exact match, or a regex.
|
|
504
|
+
|
|
505
|
+
if (typeof mock === "string") {
|
|
506
|
+
return href === mock;
|
|
507
|
+
} else if (mock instanceof RegExp) {
|
|
508
|
+
return mock.test(href);
|
|
509
|
+
} else {
|
|
510
|
+
throw new Error(`Unsupported mock operation: ${JSON.stringify(mock)}`);
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* A generic mock request function for using when mocking fetch or gqlFetch.
|
|
516
|
+
*/
|
|
517
|
+
const mockRequester = (operationMatcher, operationToString) => {
|
|
518
|
+
// We want this to work in jest and in fixtures to make life easy for folks.
|
|
519
|
+
// This is the array of mocked operations that we will traverse and
|
|
520
|
+
// manipulate.
|
|
521
|
+
const mocks = []; // What we return has to be a drop in for the fetch function that is
|
|
522
|
+
// provided to `GqlRouter` which is how folks will then use this mock.
|
|
523
|
+
|
|
524
|
+
const mockFn = (...args) => {
|
|
525
|
+
// Iterate our mocked operations and find the first one that matches.
|
|
526
|
+
for (const mock of mocks) {
|
|
527
|
+
if (mock.onceOnly && mock.used) {
|
|
528
|
+
// This is a once-only mock and it has been used, so skip it.
|
|
529
|
+
continue;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (operationMatcher.apply(void 0, [mock.operation].concat(args))) {
|
|
533
|
+
mock.used = true;
|
|
534
|
+
return mock.response();
|
|
535
|
+
}
|
|
536
|
+
} // Default is to reject with some helpful info on what request
|
|
537
|
+
// we rejected.
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
return Promise.reject(new Error(`No matching mock response found for request:
|
|
541
|
+
${operationToString.apply(void 0, args)}`));
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
const addMockedOperation = (operation, response, onceOnly) => {
|
|
545
|
+
const mockResponse = () => makeMockResponse(response);
|
|
546
|
+
|
|
547
|
+
mocks.push({
|
|
548
|
+
operation,
|
|
549
|
+
response: mockResponse,
|
|
550
|
+
onceOnly,
|
|
551
|
+
used: false
|
|
552
|
+
});
|
|
553
|
+
return mockFn;
|
|
554
|
+
};
|
|
555
|
+
|
|
556
|
+
mockFn.mockOperation = (operation, response) => addMockedOperation(operation, response, false);
|
|
557
|
+
|
|
558
|
+
mockFn.mockOperationOnce = (operation, response) => addMockedOperation(operation, response, true);
|
|
559
|
+
|
|
560
|
+
return mockFn;
|
|
561
|
+
};
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* A mock for the fetch function passed to GqlRouter.
|
|
565
|
+
*/
|
|
566
|
+
const mockFetch = () => mockRequester(fetchRequestMatchesMock, (input, init) => `Input: ${typeof input === "string" ? input : JSON.stringify(input, null, 2)}
|
|
567
|
+
Options: ${init == null ? "None" : JSON.stringify(init, null, 2)}`);
|
|
568
|
+
|
|
322
569
|
const safeHasOwnProperty = (obj, prop) => // Flow really shouldn't be raising this error here.
|
|
323
570
|
// $FlowFixMe[method-unbinding]
|
|
324
571
|
Object.prototype.hasOwnProperty.call(obj, prop); // TODO(somewhatabstract, FEI-4268): use a third-party library to do this and
|
|
@@ -388,143 +635,11 @@ const gqlRequestMatchesMock = (mock, operation, variables, context) => {
|
|
|
388
635
|
return true;
|
|
389
636
|
};
|
|
390
637
|
|
|
391
|
-
/**
|
|
392
|
-
* Helpers to define rejection states for mocking GQL requests.
|
|
393
|
-
*/
|
|
394
|
-
const RespondWith = Object.freeze({
|
|
395
|
-
data: data => ({
|
|
396
|
-
type: "data",
|
|
397
|
-
data
|
|
398
|
-
}),
|
|
399
|
-
unparseableBody: () => ({
|
|
400
|
-
type: "parse"
|
|
401
|
-
}),
|
|
402
|
-
abortedRequest: () => ({
|
|
403
|
-
type: "abort"
|
|
404
|
-
}),
|
|
405
|
-
errorStatusCode: statusCode => {
|
|
406
|
-
if (statusCode < 300) {
|
|
407
|
-
throw new Error(`${statusCode} is not a valid error status code`);
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
return {
|
|
411
|
-
type: "status",
|
|
412
|
-
statusCode
|
|
413
|
-
};
|
|
414
|
-
},
|
|
415
|
-
nonGraphQLBody: () => ({
|
|
416
|
-
type: "invalid"
|
|
417
|
-
}),
|
|
418
|
-
graphQLErrors: errorMessages => ({
|
|
419
|
-
type: "graphql",
|
|
420
|
-
errors: errorMessages
|
|
421
|
-
})
|
|
422
|
-
});
|
|
423
|
-
/**
|
|
424
|
-
* Turns an ErrorResponse value in an actual Response that will invoke
|
|
425
|
-
* that error.
|
|
426
|
-
*/
|
|
427
|
-
|
|
428
|
-
const makeGqlMockResponse = response => {
|
|
429
|
-
switch (response.type) {
|
|
430
|
-
case "data":
|
|
431
|
-
return Promise.resolve({
|
|
432
|
-
status: 200,
|
|
433
|
-
text: () => Promise.resolve(JSON.stringify({
|
|
434
|
-
data: response.data
|
|
435
|
-
}))
|
|
436
|
-
});
|
|
437
|
-
|
|
438
|
-
case "parse":
|
|
439
|
-
return Promise.resolve({
|
|
440
|
-
status: 200,
|
|
441
|
-
text: () => Promise.resolve("INVALID JSON")
|
|
442
|
-
});
|
|
443
|
-
|
|
444
|
-
case "abort":
|
|
445
|
-
const abortError = new Error("Mock request aborted");
|
|
446
|
-
abortError.name = "AbortError";
|
|
447
|
-
return Promise.reject(abortError);
|
|
448
|
-
|
|
449
|
-
case "status":
|
|
450
|
-
return Promise.resolve({
|
|
451
|
-
status: response.statusCode,
|
|
452
|
-
text: () => Promise.resolve(JSON.stringify({}))
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
case "invalid":
|
|
456
|
-
return Promise.resolve({
|
|
457
|
-
status: 200,
|
|
458
|
-
text: () => Promise.resolve(JSON.stringify({
|
|
459
|
-
valid: "json",
|
|
460
|
-
that: "is not a valid graphql response"
|
|
461
|
-
}))
|
|
462
|
-
});
|
|
463
|
-
|
|
464
|
-
case "graphql":
|
|
465
|
-
return Promise.resolve({
|
|
466
|
-
status: 200,
|
|
467
|
-
text: () => Promise.resolve(JSON.stringify({
|
|
468
|
-
errors: response.errors.map(e => ({
|
|
469
|
-
message: e
|
|
470
|
-
}))
|
|
471
|
-
}))
|
|
472
|
-
});
|
|
473
|
-
|
|
474
|
-
default:
|
|
475
|
-
throw new Error(`Unknown response type: ${response.type}`);
|
|
476
|
-
}
|
|
477
|
-
};
|
|
478
|
-
|
|
479
638
|
/**
|
|
480
639
|
* A mock for the fetch function passed to GqlRouter.
|
|
481
640
|
*/
|
|
482
|
-
const mockGqlFetch = () => {
|
|
483
|
-
// We want this to work in jest and in fixtures to make life easy for folks.
|
|
484
|
-
// This is the array of mocked operations that we will traverse and
|
|
485
|
-
// manipulate.
|
|
486
|
-
const mocks = []; // What we return has to be a drop in for the fetch function that is
|
|
487
|
-
// provided to `GqlRouter` which is how folks will then use this mock.
|
|
488
|
-
|
|
489
|
-
const gqlFetchMock = (operation, variables, context) => {
|
|
490
|
-
// Iterate our mocked operations and find the first one that matches.
|
|
491
|
-
for (const mock of mocks) {
|
|
492
|
-
if (mock.onceOnly && mock.used) {
|
|
493
|
-
// This is a once-only mock and it has been used, so skip it.
|
|
494
|
-
continue;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
if (gqlRequestMatchesMock(mock.operation, operation, variables, context)) {
|
|
498
|
-
mock.used = true;
|
|
499
|
-
return mock.response();
|
|
500
|
-
}
|
|
501
|
-
} // Default is to reject with some helpful info on what request
|
|
502
|
-
// we rejected.
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
return Promise.reject(new Error(`No matching GraphQL mock response found for request:
|
|
506
|
-
Operation: ${operation.type} ${operation.id}
|
|
641
|
+
const mockGqlFetch = () => mockRequester(gqlRequestMatchesMock, (operation, variables, context) => `Operation: ${operation.type} ${operation.id}
|
|
507
642
|
Variables: ${variables == null ? "None" : JSON.stringify(variables, null, 2)}
|
|
508
|
-
Context: ${JSON.stringify(context, null, 2)}`)
|
|
509
|
-
};
|
|
510
|
-
|
|
511
|
-
const addMockedOperation = (operation, response, onceOnly) => {
|
|
512
|
-
const mockResponse = () => makeGqlMockResponse(response);
|
|
513
|
-
|
|
514
|
-
mocks.push({
|
|
515
|
-
operation,
|
|
516
|
-
response: mockResponse,
|
|
517
|
-
onceOnly,
|
|
518
|
-
used: false
|
|
519
|
-
});
|
|
520
|
-
return gqlFetchMock;
|
|
521
|
-
};
|
|
522
|
-
|
|
523
|
-
gqlFetchMock.mockOperation = (operation, response) => addMockedOperation(operation, response, false);
|
|
524
|
-
|
|
525
|
-
gqlFetchMock.mockOperationOnce = (operation, response) => addMockedOperation(operation, response, true);
|
|
526
|
-
|
|
527
|
-
return gqlFetchMock;
|
|
528
|
-
};
|
|
643
|
+
Context: ${JSON.stringify(context, null, 2)}`);
|
|
529
644
|
|
|
530
|
-
export { RespondWith, adapters, fixtures, mockGqlFetch, setup as setupFixtures };
|
|
645
|
+
export { RespondWith, adapters, fixtures, mockFetch, mockGqlFetch, setup as setupFixtures };
|