@khanacademy/wonder-blocks-testing 7.1.9 → 7.1.11
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 +36 -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} +3 -4
- package/src/__tests__/{respond-with.test.js → respond-with.test.ts} +2 -3
- package/src/__tests__/response-impl.test.js +3 -3
- package/src/__tests__/{settle-controller.test.js → settle-controller.test.ts} +2 -3
- package/src/__tests__/{settle-signal.test.js → settle-signal.test.ts} +1 -2
- 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} +6 -7
- package/src/fetch/__tests__/{mock-fetch.test.js → mock-fetch.test.ts} +3 -4
- package/src/fetch/{fetch-request-matches-mock.js → fetch-request-matches-mock.ts} +4 -3
- package/src/fetch/{mock-fetch.js → mock-fetch.ts} +5 -6
- package/src/fetch/types.ts +14 -0
- package/src/fixtures/__tests__/{fixtures.test.js → fixtures.test.tsx} +7 -5
- package/src/fixtures/{fixtures.basic.stories.js → fixtures.basic.stories.tsx} +17 -14
- package/src/fixtures/{fixtures.defaultwrapper.stories.js → fixtures.defaultwrapper.stories.tsx} +9 -9
- package/src/fixtures/{fixtures.js → fixtures.tsx} +17 -12
- 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} +18 -19
- package/src/gql/__tests__/{mock-gql-fetch.test.js → mock-gql-fetch.test.tsx} +46 -47
- package/src/gql/__tests__/{wb-data-integration.test.js → wb-data-integration.test.tsx} +23 -24
- package/src/gql/{gql-request-matches-mock.js → gql-request-matches-mock.ts} +2 -5
- package/src/gql/mock-gql-fetch.ts +15 -0
- package/src/gql/types.ts +33 -0
- package/src/harness/__tests__/{hook-harness.test.js → hook-harness.test.ts} +13 -14
- package/src/harness/__tests__/{make-hook-harness.test.js → make-hook-harness.test.tsx} +12 -13
- package/src/harness/__tests__/{make-test-harness.test.js → make-test-harness.test.tsx} +7 -8
- package/src/harness/__tests__/{render-adapters.test.js → render-adapters.test.tsx} +10 -11
- package/src/harness/__tests__/{test-harness.test.js → test-harness.test.ts} +13 -14
- package/src/harness/__tests__/{types.flowtest.js → types.flowtest.tsx} +25 -28
- package/src/harness/adapters/__tests__/{css.test.js → css.test.tsx} +3 -4
- package/src/harness/adapters/__tests__/{data.test.js → data.test.tsx} +5 -4
- package/src/harness/adapters/__tests__/{portal.test.js → portal.test.tsx} +1 -2
- package/src/harness/adapters/__tests__/{router.test.js → router.test.tsx} +76 -57
- package/src/harness/adapters/{adapters.js → adapters.ts} +6 -7
- package/src/harness/adapters/{css.js → css.tsx} +22 -19
- package/src/harness/adapters/{data.js → data.tsx} +8 -6
- package/src/harness/adapters/{portal.js → portal.tsx} +4 -5
- package/src/harness/adapters/router.tsx +218 -0
- package/src/harness/{hook-harness.js → hook-harness.ts} +5 -6
- package/src/harness/{make-hook-harness.js → make-hook-harness.ts} +8 -8
- package/src/harness/{make-test-harness.js → make-test-harness.tsx} +19 -22
- package/src/harness/{render-adapters.js → render-adapters.ts} +5 -5
- package/src/harness/test-harness.ts +13 -0
- package/src/harness/{types.js → types.ts} +14 -12
- package/src/index.ts +20 -0
- package/src/{mock-requester.js → mock-requester.ts} +6 -5
- package/src/{respond-with.js → respond-with.ts} +45 -40
- package/src/{response-impl.js → response-impl.ts} +1 -2
- package/src/settle-controller.ts +37 -0
- 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/fetch/types.js +0 -15
- package/src/gql/mock-gql-fetch.js +0 -18
- package/src/gql/types.js +0 -34
- package/src/harness/adapters/router.js +0 -206
- package/src/harness/test-harness.js +0 -24
- package/src/index.js +0 -26
- package/src/settle-controller.js +0 -35
- package/src/types.js +0 -39
- /package/src/harness/adapters/__tests__/__snapshots__/{router.test.js.snap → router.test.tsx.snap} +0 -0
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
import {render, screen, waitFor} from "@testing-library/react";
|
|
4
3
|
|
|
5
4
|
import {GqlRouter, useGql} from "@khanacademy/wonder-blocks-data";
|
|
6
|
-
import {RespondWith} from "../../respond-with
|
|
7
|
-
import {mockGqlFetch} from "../mock-gql-fetch
|
|
5
|
+
import {RespondWith} from "../../respond-with";
|
|
6
|
+
import {mockGqlFetch} from "../mock-gql-fetch";
|
|
8
7
|
|
|
9
8
|
describe("integrating mockGqlFetch, RespondWith, GqlRouter and useGql", () => {
|
|
10
9
|
it("should reject with error indicating there are no mocks", async () => {
|
|
11
10
|
// Arrange
|
|
12
11
|
const mockFetch = mockGqlFetch();
|
|
13
12
|
const RenderError = () => {
|
|
14
|
-
const [result, setResult] = React.useState(null);
|
|
13
|
+
const [result, setResult] = React.useState<any>(null);
|
|
15
14
|
const gqlFetch = useGql();
|
|
16
15
|
React.useEffect(() => {
|
|
17
16
|
gqlFetch({
|
|
18
17
|
type: "query",
|
|
19
18
|
id: "getMyStuff",
|
|
20
|
-
}).catch((e) => {
|
|
19
|
+
}).catch((e: any) => {
|
|
21
20
|
setResult(e.message);
|
|
22
21
|
});
|
|
23
22
|
}, [gqlFetch]);
|
|
@@ -47,14 +46,14 @@ describe("integrating mockGqlFetch, RespondWith, GqlRouter and useGql", () => {
|
|
|
47
46
|
const query = {
|
|
48
47
|
type: "query",
|
|
49
48
|
id: "getMyStuff",
|
|
50
|
-
};
|
|
51
|
-
const data = {myStuff: "stuff"};
|
|
49
|
+
} as const;
|
|
50
|
+
const data = {myStuff: "stuff"} as const;
|
|
52
51
|
const RenderData = () => {
|
|
53
|
-
const [result, setResult] = React.useState(null);
|
|
52
|
+
const [result, setResult] = React.useState<any>(null);
|
|
54
53
|
const gqlFetch = useGql();
|
|
55
54
|
React.useEffect(() => {
|
|
56
55
|
// eslint-disable-next-line promise/catch-or-return
|
|
57
|
-
gqlFetch(query).then((r) => {
|
|
56
|
+
gqlFetch(query).then((r: any) => {
|
|
58
57
|
setResult(JSON.stringify(r ?? "(null)"));
|
|
59
58
|
return;
|
|
60
59
|
});
|
|
@@ -87,13 +86,13 @@ describe("integrating mockGqlFetch, RespondWith, GqlRouter and useGql", () => {
|
|
|
87
86
|
const query = {
|
|
88
87
|
type: "query",
|
|
89
88
|
id: "getMyStuff",
|
|
90
|
-
};
|
|
89
|
+
} as const;
|
|
91
90
|
const RenderError = () => {
|
|
92
|
-
const [result, setResult] = React.useState(null);
|
|
91
|
+
const [result, setResult] = React.useState<any>(null);
|
|
93
92
|
const gqlFetch = useGql();
|
|
94
93
|
React.useEffect(() => {
|
|
95
94
|
// eslint-disable-next-line promise/catch-or-return
|
|
96
|
-
gqlFetch(query).catch((e) => {
|
|
95
|
+
gqlFetch(query).catch((e: any) => {
|
|
97
96
|
setResult(e.message);
|
|
98
97
|
return;
|
|
99
98
|
});
|
|
@@ -124,13 +123,13 @@ describe("integrating mockGqlFetch, RespondWith, GqlRouter and useGql", () => {
|
|
|
124
123
|
const query = {
|
|
125
124
|
type: "query",
|
|
126
125
|
id: "getMyStuff",
|
|
127
|
-
};
|
|
126
|
+
} as const;
|
|
128
127
|
const RenderError = () => {
|
|
129
|
-
const [result, setResult] = React.useState(null);
|
|
128
|
+
const [result, setResult] = React.useState<any>(null);
|
|
130
129
|
const gqlFetch = useGql();
|
|
131
130
|
React.useEffect(() => {
|
|
132
131
|
// eslint-disable-next-line promise/catch-or-return
|
|
133
|
-
gqlFetch(query).catch((e) => {
|
|
132
|
+
gqlFetch(query).catch((e: any) => {
|
|
134
133
|
setResult(e.message);
|
|
135
134
|
});
|
|
136
135
|
}, [gqlFetch]);
|
|
@@ -162,13 +161,13 @@ describe("integrating mockGqlFetch, RespondWith, GqlRouter and useGql", () => {
|
|
|
162
161
|
const query = {
|
|
163
162
|
type: "query",
|
|
164
163
|
id: "getMyStuff",
|
|
165
|
-
};
|
|
164
|
+
} as const;
|
|
166
165
|
const RenderError = () => {
|
|
167
|
-
const [result, setResult] = React.useState(null);
|
|
166
|
+
const [result, setResult] = React.useState<any>(null);
|
|
168
167
|
const gqlFetch = useGql();
|
|
169
168
|
React.useEffect(() => {
|
|
170
169
|
// eslint-disable-next-line promise/catch-or-return
|
|
171
|
-
gqlFetch(query).catch((e) => {
|
|
170
|
+
gqlFetch(query).catch((e: any) => {
|
|
172
171
|
setResult(e.message);
|
|
173
172
|
});
|
|
174
173
|
}, [gqlFetch]);
|
|
@@ -200,13 +199,13 @@ describe("integrating mockGqlFetch, RespondWith, GqlRouter and useGql", () => {
|
|
|
200
199
|
const query = {
|
|
201
200
|
type: "query",
|
|
202
201
|
id: "getMyStuff",
|
|
203
|
-
};
|
|
202
|
+
} as const;
|
|
204
203
|
const RenderError = () => {
|
|
205
|
-
const [result, setResult] = React.useState(null);
|
|
204
|
+
const [result, setResult] = React.useState<any>(null);
|
|
206
205
|
const gqlFetch = useGql();
|
|
207
206
|
React.useEffect(() => {
|
|
208
207
|
// eslint-disable-next-line promise/catch-or-return
|
|
209
|
-
gqlFetch(query).catch((e) => {
|
|
208
|
+
gqlFetch(query).catch((e: any) => {
|
|
210
209
|
setResult(e.message);
|
|
211
210
|
});
|
|
212
211
|
}, [gqlFetch]);
|
|
@@ -238,13 +237,13 @@ describe("integrating mockGqlFetch, RespondWith, GqlRouter and useGql", () => {
|
|
|
238
237
|
const query = {
|
|
239
238
|
type: "query",
|
|
240
239
|
id: "getMyStuff",
|
|
241
|
-
};
|
|
240
|
+
} as const;
|
|
242
241
|
const RenderError = () => {
|
|
243
|
-
const [result, setResult] = React.useState(null);
|
|
242
|
+
const [result, setResult] = React.useState<any>(null);
|
|
244
243
|
const gqlFetch = useGql();
|
|
245
244
|
React.useEffect(() => {
|
|
246
245
|
// eslint-disable-next-line promise/catch-or-return
|
|
247
|
-
gqlFetch(query).catch((e) => {
|
|
246
|
+
gqlFetch(query).catch((e: any) => {
|
|
248
247
|
setResult(e.message);
|
|
249
248
|
});
|
|
250
249
|
}, [gqlFetch]);
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import type {GqlOperation, GqlContext} from "@khanacademy/wonder-blocks-data";
|
|
3
|
-
import type {GqlMockOperation} from "./types
|
|
2
|
+
import type {GqlMockOperation} from "./types";
|
|
4
3
|
|
|
5
4
|
const safeHasOwnProperty = (obj: any, prop: string): boolean =>
|
|
6
|
-
// Flow really shouldn't be raising this error here.
|
|
7
|
-
// $FlowFixMe[method-unbinding]
|
|
8
5
|
Object.prototype.hasOwnProperty.call(obj, prop);
|
|
9
6
|
|
|
10
7
|
// TODO(somewhatabstract, FEI-4268): use a third-party library to do this and
|
|
@@ -38,7 +35,7 @@ const areObjectsEqual = (a: any, b: any): boolean => {
|
|
|
38
35
|
export const gqlRequestMatchesMock = (
|
|
39
36
|
mock: GqlMockOperation<any, any, any>,
|
|
40
37
|
operation: GqlOperation<any, any>,
|
|
41
|
-
variables:
|
|
38
|
+
variables: Record<any, any> | null | undefined,
|
|
42
39
|
context: GqlContext,
|
|
43
40
|
): boolean => {
|
|
44
41
|
// If they don't represent the same operation, then they can't match.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {gqlRequestMatchesMock} from "./gql-request-matches-mock";
|
|
2
|
+
import {mockRequester} from "../mock-requester";
|
|
3
|
+
import type {GqlFetchMockFn, GqlMockOperation} from "./types";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A mock for the fetch function passed to GqlRouter.
|
|
7
|
+
*/
|
|
8
|
+
export const mockGqlFetch = (): GqlFetchMockFn =>
|
|
9
|
+
mockRequester<GqlMockOperation<any, any, any>, any>(
|
|
10
|
+
gqlRequestMatchesMock,
|
|
11
|
+
(operation, variables, context) =>
|
|
12
|
+
`Operation: ${operation.type} ${operation.id}
|
|
13
|
+
Variables: ${variables == null ? "None" : JSON.stringify(variables, null, 2)}
|
|
14
|
+
Context: ${JSON.stringify(context, null, 2)}`,
|
|
15
|
+
);
|
package/src/gql/types.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type {GqlOperation, GqlContext} from "@khanacademy/wonder-blocks-data";
|
|
2
|
+
import type {GraphQLJson} from "../types";
|
|
3
|
+
import type {MockResponse} from "../respond-with";
|
|
4
|
+
|
|
5
|
+
export type GqlMockOperation<
|
|
6
|
+
TData extends Record<any, any>,
|
|
7
|
+
TVariables extends Record<any, any>,
|
|
8
|
+
TContext extends GqlContext,
|
|
9
|
+
> = {
|
|
10
|
+
operation: GqlOperation<TData, TVariables>;
|
|
11
|
+
variables?: TVariables;
|
|
12
|
+
context?: TContext;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
type GqlMockOperationFn = <
|
|
16
|
+
TData extends Record<any, any>,
|
|
17
|
+
TVariables extends Record<any, any>,
|
|
18
|
+
TContext extends GqlContext,
|
|
19
|
+
TResponseData extends GraphQLJson<TData>,
|
|
20
|
+
>(
|
|
21
|
+
operation: GqlMockOperation<TData, TVariables, TContext>,
|
|
22
|
+
response: MockResponse<TResponseData>,
|
|
23
|
+
) => GqlFetchMockFn;
|
|
24
|
+
|
|
25
|
+
export type GqlFetchMockFn = {
|
|
26
|
+
(
|
|
27
|
+
operation: GqlOperation<any, any>,
|
|
28
|
+
variables: Record<any, any> | null | undefined,
|
|
29
|
+
context: GqlContext,
|
|
30
|
+
): Promise<Response>;
|
|
31
|
+
mockOperation: GqlMockOperationFn;
|
|
32
|
+
mockOperationOnce: GqlMockOperationFn;
|
|
33
|
+
};
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {jest as ws} from "@khanacademy/wonder-stuff-testing";
|
|
3
|
-
import * as MHH from "../make-hook-harness
|
|
4
|
-
import {DefaultAdapters, DefaultConfigs} from "../adapters/adapters
|
|
2
|
+
import * as MHH from "../make-hook-harness";
|
|
3
|
+
import {DefaultAdapters, DefaultConfigs} from "../adapters/adapters";
|
|
5
4
|
|
|
6
|
-
jest.mock("../make-hook-harness
|
|
5
|
+
jest.mock("../make-hook-harness", () => {
|
|
7
6
|
const returnValueFake = {
|
|
8
7
|
thisisa: "PRETEND REACT COMPONENT",
|
|
9
|
-
};
|
|
8
|
+
} as const;
|
|
10
9
|
const harnessFake = jest.fn().mockReturnValue(returnValueFake);
|
|
11
10
|
return {
|
|
12
11
|
harnessFake,
|
|
@@ -21,7 +20,7 @@ describe("#hookHarness", () => {
|
|
|
21
20
|
const makeHookHarnessSpy = jest.spyOn(MHH, "makeHookHarness");
|
|
22
21
|
|
|
23
22
|
// Act
|
|
24
|
-
await ws.isolateModules(() => import("../hook-harness
|
|
23
|
+
await ws.isolateModules(() => import("../hook-harness"));
|
|
25
24
|
|
|
26
25
|
// Assert
|
|
27
26
|
expect(makeHookHarnessSpy).toHaveBeenCalledWith(
|
|
@@ -34,12 +33,12 @@ describe("#hookHarness", () => {
|
|
|
34
33
|
// Arrange
|
|
35
34
|
const config = {
|
|
36
35
|
router: "/boo",
|
|
37
|
-
};
|
|
38
|
-
//
|
|
36
|
+
} as const;
|
|
37
|
+
// @ts-expect-error [FEI-5019] - TS2339 - Property 'harnessFake' does not exist on type 'typeof import("/Users/kevinbarabash/khan/wonder-blocks/packages/wonder-blocks-testing/src/harness/make-hook-harness")'.
|
|
39
38
|
const [{harnessFake}, {hookHarness}] = await ws.isolateModules(() =>
|
|
40
39
|
Promise.all([
|
|
41
|
-
import("../make-hook-harness
|
|
42
|
-
import("../hook-harness
|
|
40
|
+
import("../make-hook-harness"),
|
|
41
|
+
import("../hook-harness"),
|
|
43
42
|
]),
|
|
44
43
|
);
|
|
45
44
|
|
|
@@ -54,12 +53,12 @@ describe("#hookHarness", () => {
|
|
|
54
53
|
// Arrange
|
|
55
54
|
const config = {
|
|
56
55
|
router: "/boo",
|
|
57
|
-
};
|
|
58
|
-
//
|
|
56
|
+
} as const;
|
|
57
|
+
// @ts-expect-error [FEI-5019] - TS2339 - Property 'returnValueFake' does not exist on type 'typeof import("/Users/kevinbarabash/khan/wonder-blocks/packages/wonder-blocks-testing/src/harness/make-hook-harness")'.
|
|
59
58
|
const [{returnValueFake}, {hookHarness}] = await ws.isolateModules(() =>
|
|
60
59
|
Promise.all([
|
|
61
|
-
import("../make-hook-harness
|
|
62
|
-
import("../hook-harness
|
|
60
|
+
import("../make-hook-harness"),
|
|
61
|
+
import("../hook-harness"),
|
|
63
62
|
]),
|
|
64
63
|
);
|
|
65
64
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
import {render} from "@testing-library/react";
|
|
4
|
-
import {makeHookHarness} from "../make-hook-harness
|
|
5
|
-
import * as MTH from "../make-test-harness
|
|
3
|
+
import {makeHookHarness} from "../make-hook-harness";
|
|
4
|
+
import * as MTH from "../make-test-harness";
|
|
6
5
|
|
|
7
6
|
describe("#makeHookHarness", () => {
|
|
8
7
|
it("should call makeTestHarness", () => {
|
|
@@ -10,10 +9,10 @@ describe("#makeHookHarness", () => {
|
|
|
10
9
|
const makeTestHarnessSpy = jest.spyOn(MTH, "makeTestHarness");
|
|
11
10
|
const adapters = {
|
|
12
11
|
adapter: jest.fn(),
|
|
13
|
-
};
|
|
12
|
+
} as const;
|
|
14
13
|
const defaultConfigs = {
|
|
15
14
|
adapter: {},
|
|
16
|
-
};
|
|
15
|
+
} as const;
|
|
17
16
|
|
|
18
17
|
// Act
|
|
19
18
|
makeHookHarness(adapters, defaultConfigs);
|
|
@@ -28,10 +27,10 @@ describe("#makeHookHarness", () => {
|
|
|
28
27
|
it("should return a function", () => {
|
|
29
28
|
const adapters = {
|
|
30
29
|
adapter: jest.fn(),
|
|
31
|
-
};
|
|
30
|
+
} as const;
|
|
32
31
|
const defaultConfigs = {
|
|
33
32
|
adapter: {},
|
|
34
|
-
};
|
|
33
|
+
} as const;
|
|
35
34
|
|
|
36
35
|
// Act
|
|
37
36
|
const result = makeHookHarness(adapters, defaultConfigs);
|
|
@@ -47,13 +46,13 @@ describe("#makeHookHarness", () => {
|
|
|
47
46
|
jest.spyOn(MTH, "makeTestHarness").mockReturnValue(harnessSpy);
|
|
48
47
|
const adapters = {
|
|
49
48
|
adapter: jest.fn(),
|
|
50
|
-
};
|
|
49
|
+
} as const;
|
|
51
50
|
const defaultConfigs = {
|
|
52
51
|
adapter: {},
|
|
53
|
-
};
|
|
52
|
+
} as const;
|
|
54
53
|
const configs = {
|
|
55
54
|
adapter: {},
|
|
56
|
-
};
|
|
55
|
+
} as const;
|
|
57
56
|
const hookHarness = makeHookHarness(adapters, defaultConfigs);
|
|
58
57
|
|
|
59
58
|
// Act
|
|
@@ -72,13 +71,13 @@ describe("#makeHookHarness", () => {
|
|
|
72
71
|
jest.spyOn(MTH, "makeTestHarness").mockReturnValue(harnessSpy);
|
|
73
72
|
const adapters = {
|
|
74
73
|
adapter: jest.fn(),
|
|
75
|
-
};
|
|
74
|
+
} as const;
|
|
76
75
|
const defaultConfigs = {
|
|
77
76
|
adapter: {},
|
|
78
|
-
};
|
|
77
|
+
} as const;
|
|
79
78
|
const configs = {
|
|
80
79
|
adapter: {},
|
|
81
|
-
};
|
|
80
|
+
} as const;
|
|
82
81
|
const children = "THE CHILDREN";
|
|
83
82
|
|
|
84
83
|
// Act
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
import {Route} from "react-router-dom";
|
|
4
3
|
import {render} from "@testing-library/react";
|
|
5
4
|
|
|
6
|
-
import * as RA from "../render-adapters
|
|
7
|
-
import {makeTestHarness} from "../make-test-harness
|
|
8
|
-
import {DefaultConfigs, DefaultAdapters} from "../adapters/adapters
|
|
5
|
+
import * as RA from "../render-adapters";
|
|
6
|
+
import {makeTestHarness} from "../make-test-harness";
|
|
7
|
+
import {DefaultConfigs, DefaultAdapters} from "../adapters/adapters";
|
|
9
8
|
|
|
10
9
|
describe("#makeTestHarness", () => {
|
|
11
10
|
it("should return a function", () => {
|
|
@@ -96,7 +95,7 @@ describe("#makeTestHarness", () => {
|
|
|
96
95
|
DefaultAdapters,
|
|
97
96
|
DefaultConfigs,
|
|
98
97
|
);
|
|
99
|
-
const Component = (props: {
|
|
98
|
+
const Component = (props: {text: string}) => (
|
|
100
99
|
<div>{props.text}</div>
|
|
101
100
|
);
|
|
102
101
|
|
|
@@ -129,7 +128,7 @@ describe("#makeTestHarness", () => {
|
|
|
129
128
|
DefaultAdapters,
|
|
130
129
|
DefaultConfigs,
|
|
131
130
|
);
|
|
132
|
-
const configOverrides:
|
|
131
|
+
const configOverrides: Partial<typeof DefaultConfigs> = {
|
|
133
132
|
router: "/mysecretplace",
|
|
134
133
|
};
|
|
135
134
|
const Component = () => <div>test</div>;
|
|
@@ -159,12 +158,12 @@ describe("#makeTestHarness", () => {
|
|
|
159
158
|
DefaultAdapters,
|
|
160
159
|
DefaultConfigs,
|
|
161
160
|
);
|
|
162
|
-
const configOverrides:
|
|
161
|
+
const configOverrides: Partial<typeof DefaultConfigs> = {
|
|
163
162
|
router: "/mysecretplace/test",
|
|
164
163
|
};
|
|
165
164
|
// Render a route match that only works if we render our
|
|
166
165
|
// overridden location.
|
|
167
|
-
const Component = (props: {
|
|
166
|
+
const Component = (props: {text: string}) => (
|
|
168
167
|
<Route path="/mysecretplace/*">{props.text}</Route>
|
|
169
168
|
);
|
|
170
169
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import * as React from "react";
|
|
3
|
-
import {renderAdapters} from "../render-adapters
|
|
2
|
+
import {renderAdapters} from "../render-adapters";
|
|
4
3
|
|
|
5
|
-
import type {TestHarnessAdapter, TestHarnessConfigs} from "../types
|
|
4
|
+
import type {TestHarnessAdapter, TestHarnessConfigs} from "../types";
|
|
6
5
|
|
|
7
6
|
describe("#renderAdapters", () => {
|
|
8
7
|
it("should return children if no adapters", () => {
|
|
@@ -20,8 +19,8 @@ describe("#renderAdapters", () => {
|
|
|
20
19
|
// Arrange
|
|
21
20
|
const children = <div>Adapt me!</div>;
|
|
22
21
|
const adapters = {
|
|
23
|
-
adapterA:
|
|
24
|
-
};
|
|
22
|
+
adapterA: jest.fn() as TestHarnessAdapter<string>,
|
|
23
|
+
} as const;
|
|
25
24
|
const configs: TestHarnessConfigs<typeof adapters> = {
|
|
26
25
|
adapterA: "APPLY A CONFIG",
|
|
27
26
|
};
|
|
@@ -39,15 +38,15 @@ describe("#renderAdapters", () => {
|
|
|
39
38
|
it("should render each adapter and the children", () => {
|
|
40
39
|
// Arrange
|
|
41
40
|
const children = "Adapt me!";
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
// @ts-expect-error: `string` is not a valid `ReactElement`.
|
|
42
|
+
const adapter: TestHarnessAdapter<string> = (c: any, conf: any) => {
|
|
44
43
|
return `${conf}:${c}`;
|
|
45
44
|
};
|
|
46
45
|
const adapters = {
|
|
47
46
|
adapterA: adapter,
|
|
48
47
|
adapterB: adapter,
|
|
49
48
|
adapterC: adapter,
|
|
50
|
-
};
|
|
49
|
+
} as const;
|
|
51
50
|
const configs: TestHarnessConfigs<typeof adapters> = {
|
|
52
51
|
adapterA: "A",
|
|
53
52
|
adapterB: "B",
|
|
@@ -64,15 +63,15 @@ describe("#renderAdapters", () => {
|
|
|
64
63
|
it("should skip adapters where the corresponding config is null", () => {
|
|
65
64
|
// Arrange
|
|
66
65
|
const children = "Adapt me!";
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
// @ts-expect-error: `string` is not a valid `ReactElement`.
|
|
67
|
+
const adapter: TestHarnessAdapter<string> = (c: any, conf: any) => {
|
|
69
68
|
return `${conf}:${c}`;
|
|
70
69
|
};
|
|
71
70
|
const adapters = {
|
|
72
71
|
adapterA: adapter,
|
|
73
72
|
adapterB: adapter,
|
|
74
73
|
adapterC: adapter,
|
|
75
|
-
};
|
|
74
|
+
} as const;
|
|
76
75
|
const configs: TestHarnessConfigs<typeof adapters> = {
|
|
77
76
|
adapterA: "A",
|
|
78
77
|
adapterB: null,
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {jest as ws} from "@khanacademy/wonder-stuff-testing";
|
|
3
|
-
import * as MTH from "../make-test-harness
|
|
4
|
-
import {DefaultAdapters, DefaultConfigs} from "../adapters/adapters
|
|
2
|
+
import * as MTH from "../make-test-harness";
|
|
3
|
+
import {DefaultAdapters, DefaultConfigs} from "../adapters/adapters";
|
|
5
4
|
|
|
6
|
-
jest.mock("../make-test-harness
|
|
5
|
+
jest.mock("../make-test-harness", () => {
|
|
7
6
|
const returnValueFake = {
|
|
8
7
|
thisisa: "PRETEND REACT COMPONENT",
|
|
9
|
-
};
|
|
8
|
+
} as const;
|
|
10
9
|
const harnessFake = jest.fn().mockReturnValue(returnValueFake);
|
|
11
10
|
return {
|
|
12
11
|
harnessFake,
|
|
@@ -21,7 +20,7 @@ describe("#testHarness", () => {
|
|
|
21
20
|
const makeTestHarnessSpy = jest.spyOn(MTH, "makeTestHarness");
|
|
22
21
|
|
|
23
22
|
// Act
|
|
24
|
-
await ws.isolateModules(() => import("../hook-harness
|
|
23
|
+
await ws.isolateModules(() => import("../hook-harness"));
|
|
25
24
|
|
|
26
25
|
// Assert
|
|
27
26
|
expect(makeTestHarnessSpy).toHaveBeenCalledWith(
|
|
@@ -35,12 +34,12 @@ describe("#testHarness", () => {
|
|
|
35
34
|
const Component = () => null;
|
|
36
35
|
const config = {
|
|
37
36
|
router: "/boo",
|
|
38
|
-
};
|
|
39
|
-
//
|
|
37
|
+
} as const;
|
|
38
|
+
// @ts-expect-error [FEI-5019] - TS2339 - Property 'harnessFake' does not exist on type 'typeof import("/Users/kevinbarabash/khan/wonder-blocks/packages/wonder-blocks-testing/src/harness/make-test-harness")'.
|
|
40
39
|
const [{harnessFake}, {testHarness}] = await ws.isolateModules(() =>
|
|
41
40
|
Promise.all([
|
|
42
|
-
import("../make-test-harness
|
|
43
|
-
import("../test-harness
|
|
41
|
+
import("../make-test-harness"),
|
|
42
|
+
import("../test-harness"),
|
|
44
43
|
]),
|
|
45
44
|
);
|
|
46
45
|
|
|
@@ -56,12 +55,12 @@ describe("#testHarness", () => {
|
|
|
56
55
|
const Component = () => null;
|
|
57
56
|
const config = {
|
|
58
57
|
router: "/boo",
|
|
59
|
-
};
|
|
60
|
-
//
|
|
58
|
+
} as const;
|
|
59
|
+
// @ts-expect-error [FEI-5019] - TS2339 - Property 'returnValueFake' does not exist on type 'typeof import("/Users/kevinbarabash/khan/wonder-blocks/packages/wonder-blocks-testing/src/harness/make-test-harness")'.
|
|
61
60
|
const [{returnValueFake}, {testHarness}] = await ws.isolateModules(() =>
|
|
62
61
|
Promise.all([
|
|
63
|
-
import("../make-test-harness
|
|
64
|
-
import("../test-harness
|
|
62
|
+
import("../make-test-harness"),
|
|
63
|
+
import("../test-harness"),
|
|
65
64
|
]),
|
|
66
65
|
);
|
|
67
66
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
|
|
4
3
|
import type {
|
|
@@ -6,25 +5,26 @@ import type {
|
|
|
6
5
|
TestHarnessAdapters,
|
|
7
6
|
TestHarnessConfig,
|
|
8
7
|
TestHarnessConfigs,
|
|
9
|
-
} from "../types
|
|
8
|
+
} from "../types";
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* TestHarnessAdapter<TConfig>
|
|
13
12
|
*/
|
|
14
13
|
|
|
15
14
|
//> should assert type of config.
|
|
15
|
+
// @ts-expect-error [FEI-5019] - TS2352 - Conversion of type '(children: React.ReactNode, config: number) => React.ReactElement<any>' to type 'TestHarnessAdapter<string>' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
|
|
16
16
|
((
|
|
17
|
-
children: React.
|
|
17
|
+
children: React.ReactNode,
|
|
18
18
|
// TConfig is string, but we typed this arg as a number
|
|
19
19
|
// $FlowExpectedError[incompatible-cast]
|
|
20
20
|
config: number,
|
|
21
|
-
): React.
|
|
21
|
+
): React.ReactElement<any> => <div />) as TestHarnessAdapter<string>;
|
|
22
22
|
//<
|
|
23
23
|
|
|
24
24
|
//> should work for correct definition
|
|
25
|
-
((children: React.
|
|
25
|
+
((children: React.ReactNode, config: string): React.ReactElement<any> => (
|
|
26
26
|
<div />
|
|
27
|
-
)
|
|
27
|
+
)) as TestHarnessAdapter<string>;
|
|
28
28
|
//<
|
|
29
29
|
|
|
30
30
|
/**
|
|
@@ -32,34 +32,34 @@ import type {
|
|
|
32
32
|
*/
|
|
33
33
|
|
|
34
34
|
//> should work for empty case
|
|
35
|
-
({}
|
|
35
|
+
({} as TestHarnessAdapters);
|
|
36
36
|
//<
|
|
37
37
|
|
|
38
38
|
//> should assert if adapter is not Adapter<TConfig>
|
|
39
|
+
// @ts-expect-error [FEI-5019] - TS2352 - Conversion of type '{ adapterString: string; }' to type 'TestHarnessAdapters' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
|
|
39
40
|
({
|
|
40
41
|
// String is not a adapter function
|
|
41
42
|
// $FlowExpectedError[incompatible-cast]
|
|
42
43
|
adapterString: "string",
|
|
43
|
-
}
|
|
44
|
+
} as TestHarnessAdapters);
|
|
44
45
|
//<
|
|
45
46
|
|
|
46
47
|
//> should work for a function matching Adapter<TConfig>
|
|
47
48
|
({
|
|
48
49
|
adapterA: (children, config) => <div>test</div>,
|
|
49
|
-
}
|
|
50
|
+
} as TestHarnessAdapters);
|
|
50
51
|
//<
|
|
51
52
|
|
|
52
53
|
/**
|
|
53
54
|
* TestHarnessConfig<TAdapter>
|
|
54
55
|
*/
|
|
55
56
|
//> should give the config type of an adapter
|
|
56
|
-
|
|
57
|
+
"string" as TestHarnessConfig<TestHarnessAdapter<string>>;
|
|
57
58
|
//<
|
|
58
59
|
|
|
59
60
|
//> should error if the config type is wrong
|
|
60
61
|
// 45 is not a string
|
|
61
|
-
|
|
62
|
-
(45: TestHarnessConfig<TestHarnessAdapter<string>>);
|
|
62
|
+
45 as TestHarnessConfig<TestHarnessAdapter<string>>;
|
|
63
63
|
//<
|
|
64
64
|
|
|
65
65
|
/**
|
|
@@ -69,7 +69,7 @@ import type {
|
|
|
69
69
|
* are explicitly typed as `TestHarnessAdapter<TConfig>` so if passing in a
|
|
70
70
|
* non-Adapters type (which we should be, to get strong TConfig types instead
|
|
71
71
|
* of `any`), then that object should make sure that each adapter is strongly
|
|
72
|
-
* marked as `TestHarnessAdapter<TConfig>` -
|
|
72
|
+
* marked as `TestHarnessAdapter<TConfig>` - TypeScript does not appear to pattern
|
|
73
73
|
* match against the type definition when invoking the ExtractConfig type and I
|
|
74
74
|
* haven't worked out how to get it to multi-dispatch so that it matches
|
|
75
75
|
* functions too. Even worse, if the type doesn't match, it just allows `any`
|
|
@@ -77,32 +77,29 @@ import type {
|
|
|
77
77
|
*/
|
|
78
78
|
const notadapters = "this is wrong";
|
|
79
79
|
const adapterA: TestHarnessAdapter<string> = (
|
|
80
|
-
children: React.
|
|
81
|
-
config
|
|
82
|
-
): React.
|
|
80
|
+
children: React.ReactNode,
|
|
81
|
+
config?: string | null,
|
|
82
|
+
): React.ReactElement<any> => <div />;
|
|
83
83
|
const adapterB: TestHarnessAdapter<number> = (
|
|
84
|
-
children: React.
|
|
85
|
-
config
|
|
86
|
-
): React.
|
|
84
|
+
children: React.ReactNode,
|
|
85
|
+
config?: number | null,
|
|
86
|
+
): React.ReactElement<any> => <div />;
|
|
87
87
|
const adapters = {
|
|
88
88
|
adapterA,
|
|
89
89
|
adapterB,
|
|
90
|
-
};
|
|
90
|
+
} as const;
|
|
91
91
|
|
|
92
92
|
//> should assert if parameterized type is not valid Adapters
|
|
93
93
|
// string is not a valid Adapter
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
({}: TestHarnessConfigs<typeof notadapters>);
|
|
94
|
+
// @ts-expect-error: Type 'string' does not satisfy the constraint 'TestHarnessAdapters'
|
|
95
|
+
({} as TestHarnessConfigs<typeof notadapters>);
|
|
97
96
|
//<
|
|
98
97
|
|
|
99
98
|
//> should expect one config per adapter
|
|
100
99
|
// both adapter configs missing
|
|
101
|
-
|
|
102
|
-
({}: TestHarnessConfigs<typeof adapters>);
|
|
100
|
+
({} as TestHarnessConfigs<typeof adapters>);
|
|
103
101
|
// adapterB config missing
|
|
104
|
-
|
|
105
|
-
({adapterA: "test"}: TestHarnessConfigs<typeof adapters>);
|
|
102
|
+
({adapterA: "test"} as TestHarnessConfigs<typeof adapters>);
|
|
106
103
|
//<
|
|
107
104
|
|
|
108
105
|
//> should assert if config does not match adapter config
|
|
@@ -111,5 +108,5 @@ const adapters = {
|
|
|
111
108
|
// the config type here is a number, not a string
|
|
112
109
|
// $FlowExpectedError[incompatible-cast]
|
|
113
110
|
adapterB: "a string, but it should be a number",
|
|
114
|
-
}
|
|
111
|
+
} as TestHarnessConfigs<typeof adapters>);
|
|
115
112
|
//<
|