@khanacademy/wonder-blocks-testing 4.0.4 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/es/index.js +212 -26
- package/dist/index.js +589 -62
- package/package.json +4 -2
- 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/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
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
|
|
4
|
+
import {renderAdapters} from "./render-adapters.js";
|
|
5
|
+
|
|
6
|
+
import type {TestHarnessAdapters, TestHarnessConfigs} from "./types.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Create a test harness method for use with React components.
|
|
10
|
+
*
|
|
11
|
+
* This returns a test harness method that applies the default configurations
|
|
12
|
+
* to the given adapters, wrapping a given component.
|
|
13
|
+
*
|
|
14
|
+
* @param {TAdapters} adapters All the adapters to be supported by the returned
|
|
15
|
+
* test harness.
|
|
16
|
+
* @param {Configs<TAdapters>} defaultConfigs Default configuration values for
|
|
17
|
+
* the adapters.
|
|
18
|
+
* @returns {<-TProps, +Instance = mixed>(
|
|
19
|
+
* Component: React.AbstractComponent<TProps, Instance>,
|
|
20
|
+
* configs?: $Shape<Configs<TAdapters>>,
|
|
21
|
+
* ) => React.AbstractComponent<TProps, Instance>} A test harness.
|
|
22
|
+
*/
|
|
23
|
+
export const makeTestHarness = <TAdapters: TestHarnessAdapters>(
|
|
24
|
+
adapters: TAdapters,
|
|
25
|
+
defaultConfigs: TestHarnessConfigs<TAdapters>,
|
|
26
|
+
): (<-TProps, +Instance = mixed>(
|
|
27
|
+
Component: React.AbstractComponent<TProps, Instance>,
|
|
28
|
+
configs?: $Shape<TestHarnessConfigs<TAdapters>>,
|
|
29
|
+
) => React.AbstractComponent<TProps, Instance>) => {
|
|
30
|
+
/**
|
|
31
|
+
* Create a harnessed version of the given component.
|
|
32
|
+
*
|
|
33
|
+
* @param {React.AbstractComponent<TProps, Instance>} component The
|
|
34
|
+
* component to be wrapped.
|
|
35
|
+
* @param {$Shape<Configs<TAdapters>>} [configs] Any adapter
|
|
36
|
+
* configuration that you want to override from the `defaultConfigs` values.
|
|
37
|
+
*/
|
|
38
|
+
return <-TProps, +Instance = mixed>(
|
|
39
|
+
Component: React.AbstractComponent<TProps, Instance>,
|
|
40
|
+
configs?: $Shape<TestHarnessConfigs<TAdapters>>,
|
|
41
|
+
): React.AbstractComponent<TProps, Instance> => {
|
|
42
|
+
/**
|
|
43
|
+
* $FlowIgnore[cannot-spread-indexer]
|
|
44
|
+
* We know `configs` may overwrite `DefaultConfigs` and we're ok with it.
|
|
45
|
+
* The interface definition handles the typing for us so we're ok
|
|
46
|
+
* with it not being inferred here.
|
|
47
|
+
*/
|
|
48
|
+
const fullConfig: TestHarnessConfigs<TAdapters> = {
|
|
49
|
+
...defaultConfigs,
|
|
50
|
+
...configs,
|
|
51
|
+
};
|
|
52
|
+
const harnessedComponent = React.forwardRef((props, ref) =>
|
|
53
|
+
renderAdapters<TAdapters>(
|
|
54
|
+
adapters,
|
|
55
|
+
fullConfig,
|
|
56
|
+
<Component {...props} ref={ref} />,
|
|
57
|
+
),
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
// We add a name for the component here so that we can detect that
|
|
61
|
+
// later and also see it in traces and what have you.
|
|
62
|
+
harnessedComponent.displayName = `testHarness(${
|
|
63
|
+
Component.displayName || Component.name || "Component"
|
|
64
|
+
})`;
|
|
65
|
+
|
|
66
|
+
return harnessedComponent;
|
|
67
|
+
};
|
|
68
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
|
|
4
|
+
import type {TestHarnessConfigs, TestHarnessAdapters} from "./types.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Render test adapters around a child component.
|
|
8
|
+
*/
|
|
9
|
+
export const renderAdapters = <TAdapters: TestHarnessAdapters>(
|
|
10
|
+
adapters: TAdapters,
|
|
11
|
+
configs: TestHarnessConfigs<TAdapters>,
|
|
12
|
+
children: React.Node,
|
|
13
|
+
): React.Node => {
|
|
14
|
+
let currentChildren = children;
|
|
15
|
+
for (const adapterName of Object.keys(adapters)) {
|
|
16
|
+
const adapter = adapters[adapterName];
|
|
17
|
+
const config = configs[adapterName];
|
|
18
|
+
/**
|
|
19
|
+
* Some adapters support a null config, some don't, either way
|
|
20
|
+
* we always assume that null config means no adapter.
|
|
21
|
+
*/
|
|
22
|
+
if (config != null) {
|
|
23
|
+
currentChildren = adapter(currentChildren, config);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return currentChildren;
|
|
27
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
|
|
4
|
+
import {makeTestHarness} from "./make-test-harness.js";
|
|
5
|
+
import {DefaultAdapters, DefaultConfigs} from "./adapters/adapters.js";
|
|
6
|
+
|
|
7
|
+
import type {TestHarnessConfigs} from "./types.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Wrap a component with a test harness using Wonder Blocks default adapters.
|
|
11
|
+
*
|
|
12
|
+
* This is primarily useful for tests within Wonder Blocks.
|
|
13
|
+
*
|
|
14
|
+
* If you want to expand the range of adapters or change the default
|
|
15
|
+
* configurations, use `makeTestHarness` to create a new `testHarness`
|
|
16
|
+
* function.
|
|
17
|
+
*/
|
|
18
|
+
export const testHarness: <-TProps, +Instance = mixed>(
|
|
19
|
+
Component: React.AbstractComponent<TProps, Instance>,
|
|
20
|
+
configs?: $Shape<TestHarnessConfigs<typeof DefaultAdapters>>,
|
|
21
|
+
) => React.AbstractComponent<TProps, Instance> = makeTestHarness(
|
|
22
|
+
DefaultAdapters,
|
|
23
|
+
DefaultConfigs,
|
|
24
|
+
);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A adapter to be composed with our test harnass infrastructure.
|
|
6
|
+
*/
|
|
7
|
+
export type TestHarnessAdapter<-TConfig> = (
|
|
8
|
+
children: React.Node,
|
|
9
|
+
config: TConfig,
|
|
10
|
+
) => React.Element<any>;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A general map of adapters by their identifiers.
|
|
14
|
+
*
|
|
15
|
+
* It's OK that this has `any` for the config type as this is the very base
|
|
16
|
+
* version of a adapter set. In reality, a more specific type will be used
|
|
17
|
+
* with the harness functions that use more specific definitions of known
|
|
18
|
+
* adapters. This is just to support the base reality of not knowing.
|
|
19
|
+
*
|
|
20
|
+
* Use this on input positions only. Output positions for adapters
|
|
21
|
+
* should infer their type in most cases to ensure the strongest typing of
|
|
22
|
+
* the adapters.
|
|
23
|
+
*/
|
|
24
|
+
export type TestHarnessAdapters = {|
|
|
25
|
+
[adapterID: string]: TestHarnessAdapter<any>,
|
|
26
|
+
|};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Mapping functions from a adapter-like function to config type.
|
|
30
|
+
*/
|
|
31
|
+
type ExtractConfig = <TConfig>(TestHarnessAdapter<TConfig>) => TConfig;
|
|
32
|
+
type ExtractMaybeConfig = <TConfig>(TestHarnessAdapter<TConfig>) => ?TConfig;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Type for easily defining an adapter's config type.
|
|
36
|
+
*
|
|
37
|
+
* This is the `TestHarnessAdapter` equivalent of `React.ElementConfig`.
|
|
38
|
+
*/
|
|
39
|
+
export type TestHarnessConfig<-TAdapter> = $Call<ExtractConfig, TAdapter>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The `TestHarnessConfigs` type as defined by parsing a given set of adapters.
|
|
43
|
+
*
|
|
44
|
+
* NOTE: This only works if the properties of the passed `TAdapters` type
|
|
45
|
+
* are explicitly typed as `TestHarnessAdapter<TConfig>` so if passing in a
|
|
46
|
+
* non-Adapters type (which we should be, to get strong `TConfig` types instead
|
|
47
|
+
* of `any`), then that object should make sure that each adapter is strongly
|
|
48
|
+
* marked as `TestHarnessAdapter<TConfig>` - flow does not appear to pattern
|
|
49
|
+
* match against the type definition when invoking the `ExtractConfig` type and I
|
|
50
|
+
* haven't worked out how to get it to multi-dispatch so that it matches
|
|
51
|
+
* functions too. Even worse, if the type doesn't match, it just allows `any`
|
|
52
|
+
* in the `Configs` object, rather than indicating any kind of problem.
|
|
53
|
+
*/
|
|
54
|
+
export type TestHarnessConfigs<-TAdapters: TestHarnessAdapters> = $ObjMap<
|
|
55
|
+
TAdapters,
|
|
56
|
+
ExtractMaybeConfig,
|
|
57
|
+
>;
|
package/src/index.js
CHANGED
|
@@ -1,30 +1,34 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
|
|
3
3
|
// Fixtures framework
|
|
4
|
-
export * as
|
|
4
|
+
export * as fixtureAdapters from "./fixtures/adapters/adapters.js";
|
|
5
5
|
export {fixtures} from "./fixtures/fixtures.js";
|
|
6
6
|
export {setup as setupFixtures} from "./fixtures/setup.js";
|
|
7
7
|
export type {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
GetPropsOptions,
|
|
8
|
+
CustomMountProps,
|
|
9
|
+
FixturesAdapter,
|
|
10
|
+
FixturesAdapterFactory,
|
|
11
|
+
FixturesAdapterFixtureOptions,
|
|
12
|
+
FixturesAdapterGroup,
|
|
13
|
+
FixturesAdapterGroupOptions,
|
|
14
|
+
FixturesAdapterOptions,
|
|
15
|
+
FixturesConfiguration,
|
|
17
16
|
FixturesOptions,
|
|
17
|
+
GetPropsOptions,
|
|
18
18
|
} from "./fixtures/types.js";
|
|
19
19
|
|
|
20
20
|
// Fetch mocking framework
|
|
21
|
-
export type {MockResponse} from "./make-mock-response.js";
|
|
22
|
-
export {RespondWith} from "./make-mock-response.js";
|
|
23
21
|
export {mockFetch} from "./fetch/mock-fetch.js";
|
|
24
|
-
export type {
|
|
25
|
-
FetchMockFn,
|
|
26
|
-
FetchMock,
|
|
27
|
-
FetchMockOperation,
|
|
28
|
-
} from "./fetch/types.js";
|
|
29
22
|
export {mockGqlFetch} from "./gql/mock-gql-fetch.js";
|
|
30
|
-
export
|
|
23
|
+
export {RespondWith} from "./make-mock-response.js";
|
|
24
|
+
export type {MockResponse} from "./make-mock-response.js";
|
|
25
|
+
export type {FetchMockFn, FetchMockOperation} from "./fetch/types.js";
|
|
26
|
+
export type {GqlFetchMockFn, GqlMockOperation} from "./gql/types.js";
|
|
27
|
+
|
|
28
|
+
// Test harness framework
|
|
29
|
+
export * from "./harness/types.js";
|
|
30
|
+
export * as harnessAdapters from "./harness/adapters/adapters.js";
|
|
31
|
+
export {makeHookHarness} from "./harness/make-hook-harness.js";
|
|
32
|
+
export {makeTestHarness} from "./harness/make-test-harness.js";
|
|
33
|
+
export {hookHarness} from "./harness/hook-harness.js";
|
|
34
|
+
export {testHarness} from "./harness/test-harness.js";
|