@khanacademy/wonder-blocks-testing 10.1.0 → 11.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 +25 -0
- package/dist/es/index.js +25 -386
- package/dist/gql/types.d.ts +1 -2
- package/dist/harness/adapters/data.d.ts +1 -1
- package/dist/harness/adapters/index.d.ts +41 -0
- package/dist/harness/adapters/ssr.d.ts +1 -1
- package/dist/index.d.ts +8 -13
- package/dist/index.js +61 -395
- package/package.json +8 -6
- package/src/gql/__tests__/mock-gql-fetch.test.tsx +1 -1
- package/src/gql/__tests__/types.typestest.ts +1 -1
- package/src/gql/__tests__/wb-data-integration.test.tsx +1 -1
- package/src/gql/mock-gql-fetch.ts +1 -1
- package/src/gql/types.ts +4 -2
- package/src/harness/adapters/__tests__/ssr.test.tsx +1 -1
- package/src/harness/adapters/data.tsx +1 -1
- package/src/harness/adapters/{adapters.ts → index.ts} +10 -11
- package/src/harness/adapters/ssr.tsx +1 -1
- package/src/index.ts +32 -13
- package/tsconfig-build.json +1 -0
- package/tsconfig-build.tsbuildinfo +1 -1
- package/dist/fetch/fetch-request-matches-mock.d.ts +0 -5
- package/dist/fetch/mock-fetch.d.ts +0 -5
- package/dist/fetch/types.d.ts +0 -9
- package/dist/fixtures/fixtures.basic.stories.d.ts +0 -13
- package/dist/fixtures/fixtures.d.ts +0 -13
- package/dist/fixtures/fixtures.defaultwrapper.stories.d.ts +0 -9
- package/dist/fixtures/types.d.ts +0 -36
- package/dist/harness/adapt.d.ts +0 -17
- package/dist/harness/adapters/adapters.d.ts +0 -36
- package/dist/harness/adapters/css.d.ts +0 -12
- package/dist/harness/adapters/portal.d.ts +0 -12
- package/dist/harness/adapters/router.d.ts +0 -94
- package/dist/harness/get-named-adapter-component.d.ts +0 -16
- package/dist/harness/hook-harness.d.ts +0 -13
- package/dist/harness/make-hook-harness.d.ts +0 -17
- package/dist/harness/make-test-harness.d.ts +0 -15
- package/dist/harness/test-harness.d.ts +0 -33
- package/dist/harness/types.d.ts +0 -36
- package/dist/mock-requester.d.ts +0 -5
- package/dist/respond-with.d.ts +0 -75
- package/dist/response-impl.d.ts +0 -1
- package/dist/settle-controller.d.ts +0 -19
- package/dist/settle-signal.d.ts +0 -18
- package/dist/types.d.ts +0 -25
- package/src/__tests__/mock-requester.test.ts +0 -212
- package/src/__tests__/respond-with.test.ts +0 -524
- package/src/__tests__/response-impl.test.js +0 -47
- package/src/__tests__/settle-controller.test.ts +0 -28
- package/src/__tests__/settle-signal.test.ts +0 -104
- package/src/fetch/__tests__/__snapshots__/mock-fetch.test.ts.snap +0 -29
- package/src/fetch/__tests__/fetch-request-matches-mock.test.ts +0 -98
- package/src/fetch/__tests__/mock-fetch.test.ts +0 -83
- package/src/fetch/fetch-request-matches-mock.ts +0 -42
- package/src/fetch/mock-fetch.ts +0 -20
- package/src/fetch/types.ts +0 -14
- package/src/fixtures/__tests__/fixtures.test.tsx +0 -147
- package/src/fixtures/fixtures.basic.stories.tsx +0 -62
- package/src/fixtures/fixtures.defaultwrapper.stories.tsx +0 -49
- package/src/fixtures/fixtures.tsx +0 -72
- package/src/fixtures/types.ts +0 -42
- package/src/harness/__tests__/adapt.test.tsx +0 -248
- package/src/harness/__tests__/hook-harness.test.ts +0 -73
- package/src/harness/__tests__/make-hook-harness.test.tsx +0 -93
- package/src/harness/__tests__/make-test-harness.test.tsx +0 -195
- package/src/harness/__tests__/test-harness.test.ts +0 -75
- package/src/harness/__tests__/types.typestest.tsx +0 -103
- package/src/harness/adapt.tsx +0 -41
- package/src/harness/adapters/__tests__/__snapshots__/router.test.tsx.snap +0 -5
- package/src/harness/adapters/__tests__/css.test.tsx +0 -95
- package/src/harness/adapters/__tests__/portal.test.tsx +0 -30
- package/src/harness/adapters/__tests__/router.test.tsx +0 -252
- package/src/harness/adapters/css.tsx +0 -66
- package/src/harness/adapters/portal.tsx +0 -25
- package/src/harness/adapters/router.tsx +0 -205
- package/src/harness/get-named-adapter-component.tsx +0 -36
- package/src/harness/hook-harness.ts +0 -22
- package/src/harness/make-hook-harness.tsx +0 -40
- package/src/harness/make-test-harness.tsx +0 -60
- package/src/harness/test-harness.ts +0 -13
- package/src/harness/types.ts +0 -47
- package/src/mock-requester.ts +0 -68
- package/src/respond-with.ts +0 -263
- package/src/response-impl.ts +0 -8
- package/src/settle-controller.ts +0 -34
- package/src/settle-signal.ts +0 -42
- package/src/types.ts +0 -40
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/// <reference path="../../../types/aphrodite.d.ts" />
|
|
2
|
-
import type { TestHarnessConfigs } from "../types";
|
|
3
|
-
/**
|
|
4
|
-
* NOTE: We do not type `DefaultAdapters` with `Adapters` here because we want
|
|
5
|
-
* the individual config types of each adapter to remain intact rather than
|
|
6
|
-
* getting changed to `any`.
|
|
7
|
-
*/
|
|
8
|
-
/**
|
|
9
|
-
* The default adapters provided by Wonder Blocks.
|
|
10
|
-
*/
|
|
11
|
-
export declare const DefaultAdapters: {
|
|
12
|
-
readonly css: import("../types").TestHarnessAdapter<string | string[] | import("aphrodite").CSSProperties | {
|
|
13
|
-
classes: string[];
|
|
14
|
-
style: import("aphrodite").CSSProperties;
|
|
15
|
-
}>;
|
|
16
|
-
readonly data: import("../types").TestHarnessAdapter<((requestId: string) => Promise<import("@khanacademy/wonder-blocks-data").ValidCacheData> | null | undefined) | ((requestId: string) => Promise<import("@khanacademy/wonder-blocks-data").ValidCacheData> | null | undefined)[]>;
|
|
17
|
-
readonly portal: import("../types").TestHarnessAdapter<string>;
|
|
18
|
-
readonly router: import("../types").TestHarnessAdapter<string | Readonly<{
|
|
19
|
-
initialEntries: import("history").LocationDescriptor<unknown>[] | undefined;
|
|
20
|
-
initialIndex?: number | undefined;
|
|
21
|
-
getUserConfirmation?: ((message: string, callback: (ok: boolean) => void) => void) | undefined;
|
|
22
|
-
path?: string | undefined;
|
|
23
|
-
} | {
|
|
24
|
-
location: import("history").LocationDescriptor<unknown>;
|
|
25
|
-
forceStatic: true;
|
|
26
|
-
path?: string | undefined;
|
|
27
|
-
} | {
|
|
28
|
-
location: import("history").LocationDescriptor<unknown>;
|
|
29
|
-
path?: string | undefined;
|
|
30
|
-
}>>;
|
|
31
|
-
readonly ssr: import("../types").TestHarnessAdapter<true>;
|
|
32
|
-
};
|
|
33
|
-
/**
|
|
34
|
-
* The default configurations to use with the `DefaultAdapters`.
|
|
35
|
-
*/
|
|
36
|
-
export declare const DefaultConfigs: TestHarnessConfigs<typeof DefaultAdapters>;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { CSSProperties } from "aphrodite";
|
|
2
|
-
import type { TestHarnessAdapter } from "../types";
|
|
3
|
-
type Config = string | Array<string> | CSSProperties | {
|
|
4
|
-
classes: Array<string>;
|
|
5
|
-
style: CSSProperties;
|
|
6
|
-
};
|
|
7
|
-
export declare const defaultConfig: Config | null | undefined;
|
|
8
|
-
/**
|
|
9
|
-
* Test harness adapter for adding CSS to the harnessed component wrapper.
|
|
10
|
-
*/
|
|
11
|
-
export declare const adapter: TestHarnessAdapter<Config>;
|
|
12
|
-
export {};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { TestHarnessAdapter } from "../types";
|
|
2
|
-
type Config = string;
|
|
3
|
-
export declare const defaultConfig: Config | null | undefined;
|
|
4
|
-
/**
|
|
5
|
-
* Test harness adapter for supporting portals.
|
|
6
|
-
*
|
|
7
|
-
* Some components rely on rendering with a React Portal. This adapter ensures
|
|
8
|
-
* that the DOM contains a mounting point for the portal with the expected
|
|
9
|
-
* identifier.
|
|
10
|
-
*/
|
|
11
|
-
export declare const adapter: TestHarnessAdapter<Config>;
|
|
12
|
-
export {};
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { MemoryRouter } from "react-router-dom";
|
|
3
|
-
import type { LocationDescriptor } from "history";
|
|
4
|
-
import type { TestHarnessAdapter } from "../types";
|
|
5
|
-
type MemoryRouterProps = JSX.LibraryManagedAttributes<typeof MemoryRouter, React.ComponentProps<typeof MemoryRouter>>;
|
|
6
|
-
/**
|
|
7
|
-
* Configuration for the withLocation test harness adapter.
|
|
8
|
-
*/
|
|
9
|
-
type Config = Readonly<{
|
|
10
|
-
/**
|
|
11
|
-
* See MemoryRouter prop for initialEntries.
|
|
12
|
-
*/
|
|
13
|
-
initialEntries: MemoryRouterProps["initialEntries"];
|
|
14
|
-
/**
|
|
15
|
-
* See MemoryRouter prop for initialIndex.
|
|
16
|
-
*/
|
|
17
|
-
initialIndex?: MemoryRouterProps["initialIndex"];
|
|
18
|
-
/**
|
|
19
|
-
* See MemoryRouter prop for getUserConfirmation.
|
|
20
|
-
*/
|
|
21
|
-
getUserConfirmation?: MemoryRouterProps["getUserConfirmation"];
|
|
22
|
-
/**
|
|
23
|
-
* A path match to use.
|
|
24
|
-
*
|
|
25
|
-
* When this is specified, the harnessed component will be
|
|
26
|
-
* rendered inside a `Route` handler with this path.
|
|
27
|
-
*
|
|
28
|
-
* If the path matches the location, then the route will
|
|
29
|
-
* render the component.
|
|
30
|
-
*
|
|
31
|
-
* If the path does not match the location, then the route
|
|
32
|
-
* will not render the component.
|
|
33
|
-
*/
|
|
34
|
-
path?: string;
|
|
35
|
-
} | {
|
|
36
|
-
/**
|
|
37
|
-
* The location to use.
|
|
38
|
-
*/
|
|
39
|
-
location: LocationDescriptor;
|
|
40
|
-
/**
|
|
41
|
-
* Force the use of a StaticRouter, instead of MemoryRouter.
|
|
42
|
-
*/
|
|
43
|
-
forceStatic: true;
|
|
44
|
-
/**
|
|
45
|
-
* A path match to use.
|
|
46
|
-
*
|
|
47
|
-
* When this is specified, the harnessed component will be
|
|
48
|
-
* rendered inside a `Route` handler with this path.
|
|
49
|
-
*
|
|
50
|
-
* If the path matches the location, then the route will
|
|
51
|
-
* render the component.
|
|
52
|
-
*
|
|
53
|
-
* If the path does not match the location, then the route
|
|
54
|
-
* will not render the component.
|
|
55
|
-
*/
|
|
56
|
-
path?: string;
|
|
57
|
-
} | {
|
|
58
|
-
/**
|
|
59
|
-
* The initial location to use.
|
|
60
|
-
*/
|
|
61
|
-
location: LocationDescriptor;
|
|
62
|
-
/**
|
|
63
|
-
* A path match to use.
|
|
64
|
-
*
|
|
65
|
-
* When this is specified, the harnessed component will be
|
|
66
|
-
* rendered inside a `Route` handler with this path.
|
|
67
|
-
*
|
|
68
|
-
* If the path matches the location, then the route will
|
|
69
|
-
* render the component.
|
|
70
|
-
*
|
|
71
|
-
* If the path does not match the location, then the route
|
|
72
|
-
* will not render the component.
|
|
73
|
-
*/
|
|
74
|
-
path?: string;
|
|
75
|
-
}> | string;
|
|
76
|
-
/**
|
|
77
|
-
* The default configuration for this adapter.
|
|
78
|
-
*/
|
|
79
|
-
export declare const defaultConfig: {
|
|
80
|
-
readonly location: "/";
|
|
81
|
-
};
|
|
82
|
-
/**
|
|
83
|
-
* Adapter that sets up a router and AppShell location-specific contexts.
|
|
84
|
-
*
|
|
85
|
-
* This allows you to ensure that components are being tested in the
|
|
86
|
-
* AppShell world.
|
|
87
|
-
*
|
|
88
|
-
* NOTE(somewhatabstract): The AppShell component itself already does
|
|
89
|
-
* the work of setting up routing and the AppShellContext and so using this
|
|
90
|
-
* adapter with the App component will have zero-effect since AppShell will
|
|
91
|
-
* override it.
|
|
92
|
-
*/
|
|
93
|
-
export declare const adapter: TestHarnessAdapter<Config>;
|
|
94
|
-
export {};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import type { TestHarnessAdapter } from "./types";
|
|
3
|
-
type Props<TConfig = any> = {
|
|
4
|
-
children: React.ReactNode;
|
|
5
|
-
config: TConfig;
|
|
6
|
-
adapter: TestHarnessAdapter<TConfig>;
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* Get a component tagged with the given name for rendering an adapter.
|
|
10
|
-
*
|
|
11
|
-
* We can share these across invocations because only the name is used.
|
|
12
|
-
* The rest is configured at render time. This way we don't recreate new
|
|
13
|
-
* components on the fly and cause remounting to occur.
|
|
14
|
-
*/
|
|
15
|
-
export declare const getNamedAdapterComponent: (name: string) => React.FunctionComponent<Props<any>>;
|
|
16
|
-
export {};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { DefaultAdapters } from "./adapters/adapters";
|
|
3
|
-
import type { TestHarnessConfigs } from "./types";
|
|
4
|
-
/**
|
|
5
|
-
* Create test wrapper for hook testing with Wonder Blocks default adapters.
|
|
6
|
-
*
|
|
7
|
-
* This is primarily useful for tests within Wonder Blocks.
|
|
8
|
-
*
|
|
9
|
-
* If you want to expand the range of adapters or change the default
|
|
10
|
-
* configurations, use `makeHookHarness` to create a new `hookHarness`
|
|
11
|
-
* function.
|
|
12
|
-
*/
|
|
13
|
-
export declare const hookHarness: (configs?: Partial<TestHarnessConfigs<typeof DefaultAdapters>>) => React.ForwardRefExoticComponent<any>;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import type { TestHarnessAdapters, TestHarnessConfigs } from "./types";
|
|
3
|
-
/**
|
|
4
|
-
* Create a test harness method for use with React hooks.
|
|
5
|
-
*
|
|
6
|
-
* This returns a test harness method that applies the default configurations
|
|
7
|
-
* to the given adapters, wrapping a given component.
|
|
8
|
-
*
|
|
9
|
-
* @param {TAdapters} adapters All the adapters to be supported by the returned
|
|
10
|
-
* test harness.
|
|
11
|
-
* @param {TestHarnessConfigs<TAdapters>} defaultConfigs Default configuration values for
|
|
12
|
-
* the adapters.
|
|
13
|
-
* @returns {(
|
|
14
|
-
* configs?: $Shape<TestHarnessConfigs<TAdapters>>,
|
|
15
|
-
* ) => React.AbstractComponent<any, any>} A test harness.
|
|
16
|
-
*/
|
|
17
|
-
export declare const makeHookHarness: <TAdapters extends TestHarnessAdapters>(adapters: TAdapters, defaultConfigs: TestHarnessConfigs<TAdapters>) => (configs?: Partial<TestHarnessConfigs<TAdapters>> | undefined) => React.ForwardRefExoticComponent<any>;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import type { TestHarnessAdapters, TestHarnessConfigs } from "./types";
|
|
3
|
-
/**
|
|
4
|
-
* Create a test harness method for use with React components.
|
|
5
|
-
*
|
|
6
|
-
* This returns a test harness method that applies the default configurations
|
|
7
|
-
* to the given adapters, wrapping a given component.
|
|
8
|
-
*
|
|
9
|
-
* @param {TAdapters} adapters All the adapters to be supported by the returned
|
|
10
|
-
* test harness.
|
|
11
|
-
* @param {Configs<TAdapters>} defaultConfigs Default configuration values for
|
|
12
|
-
* the adapters.
|
|
13
|
-
* @returns A test harness.
|
|
14
|
-
*/
|
|
15
|
-
export declare const makeTestHarness: <TAdapters extends TestHarnessAdapters>(adapters: TAdapters, defaultConfigs: TestHarnessConfigs<TAdapters>) => <TProps extends object>(Component: React.ComponentType<TProps>, configs?: Partial<TestHarnessConfigs<TAdapters>> | undefined) => React.ForwardRefExoticComponent<React.PropsWithoutRef<TProps> & React.RefAttributes<unknown>>;
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/// <reference path="../../types/aphrodite.d.ts" />
|
|
2
|
-
/// <reference types="react" />
|
|
3
|
-
/**
|
|
4
|
-
* Wrap a component with a test harness using Wonder Blocks default adapters.
|
|
5
|
-
*
|
|
6
|
-
* This is primarily useful for tests within Wonder Blocks.
|
|
7
|
-
*
|
|
8
|
-
* If you want to expand the range of adapters or change the default
|
|
9
|
-
* configurations, use `makeTestHarness` to create a new `testHarness`
|
|
10
|
-
* function.
|
|
11
|
-
*/
|
|
12
|
-
export declare const testHarness: <TProps extends object>(Component: import("react").ComponentType<TProps>, configs?: Partial<import("./types").TestHarnessConfigs<{
|
|
13
|
-
readonly css: import("./types").TestHarnessAdapter<string | string[] | import("aphrodite").CSSProperties | {
|
|
14
|
-
classes: string[];
|
|
15
|
-
style: import("aphrodite").CSSProperties;
|
|
16
|
-
}>;
|
|
17
|
-
readonly data: import("./types").TestHarnessAdapter<((requestId: string) => Promise<import("@khanacademy/wonder-blocks-data").ValidCacheData> | null | undefined) | ((requestId: string) => Promise<import("@khanacademy/wonder-blocks-data").ValidCacheData> | null | undefined)[]>;
|
|
18
|
-
readonly portal: import("./types").TestHarnessAdapter<string>;
|
|
19
|
-
readonly router: import("./types").TestHarnessAdapter<string | Readonly<{
|
|
20
|
-
initialEntries: import("history").LocationDescriptor<unknown>[] | undefined;
|
|
21
|
-
initialIndex?: number | undefined;
|
|
22
|
-
getUserConfirmation?: ((message: string, callback: (ok: boolean) => void) => void) | undefined;
|
|
23
|
-
path?: string | undefined;
|
|
24
|
-
} | {
|
|
25
|
-
location: import("history").LocationDescriptor<unknown>;
|
|
26
|
-
forceStatic: true;
|
|
27
|
-
path?: string | undefined;
|
|
28
|
-
} | {
|
|
29
|
-
location: import("history").LocationDescriptor<unknown>;
|
|
30
|
-
path?: string | undefined;
|
|
31
|
-
}>>;
|
|
32
|
-
readonly ssr: import("./types").TestHarnessAdapter<true>;
|
|
33
|
-
}>> | undefined) => import("react").ForwardRefExoticComponent<import("react").PropsWithoutRef<TProps> & import("react").RefAttributes<unknown>>;
|
package/dist/harness/types.d.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
/**
|
|
3
|
-
* A adapter to be composed with our test harness infrastructure.
|
|
4
|
-
*/
|
|
5
|
-
export type TestHarnessAdapter<TConfig> = (children: React.ReactNode, config: TConfig) => React.ReactElement;
|
|
6
|
-
/**
|
|
7
|
-
* A general map of adapters by their identifiers.
|
|
8
|
-
*
|
|
9
|
-
* It's OK that this has `any` for the config type as this is the very base
|
|
10
|
-
* version of a adapter set. In reality, a more specific type will be used
|
|
11
|
-
* with the harness functions that use more specific definitions of known
|
|
12
|
-
* adapters. This is just to support the base reality of not knowing.
|
|
13
|
-
*
|
|
14
|
-
* Use this on input positions only. Output positions for adapters
|
|
15
|
-
* should infer their type in most cases to ensure the strongest typing of
|
|
16
|
-
* the adapters.
|
|
17
|
-
*/
|
|
18
|
-
export type TestHarnessAdapters = {
|
|
19
|
-
readonly [adapterID: string]: TestHarnessAdapter<any>;
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* Type for easily defining an adapter's config type.
|
|
23
|
-
*/
|
|
24
|
-
export type TestHarnessConfig<TAdapter> = TAdapter extends TestHarnessAdapter<infer TConfig> ? TConfig : never;
|
|
25
|
-
/**
|
|
26
|
-
* The `TestHarnessConfigs` type as defined by parsing a given set of adapters.
|
|
27
|
-
*
|
|
28
|
-
* NOTE: This only works if the properties of the passed `TAdapters` type
|
|
29
|
-
* are explicitly typed as `TestHarnessAdapter<TConfig>` so if passing in a
|
|
30
|
-
* non-Adapters type (which we should be, to get strong `TConfig` types instead
|
|
31
|
-
* of `any`), then that object should make sure that each adapter is strongly
|
|
32
|
-
* marked as `TestHarnessAdapter<TConfig>`
|
|
33
|
-
*/
|
|
34
|
-
export type TestHarnessConfigs<TAdapters extends TestHarnessAdapters> = {
|
|
35
|
-
[K in keyof TAdapters]: TestHarnessConfig<TAdapters[K]> | null | undefined;
|
|
36
|
-
};
|
package/dist/mock-requester.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { OperationMatcher, MockFn } from "./types";
|
|
2
|
-
/**
|
|
3
|
-
* A generic mock request function for using when mocking fetch or gqlFetch.
|
|
4
|
-
*/
|
|
5
|
-
export declare const mockRequester: <TOperationType>(operationMatcher: OperationMatcher<any>, operationToString: (...args: Array<any>) => string) => MockFn<TOperationType>;
|
package/dist/respond-with.d.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { SettleSignal } from "./settle-signal";
|
|
2
|
-
import type { GraphQLJson } from "./types";
|
|
3
|
-
/**
|
|
4
|
-
* This symbol is used so we can create an opaque type, using a custom field
|
|
5
|
-
* that cannot be directly referenced since folks won't have access to the
|
|
6
|
-
* symbol.
|
|
7
|
-
*
|
|
8
|
-
* See https://stackoverflow.com/a/56749647/23234
|
|
9
|
-
*/
|
|
10
|
-
declare const opaque: unique symbol;
|
|
11
|
-
/**
|
|
12
|
-
* Describes a mock response to a fetch request.
|
|
13
|
-
*/
|
|
14
|
-
export type MockResponse<TData> = {
|
|
15
|
-
/**
|
|
16
|
-
* This is used to enforce the use of the TData type parameter. We won't
|
|
17
|
-
* actually attach anything to this field. Doing this makes sure that
|
|
18
|
-
* TData is relevant to the response. Without it, it will get ignored
|
|
19
|
-
* and a value of type MockResponse<string> will be considered the same
|
|
20
|
-
* type as a value of type MockResponse<number> (or any other type
|
|
21
|
-
* constraint).
|
|
22
|
-
*/
|
|
23
|
-
[opaque]: TData;
|
|
24
|
-
/**
|
|
25
|
-
* Create a promise from the mocked response.
|
|
26
|
-
*
|
|
27
|
-
* If a signal was provided when the mock response was created, the promise
|
|
28
|
-
* will only settle to resolution or rejection if the signal is raised.
|
|
29
|
-
*/
|
|
30
|
-
readonly toPromise: () => Promise<Response>;
|
|
31
|
-
};
|
|
32
|
-
/**
|
|
33
|
-
* Helpers to define mock responses for mocked requests.
|
|
34
|
-
*/
|
|
35
|
-
export declare const RespondWith: Readonly<{
|
|
36
|
-
/**
|
|
37
|
-
* Response with text body and status code.
|
|
38
|
-
* Status code defaults to 200.
|
|
39
|
-
*/
|
|
40
|
-
text: <TData = string>(text: string, statusCode?: number, signal?: SettleSignal | null) => MockResponse<TData>;
|
|
41
|
-
/**
|
|
42
|
-
* Response with JSON body and status code 200.
|
|
43
|
-
*/
|
|
44
|
-
json: <TJson extends Record<any, any>>(json: TJson, signal?: SettleSignal | null) => MockResponse<TJson>;
|
|
45
|
-
/**
|
|
46
|
-
* Response with GraphQL data JSON body and status code 200.
|
|
47
|
-
*/
|
|
48
|
-
graphQLData: <TData_1 extends Record<any, any>>(data: TData_1, signal?: SettleSignal | null) => MockResponse<GraphQLJson<TData_1>>;
|
|
49
|
-
/**
|
|
50
|
-
* Response with body that will not parse as JSON and status code 200.
|
|
51
|
-
*/
|
|
52
|
-
unparseableBody: (signal?: SettleSignal | null) => MockResponse<any>;
|
|
53
|
-
/**
|
|
54
|
-
* Rejects with an AbortError to simulate an aborted request.
|
|
55
|
-
*/
|
|
56
|
-
abortedRequest: (signal?: SettleSignal | null) => MockResponse<any>;
|
|
57
|
-
/**
|
|
58
|
-
* Rejects with the given error.
|
|
59
|
-
*/
|
|
60
|
-
reject: (error: Error, signal?: SettleSignal | null) => MockResponse<any>;
|
|
61
|
-
/**
|
|
62
|
-
* A non-200 status code with empty text body.
|
|
63
|
-
* Equivalent to calling `ResponseWith.text("", statusCode)`.
|
|
64
|
-
*/
|
|
65
|
-
errorStatusCode: (statusCode: number, signal?: SettleSignal | null) => MockResponse<any>;
|
|
66
|
-
/**
|
|
67
|
-
* Response body that is valid JSON but not a valid GraphQL response.
|
|
68
|
-
*/
|
|
69
|
-
nonGraphQLBody: (signal?: SettleSignal | null) => MockResponse<any>;
|
|
70
|
-
/**
|
|
71
|
-
* Response that is a GraphQL errors response with status code 200.
|
|
72
|
-
*/
|
|
73
|
-
graphQLErrors: (errorMessages: ReadonlyArray<string>, signal?: SettleSignal | null) => MockResponse<GraphQLJson<any>>;
|
|
74
|
-
}>;
|
|
75
|
-
export {};
|
package/dist/response-impl.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const ResponseImpl: typeof Response;
|
|
@@ -1,19 +0,0 @@
|
|
|
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
|
-
}
|
package/dist/settle-signal.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
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
|
-
}
|
package/dist/types.d.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
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>;
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
import {RespondWith} from "../respond-with";
|
|
2
|
-
import {mockRequester} from "../mock-requester";
|
|
3
|
-
|
|
4
|
-
describe("#mockRequester", () => {
|
|
5
|
-
it("should return a function", () => {
|
|
6
|
-
// Arrange
|
|
7
|
-
|
|
8
|
-
// Act
|
|
9
|
-
const result = mockRequester(jest.fn(), jest.fn());
|
|
10
|
-
|
|
11
|
-
// Assert
|
|
12
|
-
expect(result).toBeInstanceOf(Function);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it("should provide mockOperation API", () => {
|
|
16
|
-
// Arrange
|
|
17
|
-
|
|
18
|
-
// Act
|
|
19
|
-
const result = mockRequester(jest.fn(), jest.fn());
|
|
20
|
-
|
|
21
|
-
// Assert
|
|
22
|
-
expect(result).toHaveProperty("mockOperation", expect.any(Function));
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it("should provide mockOperationOnce API", () => {
|
|
26
|
-
// Arrange
|
|
27
|
-
|
|
28
|
-
// Act
|
|
29
|
-
const result = mockRequester(jest.fn(), jest.fn());
|
|
30
|
-
|
|
31
|
-
// Assert
|
|
32
|
-
expect(result).toHaveProperty(
|
|
33
|
-
"mockOperationOnce",
|
|
34
|
-
expect.any(Function),
|
|
35
|
-
);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it("should throw with helpful details formatted by operationToString if no matching mock is found", async () => {
|
|
39
|
-
// Arrange
|
|
40
|
-
const mockFn = mockRequester(
|
|
41
|
-
jest.fn(),
|
|
42
|
-
(...args: any) => `TEST FORMATTING: ${JSON.stringify(args)}`,
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
// Act
|
|
46
|
-
const underTest = mockFn("any", "arguments", {we: {want: 42}});
|
|
47
|
-
|
|
48
|
-
// Assert
|
|
49
|
-
await expect(underTest).rejects.toThrowErrorMatchingInlineSnapshot(`
|
|
50
|
-
"No matching mock response found for request:
|
|
51
|
-
TEST FORMATTING: ["any","arguments",{"we":{"want":42}}]"
|
|
52
|
-
`);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
describe("mockOperation", () => {
|
|
56
|
-
it("should invoke matcher with mock for a request", async () => {
|
|
57
|
-
// Arrange
|
|
58
|
-
const matcher = jest.fn().mockReturnValue(true);
|
|
59
|
-
const operationToString = jest.fn();
|
|
60
|
-
const mockFn = mockRequester(matcher, operationToString);
|
|
61
|
-
|
|
62
|
-
// Act
|
|
63
|
-
mockFn.mockOperation(
|
|
64
|
-
"THE MOCK DESCRIPTION",
|
|
65
|
-
RespondWith.text("TADA!"),
|
|
66
|
-
);
|
|
67
|
-
await mockFn("any", "arguments", {we: {want: 42}});
|
|
68
|
-
|
|
69
|
-
// Assert
|
|
70
|
-
expect(matcher).toHaveBeenCalledWith(
|
|
71
|
-
"THE MOCK DESCRIPTION",
|
|
72
|
-
"any",
|
|
73
|
-
"arguments",
|
|
74
|
-
{
|
|
75
|
-
we: {want: 42},
|
|
76
|
-
},
|
|
77
|
-
);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it("should return mocked operation response if matcher returns true", async () => {
|
|
81
|
-
// Arrange
|
|
82
|
-
const matcher = jest.fn().mockReturnValue(true);
|
|
83
|
-
const operationToString = jest.fn();
|
|
84
|
-
const mockFn = mockRequester(matcher, operationToString);
|
|
85
|
-
|
|
86
|
-
// Act
|
|
87
|
-
mockFn.mockOperation(
|
|
88
|
-
"THE MOCK DESCRIPTION",
|
|
89
|
-
RespondWith.text("TADA!"),
|
|
90
|
-
);
|
|
91
|
-
const response = await mockFn("DO SOMETHING");
|
|
92
|
-
const result = response.text();
|
|
93
|
-
|
|
94
|
-
// Assert
|
|
95
|
-
await expect(result).resolves.toBe("TADA!");
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it("should skip mock if matcher returns false and try more mocks", async () => {
|
|
99
|
-
// Arrange
|
|
100
|
-
const matcher = jest
|
|
101
|
-
.fn()
|
|
102
|
-
.mockReturnValueOnce(false)
|
|
103
|
-
.mockReturnValueOnce(true);
|
|
104
|
-
const operationToString = jest.fn();
|
|
105
|
-
const mockFn = mockRequester(matcher, operationToString);
|
|
106
|
-
|
|
107
|
-
// Act
|
|
108
|
-
mockFn.mockOperation(
|
|
109
|
-
"THE MOCK DESCRIPTION 1",
|
|
110
|
-
RespondWith.text("ONE"),
|
|
111
|
-
);
|
|
112
|
-
mockFn.mockOperation(
|
|
113
|
-
"THE MOCK DESCRIPTION 2",
|
|
114
|
-
RespondWith.text("TWO"),
|
|
115
|
-
);
|
|
116
|
-
const response = await mockFn("DO SOMETHING");
|
|
117
|
-
const result = response.text();
|
|
118
|
-
|
|
119
|
-
// Assert
|
|
120
|
-
await expect(result).resolves.toBe("TWO");
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
describe("mockOperationOnce", () => {
|
|
125
|
-
it("should invoke matcher with mock for a request", async () => {
|
|
126
|
-
// Arrange
|
|
127
|
-
const matcher = jest.fn().mockReturnValue(true);
|
|
128
|
-
const operationToString = jest.fn();
|
|
129
|
-
const mockFn = mockRequester(matcher, operationToString);
|
|
130
|
-
|
|
131
|
-
// Act
|
|
132
|
-
mockFn.mockOperationOnce(
|
|
133
|
-
"THE MOCK DESCRIPTION",
|
|
134
|
-
RespondWith.text("TADA!"),
|
|
135
|
-
);
|
|
136
|
-
await mockFn("any", "arguments", {we: {want: 42}});
|
|
137
|
-
|
|
138
|
-
// Assert
|
|
139
|
-
expect(matcher).toHaveBeenCalledWith(
|
|
140
|
-
"THE MOCK DESCRIPTION",
|
|
141
|
-
"any",
|
|
142
|
-
"arguments",
|
|
143
|
-
{
|
|
144
|
-
we: {want: 42},
|
|
145
|
-
},
|
|
146
|
-
);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it("should match once", async () => {
|
|
150
|
-
// Arrange
|
|
151
|
-
const matcher = jest.fn().mockReturnValue(true);
|
|
152
|
-
const operationToString = jest.fn();
|
|
153
|
-
const mockFn = mockRequester(matcher, operationToString);
|
|
154
|
-
|
|
155
|
-
// Act
|
|
156
|
-
mockFn.mockOperationOnce(
|
|
157
|
-
"THE MOCK DESCRIPTION",
|
|
158
|
-
RespondWith.text("TADA!"),
|
|
159
|
-
);
|
|
160
|
-
const response = await mockFn("DO SOMETHING");
|
|
161
|
-
const result = response.text();
|
|
162
|
-
|
|
163
|
-
// Assert
|
|
164
|
-
await expect(result).resolves.toBe("TADA!");
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
it("should only match once", async () => {
|
|
168
|
-
// Arrange
|
|
169
|
-
const matcher = jest.fn().mockReturnValue(true);
|
|
170
|
-
const operationToString = jest.fn();
|
|
171
|
-
const mockFn = mockRequester(matcher, operationToString);
|
|
172
|
-
|
|
173
|
-
// Act
|
|
174
|
-
mockFn.mockOperationOnce(
|
|
175
|
-
"THE MOCK DESCRIPTION",
|
|
176
|
-
RespondWith.text("TADA!"),
|
|
177
|
-
);
|
|
178
|
-
const result = Promise.all([
|
|
179
|
-
mockFn("DO SOMETHING"),
|
|
180
|
-
mockFn("DO SOMETHING"),
|
|
181
|
-
]);
|
|
182
|
-
|
|
183
|
-
// Assert
|
|
184
|
-
await expect(result).rejects.toThrowError();
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
it("should skip mock if matcher returns false and try more mocks", async () => {
|
|
188
|
-
// Arrange
|
|
189
|
-
const matcher = jest
|
|
190
|
-
.fn()
|
|
191
|
-
.mockReturnValueOnce(false)
|
|
192
|
-
.mockReturnValueOnce(true);
|
|
193
|
-
const operationToString = jest.fn();
|
|
194
|
-
const mockFn = mockRequester(matcher, operationToString);
|
|
195
|
-
|
|
196
|
-
// Act
|
|
197
|
-
mockFn.mockOperationOnce(
|
|
198
|
-
"THE MOCK DESCRIPTION 1",
|
|
199
|
-
RespondWith.text("ONE"),
|
|
200
|
-
);
|
|
201
|
-
mockFn.mockOperationOnce(
|
|
202
|
-
"THE MOCK DESCRIPTION 2",
|
|
203
|
-
RespondWith.text("TWO"),
|
|
204
|
-
);
|
|
205
|
-
const response = await mockFn("DO SOMETHING");
|
|
206
|
-
const result = response.text();
|
|
207
|
-
|
|
208
|
-
// Assert
|
|
209
|
-
await expect(result).resolves.toBe("TWO");
|
|
210
|
-
});
|
|
211
|
-
});
|
|
212
|
-
});
|