@khanacademy/wonder-blocks-testing 7.1.10 → 7.1.12
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 +31 -0
- package/dist/es/index.js +183 -120
- package/dist/fetch/fetch-request-matches-mock.d.ts +5 -0
- package/dist/fetch/fetch-request-matches-mock.js.flow +17 -0
- package/dist/fetch/mock-fetch.d.ts +5 -0
- package/dist/fetch/mock-fetch.js.flow +13 -0
- package/dist/fetch/types.d.ts +9 -0
- package/dist/fetch/types.js.flow +19 -0
- package/dist/fixtures/fixtures.basic.stories.d.ts +13 -0
- package/dist/fixtures/fixtures.basic.stories.js.flow +22 -0
- package/dist/fixtures/fixtures.d.ts +19 -0
- package/dist/fixtures/fixtures.defaultwrapper.stories.d.ts +9 -0
- package/dist/fixtures/fixtures.defaultwrapper.stories.js.flow +17 -0
- package/dist/fixtures/fixtures.js.flow +33 -0
- package/dist/fixtures/types.d.ts +36 -0
- package/dist/fixtures/types.js.flow +37 -0
- package/dist/gql/gql-request-matches-mock.d.ts +3 -0
- package/dist/gql/gql-request-matches-mock.js.flow +15 -0
- package/dist/gql/mock-gql-fetch.d.ts +5 -0
- package/dist/gql/mock-gql-fetch.js.flow +13 -0
- package/dist/gql/types.d.ts +15 -0
- package/dist/gql/types.js.flow +39 -0
- package/dist/harness/adapters/adapters.d.ts +35 -0
- package/dist/harness/adapters/adapters.js.flow +69 -0
- package/dist/harness/adapters/css.d.ts +12 -0
- package/dist/harness/adapters/css.js.flow +23 -0
- package/dist/harness/adapters/data.d.ts +18 -0
- package/dist/harness/adapters/data.js.flow +32 -0
- package/dist/harness/adapters/portal.d.ts +12 -0
- package/dist/harness/adapters/portal.js.flow +18 -0
- package/dist/harness/adapters/router.d.ts +94 -0
- package/dist/harness/adapters/router.js.flow +122 -0
- package/dist/harness/hook-harness.d.ts +13 -0
- package/dist/harness/hook-harness.js.flow +23 -0
- package/dist/harness/make-hook-harness.d.ts +17 -0
- package/dist/harness/make-hook-harness.js.flow +42 -0
- package/dist/harness/make-test-harness.d.ts +18 -0
- package/dist/harness/make-test-harness.js.flow +48 -0
- package/dist/harness/render-adapters.d.ts +6 -0
- package/dist/harness/render-adapters.js.flow +24 -0
- package/dist/harness/test-harness.d.ts +32 -0
- package/dist/harness/test-harness.js.flow +83 -0
- package/dist/harness/types.d.ts +46 -0
- package/dist/harness/types.js.flow +66 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +185 -127
- package/dist/index.js.flow +26 -2
- package/dist/mock-requester.d.ts +5 -0
- package/dist/mock-requester.js.flow +22 -0
- package/dist/respond-with.d.ts +57 -0
- package/dist/respond-with.js.flow +91 -0
- package/dist/response-impl.d.ts +1 -0
- package/dist/response-impl.js.flow +8 -0
- package/dist/settle-controller.d.ts +19 -0
- package/dist/settle-controller.js.flow +26 -0
- package/dist/settle-signal.d.ts +18 -0
- package/dist/settle-signal.js.flow +26 -0
- package/dist/types.d.ts +25 -0
- package/dist/types.js.flow +46 -0
- package/package.json +6 -6
- package/src/__tests__/{mock-requester.test.js → mock-requester.test.ts} +1 -2
- package/src/__tests__/{respond-with.test.js → respond-with.test.ts} +0 -1
- package/src/__tests__/response-impl.test.js +1 -1
- package/src/__tests__/{settle-controller.test.js → settle-controller.test.ts} +0 -1
- package/src/__tests__/{settle-signal.test.js → settle-signal.test.ts} +0 -1
- package/src/fetch/__tests__/__snapshots__/{mock-fetch.test.js.snap → mock-fetch.test.ts.snap} +3 -3
- package/src/fetch/__tests__/{fetch-request-matches-mock.test.js → fetch-request-matches-mock.test.ts} +5 -6
- package/src/fetch/__tests__/{mock-fetch.test.js → mock-fetch.test.ts} +1 -2
- package/src/fetch/{fetch-request-matches-mock.js → fetch-request-matches-mock.ts} +3 -2
- package/src/fetch/{mock-fetch.js → mock-fetch.ts} +2 -3
- package/src/fetch/{types.js → types.ts} +5 -6
- package/src/fixtures/__tests__/{fixtures.test.js → fixtures.test.tsx} +6 -4
- package/src/fixtures/{fixtures.basic.stories.js → fixtures.basic.stories.tsx} +16 -13
- package/src/fixtures/{fixtures.defaultwrapper.stories.js → fixtures.defaultwrapper.stories.tsx} +8 -8
- package/src/fixtures/{fixtures.js → fixtures.tsx} +16 -11
- package/src/fixtures/{types.js → types.ts} +9 -13
- package/src/gql/__tests__/{gql-request-matches-mock.test.js → gql-request-matches-mock.test.ts} +17 -18
- package/src/gql/__tests__/{mock-gql-fetch.test.js → mock-gql-fetch.test.tsx} +44 -45
- package/src/gql/__tests__/{wb-data-integration.test.js → wb-data-integration.test.tsx} +21 -22
- package/src/gql/{gql-request-matches-mock.js → gql-request-matches-mock.ts} +1 -4
- package/src/gql/{mock-gql-fetch.js → mock-gql-fetch.ts} +3 -6
- package/src/gql/types.ts +33 -0
- package/src/harness/__tests__/{hook-harness.test.js → hook-harness.test.ts} +5 -6
- package/src/harness/__tests__/{make-hook-harness.test.js → make-hook-harness.test.tsx} +10 -11
- package/src/harness/__tests__/{make-test-harness.test.js → make-test-harness.test.tsx} +4 -5
- package/src/harness/__tests__/{render-adapters.test.js → render-adapters.test.tsx} +8 -9
- package/src/harness/__tests__/{test-harness.test.js → test-harness.test.ts} +5 -6
- package/src/harness/__tests__/{types.flowtest.js → types.flowtest.tsx} +24 -27
- package/src/harness/adapters/__tests__/{css.test.js → css.test.tsx} +2 -3
- package/src/harness/adapters/__tests__/{data.test.js → data.test.tsx} +4 -3
- package/src/harness/adapters/__tests__/{portal.test.js → portal.test.tsx} +0 -1
- package/src/harness/adapters/__tests__/{router.test.js → router.test.tsx} +75 -56
- package/src/harness/adapters/{adapters.js → adapters.ts} +1 -2
- package/src/harness/adapters/{css.js → css.tsx} +21 -18
- package/src/harness/adapters/{data.js → data.tsx} +7 -5
- package/src/harness/adapters/{portal.js → portal.tsx} +3 -4
- package/src/harness/adapters/router.tsx +218 -0
- package/src/harness/{hook-harness.js → hook-harness.ts} +2 -3
- package/src/harness/{make-hook-harness.js → make-hook-harness.ts} +6 -6
- package/src/harness/{make-test-harness.js → make-test-harness.tsx} +17 -20
- package/src/harness/{render-adapters.js → render-adapters.ts} +4 -4
- package/src/harness/{test-harness.js → test-harness.ts} +1 -12
- package/src/harness/{types.js → types.ts} +14 -12
- package/src/{index.js → index.ts} +0 -2
- package/src/{mock-requester.js → mock-requester.ts} +4 -3
- package/src/{respond-with.js → respond-with.ts} +42 -37
- package/src/{response-impl.js → response-impl.ts} +1 -2
- package/src/{settle-controller.js → settle-controller.ts} +9 -7
- package/src/{settle-signal.js → settle-signal.ts} +10 -7
- package/src/types.ts +40 -0
- package/tsconfig.json +11 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/src/__docs__/_overview_.stories.mdx +0 -18
- package/src/__docs__/_overview_fixtures.stories.mdx +0 -18
- package/src/__docs__/_overview_mocking.stories.mdx +0 -14
- package/src/__docs__/_overview_test_harness.stories.mdx +0 -18
- package/src/__docs__/exports.fixtures.stories.mdx +0 -31
- package/src/__docs__/exports.harness-adapters.stories.mdx +0 -187
- package/src/__docs__/exports.hook-harness.stories.mdx +0 -22
- package/src/__docs__/exports.make-hook-harness.stories.mdx +0 -25
- package/src/__docs__/exports.make-test-harness.stories.mdx +0 -28
- package/src/__docs__/exports.mock-fetch.stories.mdx +0 -40
- package/src/__docs__/exports.mock-gql-fetch.stories.mdx +0 -64
- package/src/__docs__/exports.respond-with.stories.mdx +0 -84
- package/src/__docs__/exports.settle-controller.stories.mdx +0 -32
- package/src/__docs__/exports.test-harness.stories.mdx +0 -23
- package/src/__docs__/types.fetch-mock-fn.stories.mdx +0 -22
- package/src/__docs__/types.fetch-mock-operation.stories.mdx +0 -18
- package/src/__docs__/types.fixture-fn.stories.mdx +0 -46
- package/src/__docs__/types.fixture-props.stories.mdx +0 -20
- package/src/__docs__/types.get-props-options.stories.mdx +0 -52
- package/src/__docs__/types.gql-fetch-mock-fn.stories.mdx +0 -27
- package/src/__docs__/types.gql-mock-operation.stories.mdx +0 -26
- package/src/__docs__/types.mock-response.stories.mdx +0 -22
- package/src/__docs__/types.test-harness-adapter.stories.mdx +0 -21
- package/src/__docs__/types.test-harness-adapters.stories.mdx +0 -46
- package/src/__docs__/types.test-harness-config.stories.mdx +0 -18
- package/src/__docs__/types.test-harness-configs.stories.mdx +0 -59
- package/src/gql/types.js +0 -34
- package/src/harness/adapters/router.js +0 -206
- package/src/types.js +0 -39
- /package/src/harness/adapters/__tests__/__snapshots__/{router.test.js.snap → router.test.tsx.snap} +0 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { SettleSignal } from "./settle-signal";
|
|
2
|
+
import type { GraphQLJson } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Describes a mock response to a fetch request.
|
|
5
|
+
*/
|
|
6
|
+
export type MockResponse<TData> = {
|
|
7
|
+
/**
|
|
8
|
+
* Create a promise from the mocked response.
|
|
9
|
+
*
|
|
10
|
+
* If a signal was provided when the mock response was created, the promise
|
|
11
|
+
* will only settle to resolution or rejection if the signal is raised.
|
|
12
|
+
*/
|
|
13
|
+
readonly toPromise: () => Promise<Response>;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Helpers to define mock responses for mocked requests.
|
|
17
|
+
*/
|
|
18
|
+
export declare const RespondWith: Readonly<{
|
|
19
|
+
/**
|
|
20
|
+
* Response with text body and status code.
|
|
21
|
+
* Status code defaults to 200.
|
|
22
|
+
*/
|
|
23
|
+
text: <TData = string>(text: string, statusCode?: number, signal?: SettleSignal | null) => MockResponse<TData>;
|
|
24
|
+
/**
|
|
25
|
+
* Response with JSON body and status code 200.
|
|
26
|
+
*/
|
|
27
|
+
json: <TJson extends Record<any, any>>(json: TJson, signal?: SettleSignal | null) => MockResponse<TJson>;
|
|
28
|
+
/**
|
|
29
|
+
* Response with GraphQL data JSON body and status code 200.
|
|
30
|
+
*/
|
|
31
|
+
graphQLData: <TData_1 extends Record<any, any>>(data: TData_1, signal?: SettleSignal | null) => MockResponse<GraphQLJson<TData_1>>;
|
|
32
|
+
/**
|
|
33
|
+
* Response with body that will not parse as JSON and status code 200.
|
|
34
|
+
*/
|
|
35
|
+
unparseableBody: (signal?: SettleSignal | null) => MockResponse<any>;
|
|
36
|
+
/**
|
|
37
|
+
* Rejects with an AbortError to simulate an aborted request.
|
|
38
|
+
*/
|
|
39
|
+
abortedRequest: (signal?: SettleSignal | null) => MockResponse<any>;
|
|
40
|
+
/**
|
|
41
|
+
* Rejects with the given error.
|
|
42
|
+
*/
|
|
43
|
+
reject: (error: Error, signal?: SettleSignal | null) => MockResponse<any>;
|
|
44
|
+
/**
|
|
45
|
+
* A non-200 status code with empty text body.
|
|
46
|
+
* Equivalent to calling `ResponseWith.text("", statusCode)`.
|
|
47
|
+
*/
|
|
48
|
+
errorStatusCode: (statusCode: number, signal?: SettleSignal | null) => MockResponse<any>;
|
|
49
|
+
/**
|
|
50
|
+
* Response body that is valid JSON but not a valid GraphQL response.
|
|
51
|
+
*/
|
|
52
|
+
nonGraphQLBody: (signal?: SettleSignal | null) => MockResponse<any>;
|
|
53
|
+
/**
|
|
54
|
+
* Response that is a GraphQL errors response with status code 200.
|
|
55
|
+
*/
|
|
56
|
+
graphQLErrors: (errorMessages: ReadonlyArray<string>, signal?: SettleSignal | null) => MockResponse<GraphQLJson<any>>;
|
|
57
|
+
}>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flowtype definitions for respond-with
|
|
3
|
+
* Generated by Flowgen from a Typescript Definition
|
|
4
|
+
* Flowgen v1.21.0
|
|
5
|
+
* @flow
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { SettleSignal } from "./settle-signal";
|
|
9
|
+
import type { GraphQLJson } from "./types";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Describes a mock response to a fetch request.
|
|
13
|
+
*/
|
|
14
|
+
export type MockResponse<TData> = {
|
|
15
|
+
/**
|
|
16
|
+
* Create a promise from the mocked response.
|
|
17
|
+
*
|
|
18
|
+
* If a signal was provided when the mock response was created, the promise
|
|
19
|
+
* will only settle to resolution or rejection if the signal is raised.
|
|
20
|
+
*/
|
|
21
|
+
+toPromise: () => Promise<Response>,
|
|
22
|
+
...
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Helpers to define mock responses for mocked requests.
|
|
26
|
+
*/
|
|
27
|
+
declare export var RespondWith: $ReadOnly<{
|
|
28
|
+
/**
|
|
29
|
+
* Response with text body and status code.
|
|
30
|
+
* Status code defaults to 200.
|
|
31
|
+
*/
|
|
32
|
+
text: <TData>(
|
|
33
|
+
text: string,
|
|
34
|
+
statusCode?: number,
|
|
35
|
+
signal?: SettleSignal | null
|
|
36
|
+
) => MockResponse<TData>,
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Response with JSON body and status code 200.
|
|
40
|
+
*/
|
|
41
|
+
json: <TJson: { [key: any]: any, ... }>(
|
|
42
|
+
json: TJson,
|
|
43
|
+
signal?: SettleSignal | null
|
|
44
|
+
) => MockResponse<TJson>,
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Response with GraphQL data JSON body and status code 200.
|
|
48
|
+
*/
|
|
49
|
+
graphQLData: <TData_1: { [key: any]: any, ... }>(
|
|
50
|
+
data: TData_1,
|
|
51
|
+
signal?: SettleSignal | null
|
|
52
|
+
) => MockResponse<GraphQLJson<TData_1>>,
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Response with body that will not parse as JSON and status code 200.
|
|
56
|
+
*/
|
|
57
|
+
unparseableBody: (signal?: SettleSignal | null) => MockResponse<any>,
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Rejects with an AbortError to simulate an aborted request.
|
|
61
|
+
*/
|
|
62
|
+
abortedRequest: (signal?: SettleSignal | null) => MockResponse<any>,
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Rejects with the given error.
|
|
66
|
+
*/
|
|
67
|
+
reject: (error: Error, signal?: SettleSignal | null) => MockResponse<any>,
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* A non-200 status code with empty text body.
|
|
71
|
+
* Equivalent to calling `ResponseWith.text("", statusCode)`.
|
|
72
|
+
*/
|
|
73
|
+
errorStatusCode: (
|
|
74
|
+
statusCode: number,
|
|
75
|
+
signal?: SettleSignal | null
|
|
76
|
+
) => MockResponse<any>,
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Response body that is valid JSON but not a valid GraphQL response.
|
|
80
|
+
*/
|
|
81
|
+
nonGraphQLBody: (signal?: SettleSignal | null) => MockResponse<any>,
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Response that is a GraphQL errors response with status code 200.
|
|
85
|
+
*/
|
|
86
|
+
graphQLErrors: (
|
|
87
|
+
errorMessages: $ReadOnlyArray<string>,
|
|
88
|
+
signal?: SettleSignal | null
|
|
89
|
+
) => MockResponse<GraphQLJson<any>>,
|
|
90
|
+
...
|
|
91
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const ResponseImpl: typeof Response;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SettleSignal } from "./settle-signal";
|
|
2
|
+
/**
|
|
3
|
+
* A controller for the `RespondWith` API to control response settlement.
|
|
4
|
+
*/
|
|
5
|
+
export declare class SettleController {
|
|
6
|
+
private _settleFn;
|
|
7
|
+
private _signal;
|
|
8
|
+
constructor();
|
|
9
|
+
/**
|
|
10
|
+
* The signal to pass to the `RespondWith` API.
|
|
11
|
+
*/
|
|
12
|
+
get signal(): SettleSignal;
|
|
13
|
+
/**
|
|
14
|
+
* Settle the signal and therefore any associated responses.
|
|
15
|
+
*
|
|
16
|
+
* @throws {Error} if the signal has already been settled.
|
|
17
|
+
*/
|
|
18
|
+
settle(): void;
|
|
19
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flowtype definitions for settle-controller
|
|
3
|
+
* Generated by Flowgen from a Typescript Definition
|
|
4
|
+
* Flowgen v1.21.0
|
|
5
|
+
* @flow
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { SettleSignal } from "./settle-signal";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A controller for the `RespondWith` API to control response settlement.
|
|
12
|
+
*/
|
|
13
|
+
declare export class SettleController {
|
|
14
|
+
constructor(): this;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The signal to pass to the `RespondWith` API.
|
|
18
|
+
*/
|
|
19
|
+
signal: SettleSignal;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Settle the signal and therefore any associated responses.
|
|
23
|
+
* @throws {Error} if the signal has already been settled.
|
|
24
|
+
*/
|
|
25
|
+
settle(): void;
|
|
26
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A signal for controlling the `RespondWith` API responses.
|
|
3
|
+
*
|
|
4
|
+
* This provide finely-grained control over the promise lifecycle to support
|
|
5
|
+
* complex test scenarios.
|
|
6
|
+
*/
|
|
7
|
+
export declare class SettleSignal extends EventTarget {
|
|
8
|
+
private _settled;
|
|
9
|
+
constructor(setSettleFn?: ((settleFn: () => void) => unknown) | null);
|
|
10
|
+
/**
|
|
11
|
+
* An already settled signal.
|
|
12
|
+
*/
|
|
13
|
+
static settle(): SettleSignal;
|
|
14
|
+
/**
|
|
15
|
+
* Has this signal been settled yet?
|
|
16
|
+
*/
|
|
17
|
+
get settled(): boolean;
|
|
18
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flowtype definitions for settle-signal
|
|
3
|
+
* Generated by Flowgen from a Typescript Definition
|
|
4
|
+
* Flowgen v1.21.0
|
|
5
|
+
* @flow
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A signal for controlling the `RespondWith` API responses.
|
|
10
|
+
*
|
|
11
|
+
* This provide finely-grained control over the promise lifecycle to support
|
|
12
|
+
* complex test scenarios.
|
|
13
|
+
*/
|
|
14
|
+
declare export class SettleSignal implements EventTarget {
|
|
15
|
+
constructor(setSettleFn?: ((settleFn: () => void) => mixed) | null): this;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* An already settled signal.
|
|
19
|
+
*/
|
|
20
|
+
static settle(): SettleSignal;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Has this signal been settled yet?
|
|
24
|
+
*/
|
|
25
|
+
settled: boolean;
|
|
26
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { MockResponse } from "./respond-with";
|
|
2
|
+
/**
|
|
3
|
+
* A valid GraphQL response as supported by our mocking framework.
|
|
4
|
+
* Note that we don't currently support both data and errors being set.
|
|
5
|
+
*/
|
|
6
|
+
export type GraphQLJson<TData extends Record<any, any>> = {
|
|
7
|
+
data: TData;
|
|
8
|
+
} | {
|
|
9
|
+
errors: Array<{
|
|
10
|
+
message: string;
|
|
11
|
+
}>;
|
|
12
|
+
};
|
|
13
|
+
export type MockFn<TOperationType> = {
|
|
14
|
+
(...args: Array<any>): Promise<Response>;
|
|
15
|
+
mockOperation: MockOperationFn<TOperationType>;
|
|
16
|
+
mockOperationOnce: MockOperationFn<TOperationType>;
|
|
17
|
+
};
|
|
18
|
+
export type OperationMock<TOperation> = {
|
|
19
|
+
operation: TOperation;
|
|
20
|
+
onceOnly: boolean;
|
|
21
|
+
used: boolean;
|
|
22
|
+
response: () => Promise<Response>;
|
|
23
|
+
};
|
|
24
|
+
export type OperationMatcher<TOperation> = (operation: TOperation, ...args: Array<any>) => boolean;
|
|
25
|
+
export type MockOperationFn<TOperationType> = <TOperation extends TOperationType>(operation: TOperation, response: MockResponse<any>) => MockFn<TOperationType>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flowtype definitions for types
|
|
3
|
+
* Generated by Flowgen from a Typescript Definition
|
|
4
|
+
* Flowgen v1.21.0
|
|
5
|
+
* @flow
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { MockResponse } from "./respond-with";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A valid GraphQL response as supported by our mocking framework.
|
|
12
|
+
* Note that we don't currently support both data and errors being set.
|
|
13
|
+
*/
|
|
14
|
+
export type GraphQLJson<TData: { [key: any]: any, ... }> =
|
|
15
|
+
| {
|
|
16
|
+
data: TData,
|
|
17
|
+
...
|
|
18
|
+
}
|
|
19
|
+
| {
|
|
20
|
+
errors: Array<{
|
|
21
|
+
message: string,
|
|
22
|
+
...
|
|
23
|
+
}>,
|
|
24
|
+
...
|
|
25
|
+
};
|
|
26
|
+
export type MockFn<TOperationType> = {
|
|
27
|
+
(...args: Array<any>): Promise<Response>,
|
|
28
|
+
mockOperation: MockOperationFn<TOperationType>,
|
|
29
|
+
mockOperationOnce: MockOperationFn<TOperationType>,
|
|
30
|
+
...
|
|
31
|
+
};
|
|
32
|
+
export type OperationMock<TOperation> = {
|
|
33
|
+
operation: TOperation,
|
|
34
|
+
onceOnly: boolean,
|
|
35
|
+
used: boolean,
|
|
36
|
+
response: () => Promise<Response>,
|
|
37
|
+
...
|
|
38
|
+
};
|
|
39
|
+
export type OperationMatcher<TOperation> = (
|
|
40
|
+
operation: TOperation,
|
|
41
|
+
...args: Array<any>
|
|
42
|
+
) => boolean;
|
|
43
|
+
export type MockOperationFn<TOperationType> = <TOperation: TOperationType>(
|
|
44
|
+
operation: TOperation,
|
|
45
|
+
response: MockResponse<any>
|
|
46
|
+
) => MockFn<TOperationType>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanacademy/wonder-blocks-testing",
|
|
3
|
-
"version": "7.1.
|
|
3
|
+
"version": "7.1.12",
|
|
4
4
|
"design": "v1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -8,17 +8,17 @@
|
|
|
8
8
|
"description": "",
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"module": "dist/es/index.js",
|
|
11
|
-
"
|
|
11
|
+
"types": "dist/index.d.ts",
|
|
12
12
|
"scripts": {
|
|
13
13
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@babel/runtime": "^7.18.6",
|
|
17
|
-
"@khanacademy/wonder-blocks-data": "^10.1.
|
|
17
|
+
"@khanacademy/wonder-blocks-data": "^10.1.2"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
|
-
"@khanacademy/wonder-stuff-core": "^1.2.
|
|
21
|
-
"@khanacademy/wonder-stuff-testing": "^2.3.
|
|
20
|
+
"@khanacademy/wonder-stuff-core": "^1.2.2",
|
|
21
|
+
"@khanacademy/wonder-stuff-testing": "^2.3.3",
|
|
22
22
|
"@storybook/addon-actions": "^6.4.8",
|
|
23
23
|
"node-fetch": "^2.6.7",
|
|
24
24
|
"aphrodite": "^1.2.5",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"react-router-dom": "5.3.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"wb-dev-build-settings": "^0.7.
|
|
29
|
+
"wb-dev-build-settings": "^0.7.3"
|
|
30
30
|
},
|
|
31
31
|
"author": "",
|
|
32
32
|
"license": "MIT"
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {RespondWith} from "../respond-with";
|
|
3
2
|
import {mockRequester} from "../mock-requester";
|
|
4
3
|
|
|
@@ -40,7 +39,7 @@ describe("#mockRequester", () => {
|
|
|
40
39
|
// Arrange
|
|
41
40
|
const mockFn = mockRequester(
|
|
42
41
|
jest.fn(),
|
|
43
|
-
(...args) => `TEST FORMATTING: ${JSON.stringify(args)}`,
|
|
42
|
+
(...args: any) => `TEST FORMATTING: ${JSON.stringify(args)}`,
|
|
44
43
|
);
|
|
45
44
|
|
|
46
45
|
// Act
|
package/src/fetch/__tests__/__snapshots__/{mock-fetch.test.js.snap → mock-fetch.test.ts.snap}
RENAMED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
exports[`#mockFetch should reject with a useful error when there are no matching mocks for %s 1`] = `
|
|
4
4
|
"No matching mock response found for request:
|
|
5
5
|
Input: http://example.com/foo
|
|
6
|
-
|
|
6
|
+
Options: None"
|
|
7
7
|
`;
|
|
8
8
|
|
|
9
9
|
exports[`#mockFetch should reject with a useful error when there are no matching mocks for %s 2`] = `
|
|
10
10
|
"No matching mock response found for request:
|
|
11
11
|
Input: "http://example.com/foo"
|
|
12
|
-
|
|
12
|
+
Options: {
|
|
13
13
|
"method": "GET"
|
|
14
14
|
}"
|
|
15
15
|
`;
|
|
@@ -23,7 +23,7 @@ exports[`#mockFetch should reject with a useful error when there are no matching
|
|
|
23
23
|
"compress": true,
|
|
24
24
|
"counter": 0
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
Options: {
|
|
27
27
|
"method": "POST"
|
|
28
28
|
}"
|
|
29
29
|
`;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {Request} from "node-fetch";
|
|
3
2
|
import {fetchRequestMatchesMock} from "../fetch-request-matches-mock";
|
|
4
3
|
|
|
@@ -12,11 +11,11 @@ describe("#fetchRequestMatchesMock", () => {
|
|
|
12
11
|
id: "foo",
|
|
13
12
|
type: "query",
|
|
14
13
|
},
|
|
15
|
-
};
|
|
14
|
+
} as const;
|
|
16
15
|
|
|
17
16
|
// Act
|
|
18
17
|
const underTest = () =>
|
|
19
|
-
fetchRequestMatchesMock(
|
|
18
|
+
fetchRequestMatchesMock(mock as any, TEST_URL, null);
|
|
20
19
|
|
|
21
20
|
// Assert
|
|
22
21
|
expect(underTest).toThrowErrorMatchingInlineSnapshot(
|
|
@@ -32,7 +31,7 @@ describe("#fetchRequestMatchesMock", () => {
|
|
|
32
31
|
const underTest = () =>
|
|
33
32
|
fetchRequestMatchesMock(
|
|
34
33
|
mock,
|
|
35
|
-
|
|
34
|
+
{not: "a valid request"} as any,
|
|
36
35
|
null,
|
|
37
36
|
);
|
|
38
37
|
|
|
@@ -44,7 +43,7 @@ describe("#fetchRequestMatchesMock", () => {
|
|
|
44
43
|
|
|
45
44
|
describe.each([TEST_URL, new URL(TEST_URL), new Request(TEST_URL)])(
|
|
46
45
|
"for valid inputs",
|
|
47
|
-
(input) => {
|
|
46
|
+
(input: any) => {
|
|
48
47
|
it("should return false if mock is a string and it does not match the fetched URL", () => {
|
|
49
48
|
// Arrange
|
|
50
49
|
const mock = "http://example.com/bar";
|
|
@@ -84,7 +83,7 @@ describe("#fetchRequestMatchesMock", () => {
|
|
|
84
83
|
/^.*#fragment$/,
|
|
85
84
|
])(
|
|
86
85
|
"should return true if the mock is a %s and matches the fetched URL",
|
|
87
|
-
(regex) => {
|
|
86
|
+
(regex: any) => {
|
|
88
87
|
// Arrange
|
|
89
88
|
|
|
90
89
|
// Act
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {Request} from "node-fetch";
|
|
3
2
|
import {RespondWith} from "../../respond-with";
|
|
4
3
|
import {mockFetch} from "../mock-fetch";
|
|
@@ -11,7 +10,7 @@ describe("#mockFetch", () => {
|
|
|
11
10
|
${new Request("http://example.com/foo")} | ${{method: "POST"}}
|
|
12
11
|
`(
|
|
13
12
|
"should reject with a useful error when there are no matching mocks for %s",
|
|
14
|
-
async ({input, init}) => {
|
|
13
|
+
async ({input, init}: any) => {
|
|
15
14
|
// Arrange
|
|
16
15
|
const mockFn = mockFetch();
|
|
17
16
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import type {FetchMockOperation} from "./types";
|
|
3
2
|
|
|
4
3
|
/**
|
|
@@ -13,7 +12,9 @@ const getHref = (input: RequestInfo): string => {
|
|
|
13
12
|
return input;
|
|
14
13
|
} else if (typeof input.url === "string") {
|
|
15
14
|
return input.url;
|
|
15
|
+
// @ts-expect-error [FEI-5019] - TS2339 - Property 'href' does not exist on type 'Request'.
|
|
16
16
|
} else if (typeof input.href === "string") {
|
|
17
|
+
// @ts-expect-error [FEI-5019] - TS2339 - Property 'href' does not exist on type 'Request'.
|
|
17
18
|
return input.href;
|
|
18
19
|
} else {
|
|
19
20
|
throw new Error(`Unsupported input type`);
|
|
@@ -26,7 +27,7 @@ const getHref = (input: RequestInfo): string => {
|
|
|
26
27
|
export const fetchRequestMatchesMock = (
|
|
27
28
|
mock: FetchMockOperation,
|
|
28
29
|
input: RequestInfo,
|
|
29
|
-
init
|
|
30
|
+
init?: RequestInit | null,
|
|
30
31
|
): boolean => {
|
|
31
32
|
// Currently, we only match on the input portion.
|
|
32
33
|
// This can be a Request, a URL, or a string.
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {fetchRequestMatchesMock} from "./fetch-request-matches-mock";
|
|
3
2
|
import {mockRequester} from "../mock-requester";
|
|
4
3
|
import type {FetchMockFn, FetchMockOperation} from "./types";
|
|
@@ -7,7 +6,7 @@ import type {FetchMockFn, FetchMockOperation} from "./types";
|
|
|
7
6
|
* A mock for the fetch function passed to GqlRouter.
|
|
8
7
|
*/
|
|
9
8
|
export const mockFetch = (): FetchMockFn =>
|
|
10
|
-
mockRequester<FetchMockOperation,
|
|
9
|
+
mockRequester<FetchMockOperation, any>(
|
|
11
10
|
fetchRequestMatchesMock,
|
|
12
11
|
(input, init) =>
|
|
13
12
|
`Input: ${
|
|
@@ -15,5 +14,5 @@ export const mockFetch = (): FetchMockFn =>
|
|
|
15
14
|
? input
|
|
16
15
|
: JSON.stringify(input, null, 2)
|
|
17
16
|
}
|
|
18
|
-
|
|
17
|
+
Options: ${init == null ? "None" : JSON.stringify(init, null, 2)}`,
|
|
19
18
|
);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//@flow
|
|
2
1
|
import type {MockResponse} from "../respond-with";
|
|
3
2
|
|
|
4
3
|
export type FetchMockOperation = RegExp | string;
|
|
@@ -8,8 +7,8 @@ type FetchMockOperationFn = (
|
|
|
8
7
|
response: MockResponse<any>,
|
|
9
8
|
) => FetchMockFn;
|
|
10
9
|
|
|
11
|
-
export type FetchMockFn = {
|
|
12
|
-
(input: RequestInfo, init?:
|
|
13
|
-
mockOperation: FetchMockOperationFn
|
|
14
|
-
mockOperationOnce: FetchMockOperationFn
|
|
15
|
-
|
|
10
|
+
export type FetchMockFn = {
|
|
11
|
+
(input: RequestInfo, init?: RequestInit): Promise<Response>;
|
|
12
|
+
mockOperation: FetchMockOperationFn;
|
|
13
|
+
mockOperationOnce: FetchMockOperationFn;
|
|
14
|
+
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
import {render, screen} from "@testing-library/react";
|
|
4
3
|
import * as AddonActionsModule from "@storybook/addon-actions";
|
|
@@ -93,7 +92,7 @@ describe("fixtures", () => {
|
|
|
93
92
|
const props = {
|
|
94
93
|
this: "isAProp",
|
|
95
94
|
andSo: "isThis",
|
|
96
|
-
};
|
|
95
|
+
} as const;
|
|
97
96
|
|
|
98
97
|
// Act
|
|
99
98
|
const result = fixture("A simple story", props);
|
|
@@ -116,7 +115,8 @@ describe("fixtures", () => {
|
|
|
116
115
|
it("should render the component", () => {
|
|
117
116
|
// Arrange
|
|
118
117
|
const fixture = fixtures(
|
|
119
|
-
(props) =>
|
|
118
|
+
// @ts-expect-error [FEI-5019] - TS2345 - Argument of type '(props: any) => string' is not assignable to parameter of type 'ComponentType<any>'.
|
|
119
|
+
(props: any) => `I rendered ${JSON.stringify(props)}`,
|
|
120
120
|
);
|
|
121
121
|
const Fixture: any = fixture("A simple story", {});
|
|
122
122
|
|
|
@@ -132,11 +132,13 @@ describe("fixtures", () => {
|
|
|
132
132
|
it("should render the wrapper", () => {
|
|
133
133
|
// Arrange
|
|
134
134
|
const fixture = fixtures(
|
|
135
|
-
(props) =>
|
|
135
|
+
// @ts-expect-error [FEI-5019] - TS2345 - Argument of type '(props: any) => string' is not assignable to parameter of type 'ComponentType<any>'.
|
|
136
|
+
(props: any) => `I rendered ${JSON.stringify(props)}`,
|
|
136
137
|
);
|
|
137
138
|
const Fixture: any = fixture(
|
|
138
139
|
"A simple story",
|
|
139
140
|
{},
|
|
141
|
+
// @ts-expect-error [FEI-5019] - TS2345 - Argument of type '() => string' is not assignable to parameter of type 'ComponentType<any> | undefined'.
|
|
140
142
|
() => "I am a wrapper",
|
|
141
143
|
);
|
|
142
144
|
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
|
|
4
3
|
import {fixtures} from "../index";
|
|
5
4
|
|
|
6
|
-
type Props = {
|
|
7
|
-
propA: string
|
|
8
|
-
propB?: string
|
|
9
|
-
|
|
5
|
+
type Props = {
|
|
6
|
+
propA: string;
|
|
7
|
+
propB?: string;
|
|
8
|
+
};
|
|
10
9
|
|
|
11
|
-
const MyComponent = (props
|
|
10
|
+
const MyComponent: React.FC<Props> = (props): React.ReactElement =>
|
|
11
|
+
// @ts-expect-error: `string` is not a valid `ReactElement`.
|
|
12
12
|
`I am a component. Here are my props: ${JSON.stringify(props, null, 2)}`;
|
|
13
13
|
|
|
14
|
-
const Wrapper = (props) => (
|
|
14
|
+
const Wrapper = (props: any) => (
|
|
15
15
|
<>
|
|
16
16
|
Wrapper >>>
|
|
17
17
|
<MyComponent {...props} />
|
|
@@ -21,12 +21,15 @@ const Wrapper = (props) => (
|
|
|
21
21
|
|
|
22
22
|
const fixture = fixtures(MyComponent);
|
|
23
23
|
|
|
24
|
-
export const F1:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
export const F1: unknown = fixture(
|
|
25
|
+
"This is a fixture with some regular props",
|
|
26
|
+
{
|
|
27
|
+
propA: "this is a prop",
|
|
28
|
+
propB: "this is another",
|
|
29
|
+
},
|
|
30
|
+
);
|
|
28
31
|
|
|
29
|
-
export const F2:
|
|
32
|
+
export const F2: unknown = fixture(
|
|
30
33
|
"This is a fixture with props from functions, and a bit of logging",
|
|
31
34
|
({log}) => {
|
|
32
35
|
log("This is a log from a fixture during props generation", {
|
|
@@ -38,7 +41,7 @@ export const F2: mixed = fixture(
|
|
|
38
41
|
},
|
|
39
42
|
);
|
|
40
43
|
|
|
41
|
-
export const F3:
|
|
44
|
+
export const F3: unknown = fixture(
|
|
42
45
|
"This fixture uses a custom wrapper",
|
|
43
46
|
{
|
|
44
47
|
propA: "some props again",
|