@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.
Files changed (31) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/es/index.js +255 -140
  3. package/dist/index.js +304 -145
  4. package/package.json +2 -1
  5. package/src/{gql/__tests__/make-gql-mock-response.test.js → __tests__/make-mock-response.test.js} +196 -34
  6. package/src/__tests__/mock-requester.test.js +213 -0
  7. package/src/__tests__/response-impl.test.js +47 -0
  8. package/src/fetch/__tests__/__snapshots__/mock-fetch.test.js.snap +29 -0
  9. package/src/fetch/__tests__/fetch-request-matches-mock.test.js +99 -0
  10. package/src/fetch/__tests__/mock-fetch.test.js +84 -0
  11. package/src/fetch/fetch-request-matches-mock.js +43 -0
  12. package/src/fetch/mock-fetch.js +19 -0
  13. package/src/fetch/types.js +18 -0
  14. package/src/fixtures/__tests__/fixtures.test.js +66 -22
  15. package/src/fixtures/adapters/__tests__/adapter-group.test.js +24 -0
  16. package/src/fixtures/adapters/__tests__/adapter.test.js +6 -0
  17. package/src/fixtures/adapters/storybook.js +4 -1
  18. package/src/fixtures/fixtures.basic.stories.js +1 -1
  19. package/src/fixtures/fixtures.defaultwrapper.stories.js +1 -1
  20. package/src/fixtures/fixtures.js +47 -3
  21. package/src/fixtures/types.js +10 -1
  22. package/src/gql/__tests__/mock-gql-fetch.test.js +24 -15
  23. package/src/gql/__tests__/wb-data-integration.test.js +7 -4
  24. package/src/gql/mock-gql-fetch.js +9 -80
  25. package/src/gql/types.js +11 -10
  26. package/src/index.js +9 -3
  27. package/src/make-mock-response.js +150 -0
  28. package/src/mock-requester.js +75 -0
  29. package/src/response-impl.js +9 -0
  30. package/src/types.js +39 -0
  31. package/src/gql/make-gql-mock-response.js +0 -124
@@ -3,7 +3,7 @@ import * as React from "react";
3
3
  import {render, screen, waitFor} from "@testing-library/react";
4
4
 
5
5
  import {GqlRouter, useGql} from "@khanacademy/wonder-blocks-data";
6
- import {RespondWith} from "../make-gql-mock-response.js";
6
+ import {RespondWith} from "../../make-mock-response.js";
7
7
  import {mockGqlFetch} from "../mock-gql-fetch.js";
8
8
 
9
9
  describe("#mockGqlFetch", () => {
@@ -37,7 +37,7 @@ describe("#mockGqlFetch", () => {
37
37
  // Assert
38
38
  await waitFor(() =>
39
39
  expect(result).toHaveTextContent(
40
- "No matching GraphQL mock response found for request",
40
+ "No matching mock response found for request",
41
41
  ),
42
42
  );
43
43
  });
@@ -65,7 +65,10 @@ describe("#mockGqlFetch", () => {
65
65
  };
66
66
 
67
67
  // Act
68
- mockFetch.mockOperation({operation: query}, RespondWith.data(data));
68
+ mockFetch.mockOperation(
69
+ {operation: query},
70
+ RespondWith.graphQLData(data),
71
+ );
69
72
  render(
70
73
  <GqlRouter defaultContext={{}} fetch={mockFetch}>
71
74
  <RenderData />
@@ -171,7 +174,7 @@ describe("#mockGqlFetch", () => {
171
174
 
172
175
  // Assert
173
176
  await expect(result).rejects.toThrowErrorMatchingInlineSnapshot(`
174
- "No matching GraphQL mock response found for request:
177
+ "No matching mock response found for request:
175
178
  Operation: query getMyStuff
176
179
  Variables: {
177
180
  \\"a\\": \\"variable\\"
@@ -195,7 +198,7 @@ describe("#mockGqlFetch", () => {
195
198
  };
196
199
 
197
200
  // Act
198
- mockFetch.mockOperation({operation}, RespondWith.data(data));
201
+ mockFetch.mockOperation({operation}, RespondWith.graphQLData(data));
199
202
  const result = mockFetch(
200
203
  operation,
201
204
  {a: "variable"},
@@ -218,7 +221,7 @@ describe("#mockGqlFetch", () => {
218
221
  };
219
222
 
220
223
  // Act
221
- mockFetch.mockOperation({operation}, RespondWith.data(data));
224
+ mockFetch.mockOperation({operation}, RespondWith.graphQLData(data));
222
225
  const result = mockFetch(
223
226
  {type: "mutation", id: "putMyStuff"},
224
227
  {a: "variable"},
@@ -246,7 +249,7 @@ describe("#mockGqlFetch", () => {
246
249
  // Act
247
250
  mockFetch.mockOperation(
248
251
  {operation, variables},
249
- RespondWith.data(data),
252
+ RespondWith.graphQLData(data),
250
253
  );
251
254
  const result = mockFetch(operation, variables, {my: "context"});
252
255
 
@@ -271,7 +274,7 @@ describe("#mockGqlFetch", () => {
271
274
  // Act
272
275
  mockFetch.mockOperation(
273
276
  {operation, variables},
274
- RespondWith.data(data),
277
+ RespondWith.graphQLData(data),
275
278
  );
276
279
  const result = mockFetch(
277
280
  operation,
@@ -300,7 +303,7 @@ describe("#mockGqlFetch", () => {
300
303
  // Act
301
304
  mockFetch.mockOperation(
302
305
  {operation, context},
303
- RespondWith.data(data),
306
+ RespondWith.graphQLData(data),
304
307
  );
305
308
  const result = mockFetch(operation, {a: "variable"}, context);
306
309
 
@@ -325,7 +328,7 @@ describe("#mockGqlFetch", () => {
325
328
  // Act
326
329
  mockFetch.mockOperation(
327
330
  {operation, context},
328
- RespondWith.data(data),
331
+ RespondWith.graphQLData(data),
329
332
  );
330
333
  const result = mockFetch(
331
334
  operation,
@@ -357,7 +360,7 @@ describe("#mockGqlFetch", () => {
357
360
  // Act
358
361
  mockFetch.mockOperation(
359
362
  {operation, variables, context},
360
- RespondWith.data(data),
363
+ RespondWith.graphQLData(data),
361
364
  );
362
365
  const result = mockFetch(operation, variables, context);
363
366
 
@@ -385,7 +388,7 @@ describe("#mockGqlFetch", () => {
385
388
  // Act
386
389
  mockFetch.mockOperation(
387
390
  {operation, variables, context},
388
- RespondWith.data(data),
391
+ RespondWith.graphQLData(data),
389
392
  );
390
393
  const response = await mockFetch(operation, variables, context);
391
394
  const result = await response.text();
@@ -406,7 +409,7 @@ describe("#mockGqlFetch", () => {
406
409
  };
407
410
 
408
411
  // Act
409
- mockFetch.mockOperation({operation}, RespondWith.data(data));
412
+ mockFetch.mockOperation({operation}, RespondWith.graphQLData(data));
410
413
  const result = Promise.all([
411
414
  mockFetch(operation, {a: "variable"}, {my: "context"}),
412
415
  mockFetch(operation, {b: "variable"}, {another: "context"}),
@@ -433,7 +436,10 @@ describe("#mockGqlFetch", () => {
433
436
  };
434
437
 
435
438
  // Act
436
- mockFetch.mockOperationOnce({operation}, RespondWith.data(data));
439
+ mockFetch.mockOperationOnce(
440
+ {operation},
441
+ RespondWith.graphQLData(data),
442
+ );
437
443
  const result = mockFetch(
438
444
  operation,
439
445
  {a: "variable"},
@@ -456,7 +462,10 @@ describe("#mockGqlFetch", () => {
456
462
  };
457
463
 
458
464
  // Act
459
- mockFetch.mockOperationOnce({operation}, RespondWith.data(data));
465
+ mockFetch.mockOperationOnce(
466
+ {operation},
467
+ RespondWith.graphQLData(data),
468
+ );
460
469
  const result = Promise.all([
461
470
  mockFetch(operation, {a: "variable"}, {my: "context"}),
462
471
  mockFetch(operation, {b: "variable"}, {another: "context"}),
@@ -3,7 +3,7 @@ import * as React from "react";
3
3
  import {render, screen, waitFor} from "@testing-library/react";
4
4
 
5
5
  import {GqlRouter, useGql} from "@khanacademy/wonder-blocks-data";
6
- import {RespondWith} from "../make-gql-mock-response.js";
6
+ import {RespondWith} from "../../make-mock-response.js";
7
7
  import {mockGqlFetch} from "../mock-gql-fetch.js";
8
8
 
9
9
  describe("integrating mockGqlFetch, RespondWith, GqlRouter and useGql", () => {
@@ -36,12 +36,12 @@ describe("integrating mockGqlFetch, RespondWith, GqlRouter and useGql", () => {
36
36
  // Assert
37
37
  await waitFor(() =>
38
38
  expect(result).toHaveTextContent(
39
- "No matching GraphQL mock response found for request",
39
+ "No matching mock response found for request",
40
40
  ),
41
41
  );
42
42
  });
43
43
 
44
- it("should resolve with data for RespondWith.data", async () => {
44
+ it("should resolve with data for RespondWith.graphQLData", async () => {
45
45
  // Arrange
46
46
  const mockFetch = mockGqlFetch();
47
47
  const query = {
@@ -64,7 +64,10 @@ describe("integrating mockGqlFetch, RespondWith, GqlRouter and useGql", () => {
64
64
  };
65
65
 
66
66
  // Act
67
- mockFetch.mockOperation({operation: query}, RespondWith.data(data));
67
+ mockFetch.mockOperation(
68
+ {operation: query},
69
+ RespondWith.graphQLData(data),
70
+ );
68
71
  render(
69
72
  <GqlRouter defaultContext={{}} fetch={mockFetch}>
70
73
  <RenderData />
@@ -1,89 +1,18 @@
1
1
  // @flow
2
- import type {GqlContext} from "@khanacademy/wonder-blocks-data";
3
2
  import {gqlRequestMatchesMock} from "./gql-request-matches-mock.js";
4
- import {makeGqlMockResponse} from "./make-gql-mock-response.js";
5
- import type {GqlMockResponse} from "./make-gql-mock-response.js";
6
- import type {GqlMock, GqlMockOperation, GqlFetchMockFn} from "./types.js";
3
+ import {mockRequester} from "../mock-requester.js";
4
+ import type {GqlFetchMockFn, GqlMockOperation} from "./types.js";
7
5
 
8
6
  /**
9
7
  * A mock for the fetch function passed to GqlRouter.
10
8
  */
11
- export const mockGqlFetch = (): GqlFetchMockFn => {
12
- // We want this to work in jest and in fixtures to make life easy for folks.
13
- // This is the array of mocked operations that we will traverse and
14
- // manipulate.
15
- const mocks: Array<GqlMock> = [];
16
-
17
- // What we return has to be a drop in for the fetch function that is
18
- // provided to `GqlRouter` which is how folks will then use this mock.
19
- const gqlFetchMock: GqlFetchMockFn = (
20
- operation,
21
- variables,
22
- context,
23
- ): Promise<Response> => {
24
- // Iterate our mocked operations and find the first one that matches.
25
- for (const mock of mocks) {
26
- if (mock.onceOnly && mock.used) {
27
- // This is a once-only mock and it has been used, so skip it.
28
- continue;
29
- }
30
- if (
31
- gqlRequestMatchesMock(
32
- mock.operation,
33
- operation,
34
- variables,
35
- context,
36
- )
37
- ) {
38
- mock.used = true;
39
- return mock.response();
40
- }
41
- }
42
-
43
- // Default is to reject with some helpful info on what request
44
- // we rejected.
45
- return Promise.reject(
46
- new Error(`No matching GraphQL mock response found for request:
47
- Operation: ${operation.type} ${operation.id}
9
+ export const mockGqlFetch = (): GqlFetchMockFn =>
10
+ mockRequester<GqlMockOperation<any, any, any>, _>(
11
+ gqlRequestMatchesMock,
12
+ (operation, variables, context) =>
13
+ `Operation: ${operation.type} ${operation.id}
48
14
  Variables: ${
49
15
  variables == null ? "None" : JSON.stringify(variables, null, 2)
50
16
  }
51
- Context: ${JSON.stringify(context, null, 2)}`),
52
- );
53
- };
54
-
55
- const addMockedOperation = <TData, TVariables: {...}, TContext: GqlContext>(
56
- operation: GqlMockOperation<TData, TVariables, TContext>,
57
- response: GqlMockResponse<TData>,
58
- onceOnly: boolean,
59
- ): GqlFetchMockFn => {
60
- const mockResponse = () => makeGqlMockResponse(response);
61
- mocks.push({
62
- operation,
63
- response: mockResponse,
64
- onceOnly,
65
- used: false,
66
- });
67
- return gqlFetchMock;
68
- };
69
-
70
- gqlFetchMock.mockOperation = <
71
- TData,
72
- TVariables: {...},
73
- TContext: GqlContext,
74
- >(
75
- operation: GqlMockOperation<TData, TVariables, TContext>,
76
- response: GqlMockResponse<TData>,
77
- ): GqlFetchMockFn => addMockedOperation(operation, response, false);
78
-
79
- gqlFetchMock.mockOperationOnce = <
80
- TData,
81
- TVariables: {...},
82
- TContext: GqlContext,
83
- >(
84
- operation: GqlMockOperation<TData, TVariables, TContext>,
85
- response: GqlMockResponse<TData>,
86
- ): GqlFetchMockFn => addMockedOperation(operation, response, true);
87
-
88
- return gqlFetchMock;
89
- };
17
+ Context: ${JSON.stringify(context, null, 2)}`,
18
+ );
package/src/gql/types.js CHANGED
@@ -1,9 +1,10 @@
1
1
  //@flow
2
2
  import type {GqlOperation, GqlContext} from "@khanacademy/wonder-blocks-data";
3
- import type {GqlMockResponse} from "./make-gql-mock-response.js";
3
+ import type {OperationMock, GraphQLJson} from "../types.js";
4
+ import type {MockResponse} from "../make-mock-response.js";
4
5
 
5
6
  export type GqlMockOperation<
6
- TData,
7
+ TData: {...},
7
8
  TVariables: {...},
8
9
  TContext: GqlContext,
9
10
  > = {|
@@ -12,9 +13,14 @@ export type GqlMockOperation<
12
13
  context?: TContext,
13
14
  |};
14
15
 
15
- type GqlMockOperationFn = <TData, TVariables: {...}, TContext: GqlContext>(
16
+ type GqlMockOperationFn = <
17
+ TData: {...},
18
+ TVariables: {...},
19
+ TContext: GqlContext,
20
+ TResponseData: GraphQLJson<TData>,
21
+ >(
16
22
  operation: GqlMockOperation<TData, TVariables, TContext>,
17
- response: GqlMockResponse<TData>,
23
+ response: MockResponse<TResponseData>,
18
24
  ) => GqlFetchMockFn;
19
25
 
20
26
  export type GqlFetchMockFn = {|
@@ -27,9 +33,4 @@ export type GqlFetchMockFn = {|
27
33
  mockOperationOnce: GqlMockOperationFn,
28
34
  |};
29
35
 
30
- export type GqlMock = {|
31
- operation: GqlMockOperation<any, any, any>,
32
- onceOnly: boolean,
33
- used: boolean,
34
- response: () => Promise<Response>,
35
- |};
36
+ export type GqlMock = OperationMock<GqlMockOperation<any, any, any>>;
package/src/index.js CHANGED
@@ -17,8 +17,14 @@ export type {
17
17
  FixturesOptions,
18
18
  } from "./fixtures/types.js";
19
19
 
20
- // GraphQL framework
20
+ // Fetch mocking framework
21
+ export type {MockResponse} from "./make-mock-response.js";
22
+ export {RespondWith} from "./make-mock-response.js";
23
+ export {mockFetch} from "./fetch/mock-fetch.js";
24
+ export type {
25
+ FetchMockFn,
26
+ FetchMock,
27
+ FetchMockOperation,
28
+ } from "./fetch/types.js";
21
29
  export {mockGqlFetch} from "./gql/mock-gql-fetch.js";
22
- export type {GqlMockResponse} from "./gql/make-gql-mock-response.js";
23
- export {RespondWith} from "./gql/make-gql-mock-response.js";
24
30
  export type {GqlFetchMockFn, GqlMock, GqlMockOperation} from "./gql/types.js";
@@ -0,0 +1,150 @@
1
+ // @flow
2
+ import {ResponseImpl} from "./response-impl.js";
3
+ import type {GraphQLJson} from "./types.js";
4
+
5
+ /**
6
+ * Describes a mock response to a fetch request.
7
+ */
8
+ export opaque type MockResponse<TJson> =
9
+ | {|
10
+ type: "text",
11
+ text: string | (() => string),
12
+ statusCode: number,
13
+ |}
14
+ | {|
15
+ type: "reject",
16
+ error: Error | (() => Error),
17
+ |};
18
+
19
+ /**
20
+ * Helper for creating a text-based mock response.
21
+ */
22
+ const textResponse = <TData>(
23
+ text: string | (() => string),
24
+ statusCode: number = 200,
25
+ ): MockResponse<TData> => ({
26
+ type: "text",
27
+ text,
28
+ statusCode,
29
+ });
30
+
31
+ /**
32
+ * Helper for creating a rejected mock response.
33
+ */
34
+ const rejectResponse = (error: Error | (() => Error)): MockResponse<empty> => ({
35
+ type: "reject",
36
+ error,
37
+ });
38
+
39
+ /**
40
+ * Helpers to define mock responses for mocked requests.
41
+ */
42
+ export const RespondWith = Object.freeze({
43
+ /**
44
+ * Response with text body and status code.
45
+ * Status code defaults to 200.
46
+ */
47
+ text: <TData = string>(
48
+ text: string,
49
+ statusCode: number = 200,
50
+ ): MockResponse<TData> => textResponse<TData>(text, statusCode),
51
+
52
+ /**
53
+ * Response with JSON body and status code 200.
54
+ */
55
+ json: <TJson: {...}>(json: TJson): MockResponse<TJson> =>
56
+ textResponse<TJson>(() => JSON.stringify(json)),
57
+
58
+ /**
59
+ * Response with GraphQL data JSON body and status code 200.
60
+ */
61
+ graphQLData: <TData: {...}>(
62
+ data: TData,
63
+ ): MockResponse<GraphQLJson<TData>> =>
64
+ textResponse<GraphQLJson<TData>>(() => JSON.stringify({data})),
65
+
66
+ /**
67
+ * Response with body that will not parse as JSON and status code 200.
68
+ */
69
+ unparseableBody: (): MockResponse<any> => textResponse("INVALID JSON"),
70
+
71
+ /**
72
+ * Rejects with an AbortError to simulate an aborted request.
73
+ */
74
+ abortedRequest: (): MockResponse<any> =>
75
+ rejectResponse(() => {
76
+ const abortError = new Error("Mock request aborted");
77
+ abortError.name = "AbortError";
78
+ return abortError;
79
+ }),
80
+
81
+ /**
82
+ * Rejects with the given error.
83
+ */
84
+ reject: (error: Error): MockResponse<any> => rejectResponse(error),
85
+
86
+ /**
87
+ * A non-200 status code with empty text body.
88
+ * Equivalent to calling `ResponseWith.text("", statusCode)`.
89
+ */
90
+ errorStatusCode: (statusCode: number): MockResponse<any> => {
91
+ if (statusCode < 300) {
92
+ throw new Error(`${statusCode} is not a valid error status code`);
93
+ }
94
+ return textResponse("{}", statusCode);
95
+ },
96
+
97
+ /**
98
+ * Response body that is valid JSON but not a valid GraphQL response.
99
+ */
100
+ nonGraphQLBody: (): MockResponse<any> =>
101
+ textResponse(() =>
102
+ JSON.stringify({
103
+ valid: "json",
104
+ that: "is not a valid graphql response",
105
+ }),
106
+ ),
107
+
108
+ /**
109
+ * Response that is a GraphQL errors response with status code 200.
110
+ */
111
+ graphQLErrors: (
112
+ errorMessages: $ReadOnlyArray<string>,
113
+ ): MockResponse<GraphQLJson<any>> =>
114
+ textResponse<GraphQLJson<any>>(() =>
115
+ JSON.stringify({
116
+ errors: errorMessages.map((e) => ({
117
+ message: e,
118
+ })),
119
+ }),
120
+ ),
121
+ });
122
+
123
+ /**
124
+ * Turns a MockResponse value to an actual Response that represents the mock.
125
+ */
126
+ export const makeMockResponse = (
127
+ response: MockResponse<any>,
128
+ ): Promise<Response> => {
129
+ switch (response.type) {
130
+ case "text":
131
+ const text =
132
+ typeof response.text === "function"
133
+ ? response.text()
134
+ : response.text;
135
+
136
+ return Promise.resolve(
137
+ new ResponseImpl(text, {status: response.statusCode}),
138
+ );
139
+
140
+ case "reject":
141
+ const error =
142
+ response.error instanceof Error
143
+ ? response.error
144
+ : response.error();
145
+ return Promise.reject(error);
146
+
147
+ default:
148
+ throw new Error(`Unknown response type: ${response.type}`);
149
+ }
150
+ };
@@ -0,0 +1,75 @@
1
+ // @flow
2
+ import {makeMockResponse} from "./make-mock-response.js";
3
+ import type {MockResponse} from "./make-mock-response.js";
4
+ import type {OperationMock, OperationMatcher, MockFn} from "./types.js";
5
+
6
+ /**
7
+ * A generic mock request function for using when mocking fetch or gqlFetch.
8
+ */
9
+ export const mockRequester = <
10
+ TOperationType,
11
+ TOperationMock: OperationMock<TOperationType>,
12
+ >(
13
+ operationMatcher: OperationMatcher<any>,
14
+ operationToString: (
15
+ operationMock: TOperationMock,
16
+ ...args: Array<any>
17
+ ) => string,
18
+ ): MockFn<TOperationType> => {
19
+ // We want this to work in jest and in fixtures to make life easy for folks.
20
+ // This is the array of mocked operations that we will traverse and
21
+ // manipulate.
22
+ const mocks: Array<OperationMock<any>> = [];
23
+
24
+ // What we return has to be a drop in for the fetch function that is
25
+ // provided to `GqlRouter` which is how folks will then use this mock.
26
+ const mockFn: MockFn<TOperationType> = (
27
+ ...args: Array<any>
28
+ ): Promise<Response> => {
29
+ // Iterate our mocked operations and find the first one that matches.
30
+ for (const mock of mocks) {
31
+ if (mock.onceOnly && mock.used) {
32
+ // This is a once-only mock and it has been used, so skip it.
33
+ continue;
34
+ }
35
+ if (operationMatcher(mock.operation, ...args)) {
36
+ mock.used = true;
37
+ return mock.response();
38
+ }
39
+ }
40
+
41
+ // Default is to reject with some helpful info on what request
42
+ // we rejected.
43
+ return Promise.reject(
44
+ new Error(`No matching mock response found for request:
45
+ ${operationToString(...args)}`),
46
+ );
47
+ };
48
+
49
+ const addMockedOperation = <TOperation>(
50
+ operation: TOperation,
51
+ response: MockResponse<any>,
52
+ onceOnly: boolean,
53
+ ): MockFn<TOperationType> => {
54
+ const mockResponse = () => makeMockResponse(response);
55
+ mocks.push({
56
+ operation,
57
+ response: mockResponse,
58
+ onceOnly,
59
+ used: false,
60
+ });
61
+ return mockFn;
62
+ };
63
+
64
+ mockFn.mockOperation = <TOperation>(
65
+ operation: TOperation,
66
+ response: MockResponse<any>,
67
+ ): MockFn<TOperationType> => addMockedOperation(operation, response, false);
68
+
69
+ mockFn.mockOperationOnce = <TOperation>(
70
+ operation: TOperation,
71
+ response: MockResponse<any>,
72
+ ): MockFn<TOperationType> => addMockedOperation(operation, response, true);
73
+
74
+ return mockFn;
75
+ };
@@ -0,0 +1,9 @@
1
+ // @flow
2
+
3
+ // We need a version of Response. When we're in Jest JSDOM environment or a
4
+ // version of Node that supports the fetch API (17 and up, possibly with
5
+ // --experimental-fetch flag), then we're good, but otherwise we need an
6
+ // implementation, so this uses node-fetch as a peer dependency and uses that
7
+ // to provide the implementation if we don't already have one.
8
+ export const ResponseImpl: typeof Response =
9
+ typeof Response === "undefined" ? require("node-fetch").Response : Response;
package/src/types.js ADDED
@@ -0,0 +1,39 @@
1
+ // @flow
2
+ import type {MockResponse} from "./make-mock-response.js";
3
+
4
+ /**
5
+ * A valid GraphQL response as supported by our mocking framework.
6
+ * Note that we don't currently support both data and errors being set.
7
+ */
8
+ export type GraphQLJson<TData: {...}> =
9
+ | {|
10
+ data: TData,
11
+ |}
12
+ | {|
13
+ errors: Array<{|
14
+ message: string,
15
+ |}>,
16
+ |};
17
+
18
+ export type MockFn<TOperationType> = {|
19
+ (...args: Array<any>): Promise<Response>,
20
+ mockOperation: MockOperationFn<TOperationType>,
21
+ mockOperationOnce: MockOperationFn<TOperationType>,
22
+ |};
23
+
24
+ export type OperationMock<TOperation> = {|
25
+ operation: TOperation,
26
+ onceOnly: boolean,
27
+ used: boolean,
28
+ response: () => Promise<Response>,
29
+ |};
30
+
31
+ export type OperationMatcher<TOperation> = (
32
+ operation: TOperation,
33
+ ...args: Array<any>
34
+ ) => boolean;
35
+
36
+ export type MockOperationFn<TOperationType> = <TOperation: TOperationType>(
37
+ operation: TOperation,
38
+ response: MockResponse<any>,
39
+ ) => MockFn<TOperationType>;