@khanacademy/wonder-blocks-testing 4.0.4 → 5.0.2
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 +21 -0
- package/dist/es/index.js +212 -26
- package/dist/index.js +589 -62
- package/package.json +5 -3
- package/src/__docs__/_overview_.stories.mdx +3 -4
- package/src/__docs__/_overview_fixtures.stories.mdx +22 -0
- package/src/__docs__/_overview_mocking.stories.mdx +14 -0
- package/src/__docs__/_overview_test_harness.stories.mdx +18 -0
- package/src/__docs__/exports.fixture-adapters.stories.mdx +49 -0
- package/src/__docs__/exports.fixtures.stories.mdx +53 -0
- package/src/__docs__/exports.harness-adapters.stories.mdx +187 -0
- package/src/__docs__/exports.hook-harness.stories.mdx +22 -0
- package/src/__docs__/exports.make-hook-harness.stories.mdx +25 -0
- package/src/__docs__/exports.make-test-harness.stories.mdx +28 -0
- package/src/__docs__/exports.mock-fetch.stories.mdx +40 -0
- package/src/__docs__/exports.mock-gql-fetch.stories.mdx +13 -8
- package/src/__docs__/exports.respond-with.stories.mdx +54 -8
- package/src/__docs__/exports.setup-fixtures.stories.mdx +22 -0
- package/src/__docs__/exports.test-harness.stories.mdx +23 -0
- package/src/__docs__/types.custom-mount-props.stories.mdx +35 -0
- package/src/__docs__/types.fetch-mock-fn.stories.mdx +22 -0
- package/src/__docs__/types.fetch-mock-operation.stories.mdx +18 -0
- package/src/__docs__/types.fixtures-adapter-factory.stories.mdx +23 -0
- package/src/__docs__/types.fixtures-adapter-fixture-options.stories.mdx +35 -0
- package/src/__docs__/types.fixtures-adapter-group-options.stories.mdx +37 -0
- package/src/__docs__/types.fixtures-adapter-group.stories.mdx +43 -0
- package/src/__docs__/types.fixtures-adapter-options.stories.mdx +21 -0
- package/src/__docs__/types.fixtures-adapter.stories.mdx +35 -0
- package/src/__docs__/types.fixtures-configuration.stories.mdx +35 -0
- package/src/__docs__/types.fixtures-options.stories.mdx +51 -0
- package/src/__docs__/types.get-props-options.stories.mdx +25 -0
- package/src/__docs__/types.gql-fetch-mock-fn.stories.mdx +27 -0
- package/src/__docs__/types.gql-mock-operation.stories.mdx +26 -0
- package/src/__docs__/types.mock-response.stories.mdx +18 -0
- package/src/__docs__/types.test-harness-adapter.stories.mdx +21 -0
- package/src/__docs__/types.test-harness-adapters.stories.mdx +46 -0
- package/src/__docs__/types.test-harness-config.stories.mdx +18 -0
- package/src/__docs__/types.test-harness-configs.stories.mdx +59 -0
- package/src/fetch/types.js +0 -3
- package/src/fixtures/adapters/adapter-group.js +11 -11
- package/src/fixtures/adapters/adapter.js +8 -8
- package/src/fixtures/adapters/storybook.js +11 -8
- package/src/fixtures/fixtures.basic.stories.js +6 -2
- package/src/fixtures/fixtures.defaultwrapper.stories.js +6 -2
- package/src/fixtures/setup.js +8 -4
- package/src/fixtures/types.js +27 -16
- package/src/gql/types.js +1 -3
- package/src/harness/__tests__/hook-harness.test.js +72 -0
- package/src/harness/__tests__/make-hook-harness.test.js +94 -0
- package/src/harness/__tests__/make-test-harness.test.js +190 -0
- package/src/harness/__tests__/render-adapters.test.js +88 -0
- package/src/harness/__tests__/test-harness.test.js +74 -0
- package/src/harness/__tests__/types.flowtest.js +115 -0
- package/src/harness/adapters/__tests__/__snapshots__/router.test.js.snap +5 -0
- package/src/harness/adapters/__tests__/css.test.js +96 -0
- package/src/harness/adapters/__tests__/data.test.js +66 -0
- package/src/harness/adapters/__tests__/portal.test.js +31 -0
- package/src/harness/adapters/__tests__/router.test.js +233 -0
- package/src/harness/adapters/adapters.js +33 -0
- package/src/harness/adapters/css.js +65 -0
- package/src/harness/adapters/data.js +46 -0
- package/src/harness/adapters/portal.js +26 -0
- package/src/harness/adapters/router.js +206 -0
- package/src/harness/hook-harness.js +23 -0
- package/src/harness/make-hook-harness.js +39 -0
- package/src/harness/make-test-harness.js +68 -0
- package/src/harness/render-adapters.js +27 -0
- package/src/harness/test-harness.js +24 -0
- package/src/harness/types.js +57 -0
- package/src/index.js +22 -18
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanacademy/wonder-blocks-testing",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.2",
|
|
4
4
|
"design": "v1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -14,14 +14,16 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@babel/runtime": "^7.16.3",
|
|
17
|
-
"@khanacademy/wonder-blocks-data": "^8.0.
|
|
17
|
+
"@khanacademy/wonder-blocks-data": "^8.0.3"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
20
|
"@khanacademy/wonder-stuff-core": "^0.1.2",
|
|
21
21
|
"@khanacademy/wonder-stuff-testing": "^0.0.2",
|
|
22
22
|
"@storybook/addon-actions": "^6.4.8",
|
|
23
23
|
"node-fetch": "^2.6.7",
|
|
24
|
-
"
|
|
24
|
+
"aphrodite": "^1.2.5",
|
|
25
|
+
"react": "16.14.0",
|
|
26
|
+
"react-router-dom": "5.3.0"
|
|
25
27
|
},
|
|
26
28
|
"devDependencies": {
|
|
27
29
|
"wb-dev-build-settings": "^0.4.0"
|
|
@@ -13,7 +13,6 @@ import {Meta} from "@storybook/addon-docs";
|
|
|
13
13
|
|
|
14
14
|
Wonder Blocks Testing provides various utilities to support testing of React components and Wonder Blocks features.
|
|
15
15
|
|
|
16
|
-
* [Fixtures
|
|
17
|
-
*
|
|
18
|
-
|
|
19
|
-
* [`RespondWith`](/docs/testing-exports-respondwith--page)
|
|
16
|
+
* [Fixtures](/docs/testing-fixtures-overview--page)
|
|
17
|
+
* [Mocking](/docs/testing-mocking-overview--page)
|
|
18
|
+
* [Test Harness](/docs/testing-test-harness-overview--page)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Testing / Fixtures / Overview"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# Fixtures
|
|
13
|
+
|
|
14
|
+
The fixtures framework provides an agnostic way to declare component fixtures that can then be adapted via runtime configuration to the fixture rendering environment of choice.
|
|
15
|
+
|
|
16
|
+
To use the framework for defining fixtures, import the [`fixtures()`](/docs/testing-fixtures-exports-fixtures--page) method. You can configure the framework for your specific environment (such as Storybook) using the [`setupFixtures()`](/docs/testing-fixtures-exports-setupfixtures--page) method.
|
|
17
|
+
|
|
18
|
+
An adapter to output fixtures for [Storybook](/docs/testing-fixtures-exports-fixtureadapters--page) is included.
|
|
19
|
+
|
|
20
|
+
Some examples of this framework in use with Storybook can be seen [here](/docs/testing-fixtures-basic--f-1).
|
|
21
|
+
|
|
22
|
+
Types are also exported to enable the creation of adapters for other environments as you may need.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Testing / Mocking / Overview"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# Mocking
|
|
13
|
+
|
|
14
|
+
Wonder Blocks Testing provides support for mocking the Wonder Blocks Data GraphQL fetching via the [`mockGqlFetch()`](/docs/testing-mocking-exports-mockgqlfetch--page) export, and `fetch()`-like methods via the [`mockFetch()`](/docs/testing-mocking-exports-mockFetch--page) export. These are both supported by the [`RespondWith`](/docs/testing-mocking-exports-respondwith--page) API for easily generating the responses.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Testing / Test Harness / Overview"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# Test Harness
|
|
13
|
+
|
|
14
|
+
The test harness framework provides a simple approach to minimizing boilerplate when testing React components. It works by allowing for the definition of predefined adapters and configurations that can be rendered around the component under test, encapsulating boilerplate code such as setting up contexts, CSS, or mocking APIs.
|
|
15
|
+
|
|
16
|
+
There are some [default adapters](/docs/testing-test-harness-exports-harnessadapters--page) provided as well as default [`testHarness()`](/docs/testing-test-harness-exports-testharness--page) and [`hookHarness()`](/docs/testing-test-harness-exports-hookharness--page) methods that use these adapters with meaningful defaults, which can be overridden.
|
|
17
|
+
|
|
18
|
+
However, it is likely you will want to replace or augment the existing adapters with some of your own. For this purpose, the [`makeTestHarness()`](/docs/testing-test-harness-exports-maketestharness--page) and [`makeHookHarness()`](/docs/testing-test-harness-exports-makehookharness--page) methods are provided.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Testing / Fixtures / Exports / fixtureAdapters"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# fixtureAdapters
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
type StoryContext = {|
|
|
16
|
+
args: $ReadOnly<any>,
|
|
17
|
+
argTypes: $ReadOnly<any>,
|
|
18
|
+
globals: $ReadOnlyArray<any>,
|
|
19
|
+
hooks: $ReadOnlyArray<any>,
|
|
20
|
+
parameters: $ReadOnly<any>,
|
|
21
|
+
viewMode: mixed,
|
|
22
|
+
|};
|
|
23
|
+
|
|
24
|
+
type StorybookOptions = {|
|
|
25
|
+
decorators?: Array<
|
|
26
|
+
(story: React.ComponentType<any>, context: StoryContext) => React.Node,
|
|
27
|
+
>,
|
|
28
|
+
parameters?: $ReadOnly<any>,
|
|
29
|
+
|};
|
|
30
|
+
|
|
31
|
+
type DefaultExport = {|
|
|
32
|
+
title?: ?string,
|
|
33
|
+
...StorybookOptions,
|
|
34
|
+
|};
|
|
35
|
+
|
|
36
|
+
type Exports<TProps: {...}> = {|
|
|
37
|
+
default: DefaultExport,
|
|
38
|
+
[story: string]: React.ComponentType<TProps>,
|
|
39
|
+
|};
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
const fixtureAdapters = {
|
|
43
|
+
storybook: AdapterFactory<StorybookOptions, Exports<any>>,
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
These are the adapters available for use with the fixtures framework. If an adapter is not listed here for the framework you want, you can create your own conforming to the [`FixturesAdapterFactory`](/docs/testing-fixtures-types-fixturesadapterfactory--page) type.
|
|
48
|
+
|
|
49
|
+
To configure the fixtures framework, use an adapter with the [`setupFixtures`](/docs/testing-fixtures-exports-setupfixtures--page) function.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Testing / Fixtures / Exports / fixtures()"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# fixtures()
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
type FixtureProps<TProps: {...}> =
|
|
16
|
+
| $ReadOnly<TProps>
|
|
17
|
+
| ((options: $ReadOnly<GetPropsOptions>) => $ReadOnly<TProps>);
|
|
18
|
+
|
|
19
|
+
fixtures<TProps: {...}>(
|
|
20
|
+
component: React.ComponentType<TProps>,
|
|
21
|
+
fn: (
|
|
22
|
+
fixture: (
|
|
23
|
+
description: string,
|
|
24
|
+
props: FixtureProps<TProps>,
|
|
25
|
+
wrapper?: React.ComponentType<TProps>,
|
|
26
|
+
) => void,
|
|
27
|
+
) => void,
|
|
28
|
+
): ?$ReadOnly<mixed>;
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
fixtures<TProps: {...}>(
|
|
32
|
+
options: $ReadOnly<FixturesOptions<TProps>>,
|
|
33
|
+
fn: (
|
|
34
|
+
fixture: (
|
|
35
|
+
description: string,
|
|
36
|
+
props: FixtureProps<TProps>,
|
|
37
|
+
wrapper?: React.ComponentType<TProps>,
|
|
38
|
+
) => void,
|
|
39
|
+
) => void,
|
|
40
|
+
): ?$ReadOnly<mixed>;
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The `fixtures()` method is used to define a set of fixtures for a component. It provides a way to describe fixtures as one might describe unit tests. Fixtures are like stories in Storybook (and, if the fixtures framework is configured for storybook, will be stories).
|
|
44
|
+
|
|
45
|
+
The return value provides the module exports that your fixture file should export. If your build system supports CommonJS syntax, this can be exported using `module.exports = returnValue`; however, if you need to use ESM syntax, you may need to do something like we do in [our Fixtures Framework example stories](/docs/testing-fixtures-basic--f-1).
|
|
46
|
+
|
|
47
|
+
There are two ways to call the `fixtures()` function; with a component and callback, or with a set of [options](/docs/testing-fixtures-types-fixtureoptions--page) and callback.
|
|
48
|
+
|
|
49
|
+
The second argument is a callback in which you should define your fixture susing the passed `fixture` function (the first and only argument of the callback). The `fixture` function takes two or three arguments:
|
|
50
|
+
|
|
51
|
+
- `description: string`: A string describing the fixture. This should be used to explain what the fixture is expected to show.
|
|
52
|
+
- `props: FixtureProps<TProps>`: The props that the fixture should be rendered with. This can be either a plain object, or a function that returns a plain object. The function will be called with an API to assist in generating the props (see [`GetPropsOptions`](/docs/testing-fixtures-types-getpropsoptions--page)).
|
|
53
|
+
- `wrapper?: React.ComponentType<TProps>`: An optional component that will be rendered around the fixture. This can be used to wrap the fixture in a component that adds additional functionality, such as a test harness (see [`makeTestHarness`](/docs/testing-test-harness-exports-maketestharness--page)).
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Testing / Test Harness / Exports / harnessAdapters"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# harnessAdapters
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
/**
|
|
16
|
+
* The default adapters provided by Wonder Blocks.
|
|
17
|
+
*/
|
|
18
|
+
const DefaultAdapters = {
|
|
19
|
+
css: css.adapter,
|
|
20
|
+
data: data.adapter,
|
|
21
|
+
portal: portal.adapter,
|
|
22
|
+
router: router.adapter,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The default configurations to use with the `DefaultAdapters`.
|
|
27
|
+
*/
|
|
28
|
+
const DefaultConfigs: Configs<typeof DefaultAdapters> = {
|
|
29
|
+
css: css.defaultConfig,
|
|
30
|
+
data: data.defaultConfig,
|
|
31
|
+
portal: portal.defaultConfig,
|
|
32
|
+
router: router.defaultConfig,
|
|
33
|
+
};
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
These are the adapters available for use with the test harness framework and their default configurations. The [`testHarness()`](/docs/testing-test-harness-exports-testharness--page) and [`hookHarness()`](/docs/testing-test-harness-exports-hookharness--page) methods are constructed using these.
|
|
37
|
+
|
|
38
|
+
If you want to make your own test harness or hook harness using some of these defaults and some of your own, you can combine them into your call to [`makeTestHarness()`](/docs/testing-test-harness-exports-maketestharness--page) or [`makeHookHarness()`](/docs/testing-test-harness-exports-makehookharness--page).
|
|
39
|
+
|
|
40
|
+
There are four build-in adapters:
|
|
41
|
+
- [`css`](#css)
|
|
42
|
+
- [`data`](#data)
|
|
43
|
+
- [`portal`](#portal)
|
|
44
|
+
- [`router`](#router)
|
|
45
|
+
|
|
46
|
+
## css
|
|
47
|
+
|
|
48
|
+
The `css` adapter can be used to apply CSS classes and adhoc styles around the harnessed component.
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
type Config =
|
|
52
|
+
| string
|
|
53
|
+
| Array<string>
|
|
54
|
+
| CSSProperties
|
|
55
|
+
| {|
|
|
56
|
+
classes: Array<string>,
|
|
57
|
+
style: CSSProperties,
|
|
58
|
+
|};
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The configuration for this adapter can be a class name, an array of class names, an Aphrodite-compatible CSS style object, or an object definining both an array of `classes` and a `style` object.
|
|
62
|
+
|
|
63
|
+
The default configuration for this adapter is for it to not be used.
|
|
64
|
+
|
|
65
|
+
## data
|
|
66
|
+
|
|
67
|
+
The `data` adapter provides a convenient way to intercept Wonder Blocks Data requests. It renders one [`InterceptRequests`](/docs/data-exports-interceptrequests--page) component per configured interceptor.
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
type Interceptor = React.ElementConfig<typeof InterceptRequests>["interceptor"];
|
|
71
|
+
|
|
72
|
+
type Config = Interceptor | Array<Interceptor>;
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The configuration is one or more interceptors, as defined by the `interceptor` prop of the [`InterceptRequests`](/docs/data-exports-interceptrequests--page) component, which is effectively.
|
|
76
|
+
|
|
77
|
+
The default configuration for this adapter is for there to be no interceptors.
|
|
78
|
+
|
|
79
|
+
## portal
|
|
80
|
+
|
|
81
|
+
The `portal` adapter ensures there is a mounting point in the DOM for components that rely on rendering with a React portal.
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
type Config = string;
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The configuration is just a string providing the identifier to give the added element. The adapter will then render alongside the harnessed component, an empty `div` element with both the `id` and `data-test-id` attributes set to the configuration value.
|
|
88
|
+
|
|
89
|
+
The default configuration for this adapter is for it to not be used.
|
|
90
|
+
|
|
91
|
+
## router
|
|
92
|
+
|
|
93
|
+
The `router` adapter is useful for testing components that use React Router. It will render either a `MemoryRouter` or `StaticRouter`, depending on configuration. It may also optionally render a `Route` with suitable `path` match, depending on the configuration.
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
type Config =
|
|
97
|
+
| $ReadOnly<
|
|
98
|
+
| {|
|
|
99
|
+
/**
|
|
100
|
+
* See MemoryRouter prop for initialEntries.
|
|
101
|
+
*/
|
|
102
|
+
initialEntries: MemoryRouterProps["initialEntries"],
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* See MemoryRouter prop for initialIndex.
|
|
106
|
+
*/
|
|
107
|
+
initialIndex?: MemoryRouterProps["initialIndex"],
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* See MemoryRouter prop for getUserConfirmation.
|
|
111
|
+
*/
|
|
112
|
+
getUserConfirmation?: MemoryRouterProps["getUserConfirmation"],
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* A path match to use.
|
|
116
|
+
*
|
|
117
|
+
* When this is specified, the harnessed component will be
|
|
118
|
+
* rendered inside a `Route` handler with this path.
|
|
119
|
+
*
|
|
120
|
+
* If the path matches the location, then the route will
|
|
121
|
+
* render the component.
|
|
122
|
+
*
|
|
123
|
+
* If the path does not match the location, then the route
|
|
124
|
+
* will not render the component.
|
|
125
|
+
*/
|
|
126
|
+
path?: string,
|
|
127
|
+
|}
|
|
128
|
+
| {|
|
|
129
|
+
/**
|
|
130
|
+
* The location to use.
|
|
131
|
+
*/
|
|
132
|
+
location: string | Location,
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Force the use of a StaticRouter, instead of MemoryRouter.
|
|
136
|
+
*/
|
|
137
|
+
forceStatic: true,
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* A path match to use.
|
|
141
|
+
*
|
|
142
|
+
* When this is specified, the harnessed component will be
|
|
143
|
+
* rendered inside a `Route` handler with this path.
|
|
144
|
+
*
|
|
145
|
+
* If the path matches the location, then the route will
|
|
146
|
+
* render the component.
|
|
147
|
+
*
|
|
148
|
+
* If the path does not match the location, then the route
|
|
149
|
+
* will not render the component.
|
|
150
|
+
*/
|
|
151
|
+
path?: string,
|
|
152
|
+
|}
|
|
153
|
+
| {|
|
|
154
|
+
/**
|
|
155
|
+
* The initial location to use.
|
|
156
|
+
*/
|
|
157
|
+
location: string | LocationShape,
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* A path match to use.
|
|
161
|
+
*
|
|
162
|
+
* When this is specified, the harnessed component will be
|
|
163
|
+
* rendered inside a `Route` handler with this path.
|
|
164
|
+
*
|
|
165
|
+
* If the path matches the location, then the route will
|
|
166
|
+
* render the component.
|
|
167
|
+
*
|
|
168
|
+
* If the path does not match the location, then the route
|
|
169
|
+
* will not render the component.
|
|
170
|
+
*/
|
|
171
|
+
path?: string,
|
|
172
|
+
|},
|
|
173
|
+
>
|
|
174
|
+
// The initial location to use.
|
|
175
|
+
| string;
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
There are four distinct shapes to the configuration:
|
|
179
|
+
|
|
180
|
+
1. An object with `initialEntries` array (see `MemoryRouter` props), optional `initialIndex` and `getUserConfirmation` (see `MemoryRouter` props), and an optional `path` parameter if route matching is required.
|
|
181
|
+
1. An object with `forceStatic` set to true, the location as a `string` or `Location` object, with an optional `path` parameter if route matching is required.
|
|
182
|
+
1. An object specifying the location as a `string` or a `LocationShape` object, with an optional `path` parameter if route matching is required.
|
|
183
|
+
1. A `string` specifying the location to use
|
|
184
|
+
|
|
185
|
+
The first of these provides the most flexibility, basically supporting full configuration of a `MemoryRouter`, which supports history and navigation. The second configuration type is for scenarios where we absolutely do not want navigation, such as server-side rendering scenarios; it forces the use of a `StaticRouter` instance. The third type is for when you just need to render a single location with a matched route path. The fourth and final type allows you to just provide the location as a string.
|
|
186
|
+
|
|
187
|
+
By default, the router adapter is configured with `{location: "/"}`.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Testing / Test Harness / Exports / hookHarness()"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# hookHarness()
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
hookHarness(
|
|
16
|
+
configs?: $Shape<TestHarnessConfigs<typeof DefaultAdapters>>,
|
|
17
|
+
): React.AbstractComponent<any, any>;
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
This method can be used to create a test harness for use with the `wrapper` option of calls like `renderHook()` from `@testing-library/react-hooks` when writing tests for React hooks.
|
|
21
|
+
|
|
22
|
+
This method is created by using [`makeHookHarness`](/docs/testing-test-harness-exports-makehookharness--page) with [`harnessAdapters.DefaultAdapters` and `harnessAdapters.DefaultConfigs`](/docs/testing-test-harness-exports-harnessadapters--page).
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Testing / Test Harness / Exports / makeHookHarness()"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# makeHookHarness()
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
makeHookHarness<TAdapters: TestHarnessAdapters>(
|
|
16
|
+
adapters: TAdapters,
|
|
17
|
+
defaultConfigs: TestHarnessConfigs<TAdapters>,
|
|
18
|
+
): ((
|
|
19
|
+
configs?: $Shape<TestHarnessConfigs<TAdapters>>,
|
|
20
|
+
) => React.AbstractComponent<any, any>);
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
This method takes a set of adapters (such as [`harnessAdapters.DefaultAdapters`](/docs/testing-test-harness-exports-harnessadapters--page)) and a set of default configurations for those adapters (such as [`harnessAdapters.DefaultConfigs`](/docs/testing-test-harness-exports-harnessadapters--page)), and returns a function that can be called to create a component that applys those adapters with those default configs, or overrides to those configs.
|
|
24
|
+
|
|
25
|
+
This returned method can then be used for the `wrapper` option of calls like `renderHook()` from `@testing-library/react-hooks` when writing tests for React hooks.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Testing / Test Harness / Exports / makeTestHarness()"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# makeTestHarness()
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
makeTestHarness<TAdapters: TestHarnessAdapters>(
|
|
16
|
+
adapters: TAdapters,
|
|
17
|
+
defaultConfigs: TestHarnessConfigs<TAdapters>,
|
|
18
|
+
): (<-TProps, +Instance = mixed>(
|
|
19
|
+
Component: React.AbstractComponent<TProps, Instance>,
|
|
20
|
+
configs?: $Shape<TestHarnessConfigs<TAdapters>>,
|
|
21
|
+
) => React.AbstractComponent<TProps, Instance>);
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
This method takes a set of adapters (such as [`harnessAdapters.DefaultAdapters`](/docs/testing-test-harness-exports-harnessadapters--page)) and a set of default configurations for those adapters (such as [`harnessAdapters.DefaultConfigs`](/docs/testing-test-harness-exports-harnessadapters--page)), and returns a function that can be called to create a component that applys those adapters with those default configs, or overrides to those configs, around another component.
|
|
25
|
+
|
|
26
|
+
The returned method will ensure refs are forwarded to the harnessed component, and the component the method returns will have the same props as the component it is harnessing.
|
|
27
|
+
|
|
28
|
+
The harnessed component can be used in unit tests, such as in Jest, to reduce boilerplate needed to setup the test case. It can also be used as a a wrapper component when defining a fixture for a component in the Wonder Blocks Testing [Fixtures framework](/docs/testing-fixtures-overview--page).
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Testing / Mocking / Exports / mockFetch()"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# mockFetch()
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
mockFetch(): FetchMockFn;
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The `mockFetch` function provides an API to easily mock `fetch()` responses. It follows the similar patterns of `jest.fn()` and jest mocks whereby the returned value is both a proxy for the fetch function as well as an API for modifying the behavior of that function.
|
|
19
|
+
|
|
20
|
+
# API
|
|
21
|
+
|
|
22
|
+
Besides being a function that fits the `fetch()` signature, the return value of `mockFetch()` has an API to customize the behavior of that function. Used in conjunction with the [`RespondWith`](/docs/testing-mocking-exports-respondwith--page) API, this can create a variety of responses for tests and stories.
|
|
23
|
+
|
|
24
|
+
| Function | Purpose |
|
|
25
|
+
| -------- | ------- |
|
|
26
|
+
| `mockOperation` | When called, any request that matches the defined mock will respond with the given response. |
|
|
27
|
+
| `mockOperationOnce` | When called, the first request that matches the defined mock will respond with the given response. The mock is only used once. |
|
|
28
|
+
|
|
29
|
+
Both of these functions have the same signature:
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
type FetchMockOperationFn = (
|
|
33
|
+
operation: FetchMockOperation,
|
|
34
|
+
response: MockResponse<any>,
|
|
35
|
+
) => FetchMockFn;
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
# Operation Matching
|
|
39
|
+
|
|
40
|
+
The `FetchMockOperation` type is either of type `string` or `RegExp`. When specified as a string, the URL of the request must match the string exactly. When specified as a regular expression, the URL of the request must match the regular expression.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {Meta} from "@storybook/addon-docs";
|
|
2
2
|
|
|
3
3
|
<Meta
|
|
4
|
-
title="Testing / Exports / mockGqlFetch()"
|
|
4
|
+
title="Testing / Mocking / Exports / mockGqlFetch()"
|
|
5
5
|
parameters={{
|
|
6
6
|
chromatic: {
|
|
7
7
|
disableSnapshot: true,
|
|
@@ -19,19 +19,24 @@ The `mockGqlFetch` function provides an API to easily mock GraphQL responses for
|
|
|
19
19
|
|
|
20
20
|
# API
|
|
21
21
|
|
|
22
|
-
Besides being a function that fits the [`GqlFetchFn`](/docs/data-types-gqlfetchfn--page) signature, the return value of `mockGqlFetch()` has an API to customize the behavior of that function. Used in conjunction with the [`RespondWith`](/docs/testing-exports-respondwith--page) API, this can create a variety of GraphQL responses for testing and stories.
|
|
22
|
+
Besides being a function that fits the [`GqlFetchFn`](/docs/data-types-gqlfetchfn--page) signature, the return value of `mockGqlFetch()` has an API to customize the behavior of that function. Used in conjunction with the [`RespondWith`](/docs/testing-mocking-exports-respondwith--page) API, this can create a variety of GraphQL responses for testing and stories.
|
|
23
23
|
|
|
24
24
|
| Function | Purpose |
|
|
25
25
|
| -------- | ------- |
|
|
26
26
|
| `mockOperation` | When called, any GraphQL operation that matches the defined mock operation will respond with the given response. |
|
|
27
|
-
| `mockOperationOnce` | When called, the first GraphQL operation that matches the defined mock operation will respond with the given response. The mock is only used
|
|
27
|
+
| `mockOperationOnce` | When called, the first GraphQL operation that matches the defined mock operation will respond with the given response. The mock is only used once. |
|
|
28
28
|
|
|
29
29
|
Both of these functions have the same signature:
|
|
30
30
|
|
|
31
31
|
```ts
|
|
32
|
-
type GqlMockOperationFn = <
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
type GqlMockOperationFn = <
|
|
33
|
+
TData: {...},
|
|
34
|
+
TVariables: {...},
|
|
35
|
+
TContext: GqlContext,
|
|
36
|
+
TResponseData: GraphQLJson<TData>,
|
|
37
|
+
>(
|
|
38
|
+
operation: GqlMockOperation<TData, TVariables, TContext>,
|
|
39
|
+
response: MockResponse<TResponseData>,
|
|
35
40
|
) => GqlFetchMockFn;
|
|
36
41
|
```
|
|
37
42
|
|
|
@@ -40,8 +45,8 @@ type GqlMockOperationFn = <TData, TVariables: {...}, TContext: GqlContext>(
|
|
|
40
45
|
The `matchOperation` parameter given to a `mockOperation` or `mockOperationOnce` function is a `GqlMockOperation` defining the actual GraphQL operation to be matched by the mock. The variables and context of the mocked operation change how the mock is matched against requests.
|
|
41
46
|
|
|
42
47
|
```ts
|
|
43
|
-
|
|
44
|
-
TData,
|
|
48
|
+
type GqlMockOperation<
|
|
49
|
+
TData: {...},
|
|
45
50
|
TVariables: {...},
|
|
46
51
|
TContext: GqlContext,
|
|
47
52
|
> = {|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {Meta} from "@storybook/addon-docs";
|
|
2
2
|
|
|
3
3
|
<Meta
|
|
4
|
-
title="Testing / Exports / RespondWith"
|
|
4
|
+
title="Testing / Mocking / Exports / RespondWith"
|
|
5
5
|
parameters={{
|
|
6
6
|
chromatic: {
|
|
7
7
|
disableSnapshot: true,
|
|
@@ -13,15 +13,61 @@ import {Meta} from "@storybook/addon-docs";
|
|
|
13
13
|
|
|
14
14
|
```ts
|
|
15
15
|
interface RespondWith {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Rejects with an AbortError to simulate an aborted request.
|
|
18
|
+
*/
|
|
19
|
+
abortedRequest: () => MockResponse<any>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A non-200 status code with empty text body.
|
|
23
|
+
* Equivalent to calling `ResponseWith.text("", statusCode)`.
|
|
24
|
+
*/
|
|
25
|
+
errorStatusCode: (statusCode: number) => MockResponse<any>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Response with GraphQL data JSON body and status code 200.
|
|
29
|
+
*/
|
|
30
|
+
graphQLData: <TData: {...}>(
|
|
31
|
+
data: TData,
|
|
32
|
+
) => MockResponse<GraphQLJson<TData>>;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Response that is a GraphQL errors response with status code 200.
|
|
36
|
+
*/
|
|
21
37
|
graphQLErrors: (
|
|
22
38
|
errorMessages: $ReadOnlyArray<string>,
|
|
23
|
-
) =>
|
|
39
|
+
) => MockResponse<any>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Response with JSON body and status code 200.
|
|
43
|
+
*/
|
|
44
|
+
json: <TJson: {...}>(json: TJson): MockResponse<TJson>;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Response body that is valid JSON but not a valid GraphQL response.
|
|
48
|
+
*/
|
|
49
|
+
nonGraphQLBody: () => MockResponse<any>;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Rejects with the given error.
|
|
53
|
+
*/
|
|
54
|
+
reject: (error: Error) => MockResponse<any>;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Response with text body and status code.
|
|
58
|
+
* Status code defaults to 200.
|
|
59
|
+
*/
|
|
60
|
+
text: <TData = string>(
|
|
61
|
+
text: string,
|
|
62
|
+
statusCode: number = 200,
|
|
63
|
+
) => MockResponse<TData>;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Response with body that will not parse as JSON and status code 200.
|
|
67
|
+
*/
|
|
68
|
+
unparseableBody: () => MockResponse<any>;
|
|
24
69
|
});
|
|
25
70
|
```
|
|
26
71
|
|
|
27
|
-
The `RespondWith` object is a helper for defining mock responses to use with
|
|
72
|
+
The `RespondWith` object is a helper for defining mock responses to use with
|
|
73
|
+
mock request methods such as [`mockGqlFetch`](/docs/testing-mocking-exports-mockgqlfetch--page).
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Testing / Fixtures / Exports / setupFixtures()"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# setupFixtures()
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
setupFixtures<TAdapterOptions: {...}, TAdapterExports: {...}>(
|
|
16
|
+
configuration: $ReadOnly<
|
|
17
|
+
FixturesConfiguration<TAdapterOptions, TAdapterExports>,
|
|
18
|
+
>,
|
|
19
|
+
);
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
This method configures the fixtures framework so that it can adapt defined fixtures to the framework that is to be supported. The configuration is of type [`FixturesConfiguration`](/docs/testing-fixtures-types-fixturesconfiguration--page).
|