@khanacademy/wonder-blocks-testing 4.0.2 → 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.
Files changed (69) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/es/index.js +212 -26
  3. package/dist/index.js +589 -62
  4. package/package.json +5 -3
  5. package/src/__docs__/_overview_.stories.mdx +3 -4
  6. package/src/__docs__/_overview_fixtures.stories.mdx +22 -0
  7. package/src/__docs__/_overview_mocking.stories.mdx +14 -0
  8. package/src/__docs__/_overview_test_harness.stories.mdx +18 -0
  9. package/src/__docs__/exports.fixture-adapters.stories.mdx +49 -0
  10. package/src/__docs__/exports.fixtures.stories.mdx +53 -0
  11. package/src/__docs__/exports.harness-adapters.stories.mdx +187 -0
  12. package/src/__docs__/exports.hook-harness.stories.mdx +22 -0
  13. package/src/__docs__/exports.make-hook-harness.stories.mdx +25 -0
  14. package/src/__docs__/exports.make-test-harness.stories.mdx +28 -0
  15. package/src/__docs__/exports.mock-fetch.stories.mdx +40 -0
  16. package/src/__docs__/exports.mock-gql-fetch.stories.mdx +13 -8
  17. package/src/__docs__/exports.respond-with.stories.mdx +54 -8
  18. package/src/__docs__/exports.setup-fixtures.stories.mdx +22 -0
  19. package/src/__docs__/exports.test-harness.stories.mdx +23 -0
  20. package/src/__docs__/types.custom-mount-props.stories.mdx +35 -0
  21. package/src/__docs__/types.fetch-mock-fn.stories.mdx +22 -0
  22. package/src/__docs__/types.fetch-mock-operation.stories.mdx +18 -0
  23. package/src/__docs__/types.fixtures-adapter-factory.stories.mdx +23 -0
  24. package/src/__docs__/types.fixtures-adapter-fixture-options.stories.mdx +35 -0
  25. package/src/__docs__/types.fixtures-adapter-group-options.stories.mdx +37 -0
  26. package/src/__docs__/types.fixtures-adapter-group.stories.mdx +43 -0
  27. package/src/__docs__/types.fixtures-adapter-options.stories.mdx +21 -0
  28. package/src/__docs__/types.fixtures-adapter.stories.mdx +35 -0
  29. package/src/__docs__/types.fixtures-configuration.stories.mdx +35 -0
  30. package/src/__docs__/types.fixtures-options.stories.mdx +51 -0
  31. package/src/__docs__/types.get-props-options.stories.mdx +25 -0
  32. package/src/__docs__/types.gql-fetch-mock-fn.stories.mdx +27 -0
  33. package/src/__docs__/types.gql-mock-operation.stories.mdx +26 -0
  34. package/src/__docs__/types.mock-response.stories.mdx +18 -0
  35. package/src/__docs__/types.test-harness-adapter.stories.mdx +21 -0
  36. package/src/__docs__/types.test-harness-adapters.stories.mdx +46 -0
  37. package/src/__docs__/types.test-harness-config.stories.mdx +18 -0
  38. package/src/__docs__/types.test-harness-configs.stories.mdx +59 -0
  39. package/src/fetch/types.js +0 -3
  40. package/src/fixtures/adapters/adapter-group.js +11 -11
  41. package/src/fixtures/adapters/adapter.js +8 -8
  42. package/src/fixtures/adapters/storybook.js +11 -8
  43. package/src/fixtures/fixtures.basic.stories.js +6 -2
  44. package/src/fixtures/fixtures.defaultwrapper.stories.js +6 -2
  45. package/src/fixtures/setup.js +8 -4
  46. package/src/fixtures/types.js +27 -16
  47. package/src/gql/types.js +1 -3
  48. package/src/harness/__tests__/hook-harness.test.js +72 -0
  49. package/src/harness/__tests__/make-hook-harness.test.js +94 -0
  50. package/src/harness/__tests__/make-test-harness.test.js +190 -0
  51. package/src/harness/__tests__/render-adapters.test.js +88 -0
  52. package/src/harness/__tests__/test-harness.test.js +74 -0
  53. package/src/harness/adapters/__tests__/__snapshots__/router.test.js.snap +5 -0
  54. package/src/harness/adapters/__tests__/css.test.js +96 -0
  55. package/src/harness/adapters/__tests__/data.test.js +66 -0
  56. package/src/harness/adapters/__tests__/portal.test.js +31 -0
  57. package/src/harness/adapters/__tests__/router.test.js +233 -0
  58. package/src/harness/adapters/adapters.js +33 -0
  59. package/src/harness/adapters/css.js +65 -0
  60. package/src/harness/adapters/data.js +46 -0
  61. package/src/harness/adapters/portal.js +26 -0
  62. package/src/harness/adapters/router.js +206 -0
  63. package/src/harness/hook-harness.js +23 -0
  64. package/src/harness/make-hook-harness.js +39 -0
  65. package/src/harness/make-test-harness.js +68 -0
  66. package/src/harness/render-adapters.js +27 -0
  67. package/src/harness/test-harness.js +24 -0
  68. package/src/harness/types.js +57 -0
  69. package/src/index.js +22 -18
@@ -1,25 +1,25 @@
1
1
  // @flow
2
2
  import type {
3
- AdapterGroup as AdapterGroupInterface,
4
- AdapterGroupOptions,
5
- AdapterFixtureOptions,
3
+ FixturesAdapterGroup,
4
+ FixturesAdapterGroupOptions,
5
+ FixturesAdapterFixtureOptions,
6
6
  } from "../types.js";
7
7
 
8
8
  export type CloseGroupFn<TProps: {...}, Options: {...}, Exports: {...}> = (
9
- options: $ReadOnly<AdapterGroupOptions>,
9
+ options: $ReadOnly<FixturesAdapterGroupOptions>,
10
10
  adapterOptions: ?$ReadOnly<Options>,
11
- declaredFixtures: $ReadOnlyArray<AdapterFixtureOptions<TProps>>,
11
+ declaredFixtures: $ReadOnlyArray<FixturesAdapterFixtureOptions<TProps>>,
12
12
  ) => ?$ReadOnly<Exports>;
13
13
 
14
14
  /**
15
15
  * Simple adapter group implementation.
16
16
  */
17
17
  export class AdapterGroup<TProps: {...}, Options: {...}, Exports: {...}>
18
- implements AdapterGroupInterface<TProps, Options, Exports>
18
+ implements FixturesAdapterGroup<TProps, Options, Exports>
19
19
  {
20
20
  _closeGroupFn: ?CloseGroupFn<TProps, Options, Exports>;
21
- +_fixtures: Array<AdapterFixtureOptions<TProps>>;
22
- +_options: $ReadOnly<AdapterGroupOptions>;
21
+ +_fixtures: Array<FixturesAdapterFixtureOptions<TProps>>;
22
+ +_options: $ReadOnly<FixturesAdapterGroupOptions>;
23
23
 
24
24
  /**
25
25
  * Create an adapter group.
@@ -30,7 +30,7 @@ export class AdapterGroup<TProps: {...}, Options: {...}, Exports: {...}>
30
30
  */
31
31
  constructor(
32
32
  closeGroupFn: CloseGroupFn<TProps, Options, Exports>,
33
- options: $ReadOnly<AdapterGroupOptions>,
33
+ options: $ReadOnly<FixturesAdapterGroupOptions>,
34
34
  ) {
35
35
  if (typeof closeGroupFn !== "function") {
36
36
  throw new TypeError("closeGroupFn must be a function");
@@ -71,11 +71,11 @@ export class AdapterGroup<TProps: {...}, Options: {...}, Exports: {...}>
71
71
  /**
72
72
  * Declare a fixture within the group.
73
73
  *
74
- * @param {AdapterFixtureOptions<Config>} fixtureOptions The options
74
+ * @param {FixturesAdapterFixtureOptions<TProps>} fixtureOptions The options
75
75
  * describing the fixture.
76
76
  */
77
77
  +declareFixture: (
78
- options: $ReadOnly<AdapterFixtureOptions<TProps>>,
78
+ options: $ReadOnly<FixturesAdapterFixtureOptions<TProps>>,
79
79
  ) => void = (options) => {
80
80
  if (typeof options !== "object" || options === null) {
81
81
  throw new TypeError("options must be an object");
@@ -1,16 +1,16 @@
1
1
  // @flow
2
2
  import {AdapterGroup, type CloseGroupFn} from "./adapter-group.js";
3
3
  import type {
4
- Adapter as AdapterInterface,
5
- AdapterGroup as AdapterGroupInterface,
6
- AdapterGroupOptions,
4
+ FixturesAdapter,
5
+ FixturesAdapterGroup,
6
+ FixturesAdapterGroupOptions,
7
7
  } from "../types.js";
8
8
 
9
9
  /**
10
10
  * Class for implementing a custom adapter.
11
11
  */
12
12
  export class Adapter<Options: {...}, Exports: {...}>
13
- implements AdapterInterface<Options, Exports>
13
+ implements FixturesAdapter<Options, Exports>
14
14
  {
15
15
  +_name: string;
16
16
  +_closeGroupFn: CloseGroupFn<any, Options, Exports>;
@@ -51,13 +51,13 @@ export class Adapter<Options: {...}, Exports: {...}>
51
51
  /**
52
52
  * Declare a new fixture group.
53
53
  *
54
- * @param {AdapterGroupOptions} options The options describing the fixture
54
+ * @param {FixturesAdapterGroupOptions} options The options describing the fixture
55
55
  * group.
56
- * @returns {AdapterGroupInterface} The new fixture group.
56
+ * @returns {FixturesAdapterGroup} The new fixture group.
57
57
  */
58
58
  declareGroup<Config: {...}>(
59
- options: $ReadOnly<AdapterGroupOptions>,
60
- ): AdapterGroupInterface<Config, Options, Exports> {
59
+ options: $ReadOnly<FixturesAdapterGroupOptions>,
60
+ ): FixturesAdapterGroup<Config, Options, Exports> {
61
61
  return new AdapterGroup(this._closeGroupFn, options);
62
62
  }
63
63
  }
@@ -4,9 +4,9 @@ import {action} from "@storybook/addon-actions";
4
4
  import {Adapter} from "./adapter.js";
5
5
 
6
6
  import type {
7
- AdapterGroupOptions,
8
- AdapterFixtureOptions,
9
- AdapterFactory,
7
+ FixturesAdapterGroupOptions,
8
+ FixturesAdapterFixtureOptions,
9
+ FixturesAdapterFactory,
10
10
  } from "../types.js";
11
11
 
12
12
  type StoryContext = {|
@@ -38,9 +38,10 @@ type Exports<TProps: {...}> = {|
38
38
  /**
39
39
  * Get a fixture framework adapter for Storybook support.
40
40
  */
41
- export const getAdapter: AdapterFactory<StorybookOptions, Exports<any>> = (
42
- MountingComponent = null,
43
- ) =>
41
+ export const getAdapter: FixturesAdapterFactory<
42
+ StorybookOptions,
43
+ Exports<any>,
44
+ > = (MountingComponent = null) =>
44
45
  new Adapter<StorybookOptions, Exports<any>>(
45
46
  "storybook",
46
47
  <TProps: {...}>(
@@ -50,9 +51,11 @@ export const getAdapter: AdapterFactory<StorybookOptions, Exports<any>> = (
50
51
  // We don't use the default title in Storybook as storybook
51
52
  // will generate titles for us if we pass a nullish title.
52
53
  getDefaultTitle: _,
53
- }: $ReadOnly<AdapterGroupOptions>,
54
+ }: $ReadOnly<FixturesAdapterGroupOptions>,
54
55
  adapterOptions: ?$ReadOnly<StorybookOptions>,
55
- declaredFixtures: $ReadOnlyArray<AdapterFixtureOptions<TProps>>,
56
+ declaredFixtures: $ReadOnlyArray<
57
+ FixturesAdapterFixtureOptions<TProps>,
58
+ >,
56
59
  ): ?$ReadOnly<Exports<TProps>> => {
57
60
  const templateMap = new WeakMap();
58
61
 
@@ -1,7 +1,11 @@
1
1
  // @flow
2
2
  import * as React from "react";
3
3
 
4
- import {setupFixtures, fixtures, adapters} from "../index.js";
4
+ import {
5
+ setupFixtures,
6
+ fixtures,
7
+ fixtureAdapters as adapters,
8
+ } from "../index.js";
5
9
 
6
10
  // Normally would call setup from the storybook.preview.js for a project.
7
11
  setupFixtures({
@@ -23,7 +27,7 @@ const stories: Array<mixed> = Object.values(
23
27
  fixtures(
24
28
  {
25
29
  component: MyComponent,
26
- title: "Testing/Fixtures/Basic",
30
+ title: "Testing / Fixtures / Basic",
27
31
  },
28
32
  (fixture) => {
29
33
  fixture("This is a fixture with some regular props", {
@@ -1,7 +1,11 @@
1
1
  // @flow
2
2
  import * as React from "react";
3
3
 
4
- import {setupFixtures, fixtures, adapters} from "../index.js";
4
+ import {
5
+ setupFixtures,
6
+ fixtures,
7
+ fixtureAdapters as adapters,
8
+ } from "../index.js";
5
9
 
6
10
  // Normally would call setup from the storybook.preview.js for a project.
7
11
  setupFixtures({
@@ -30,7 +34,7 @@ const stories: Array<mixed> = Object.values(
30
34
  fixtures(
31
35
  {
32
36
  component: MyComponent,
33
- title: "Testing/Fixtures/DefaultWrapper",
37
+ title: "Testing / Fixtures / DefaultWrapper",
34
38
  defaultWrapper: DefaultWrapper,
35
39
  },
36
40
  (fixture) => {
@@ -1,13 +1,15 @@
1
1
  // @flow
2
- import type {Configuration} from "./types.js";
2
+ import type {FixturesConfiguration} from "./types.js";
3
3
 
4
- let _configuration: ?$ReadOnly<Configuration<any, any>> = null;
4
+ let _configuration: ?$ReadOnly<FixturesConfiguration<any, any>> = null;
5
5
 
6
6
  /**
7
7
  * Setup the fixture framework.
8
8
  */
9
9
  export const setup = <TAdapterOptions: {...}, TAdapterExports: {...}>(
10
- configuration: $ReadOnly<Configuration<TAdapterOptions, TAdapterExports>>,
10
+ configuration: $ReadOnly<
11
+ FixturesConfiguration<TAdapterOptions, TAdapterExports>,
12
+ >,
11
13
  ) => {
12
14
  _configuration = configuration;
13
15
  };
@@ -18,7 +20,9 @@ export const setup = <TAdapterOptions: {...}, TAdapterExports: {...}>(
18
20
  * @returns {Configuration} The configuration as provided via setup().
19
21
  * @throws {Error} If the configuration has not been set.
20
22
  */
21
- export const getConfiguration = (): $ReadOnly<Configuration<any, any>> => {
23
+ export const getConfiguration = (): $ReadOnly<
24
+ FixturesConfiguration<any, any>,
25
+ > => {
22
26
  if (_configuration == null) {
23
27
  throw new Error("Not configured");
24
28
  }
@@ -15,7 +15,7 @@ export type GetPropsOptions = {|
15
15
  /**
16
16
  * Adapter options keyed by the adapter name.
17
17
  */
18
- export type AdapterOptions = {|
18
+ export type FixturesAdapterOptions = {|
19
19
  storybook?: StorybookOptions,
20
20
  [adapterName: string]: {...},
21
21
  |};
@@ -49,13 +49,13 @@ export type FixturesOptions<TProps: {...}> = {|
49
49
  /**
50
50
  * Additional options to apply to specific adapters.
51
51
  */
52
- additionalAdapterOptions?: AdapterOptions,
52
+ additionalAdapterOptions?: FixturesAdapterOptions,
53
53
  |};
54
54
 
55
55
  /**
56
56
  * Describes a single fixture.
57
57
  */
58
- export type AdapterFixtureOptions<TProps: {...}> = {|
58
+ export type FixturesAdapterFixtureOptions<TProps: {...}> = {|
59
59
  /**
60
60
  * Description of the fixture.
61
61
  */
@@ -78,7 +78,7 @@ export type AdapterFixtureOptions<TProps: {...}> = {|
78
78
  /**
79
79
  * Describes a group of fixtures.
80
80
  */
81
- export type AdapterGroupOptions = {|
81
+ export type FixturesAdapterGroupOptions = {|
82
82
  /**
83
83
  * The title of the group.
84
84
  *
@@ -100,9 +100,9 @@ export type AdapterGroupOptions = {|
100
100
  |};
101
101
 
102
102
  /**
103
- * Describes the props that an adapter will inject for custom wrappers.
103
+ * Describes props that an adapter will inject for custom mounting components.
104
104
  */
105
- export type CustomWrapperProps<TProps: {...}> = {|
105
+ export type CustomMountProps<TProps: {...}> = {|
106
106
  /**
107
107
  * The fixture props for the component to be rendered.
108
108
  */
@@ -122,7 +122,7 @@ export type CustomWrapperProps<TProps: {...}> = {|
122
122
  /**
123
123
  * Declares the API for describing a fixture group provided by an adapter.
124
124
  */
125
- export interface AdapterGroup<
125
+ export interface FixturesAdapterGroup<
126
126
  TProps: {...},
127
127
  TAdapterOptions: {...},
128
128
  TAdapterExports: {...},
@@ -130,7 +130,9 @@ export interface AdapterGroup<
130
130
  /**
131
131
  * Declare a fixture.
132
132
  */
133
- declareFixture(options: $ReadOnly<AdapterFixtureOptions<TProps>>): void;
133
+ declareFixture(
134
+ options: $ReadOnly<FixturesAdapterFixtureOptions<TProps>>,
135
+ ): void;
134
136
 
135
137
  /**
136
138
  * Close the group and obtain the exports, if the adapter requires any.
@@ -150,7 +152,10 @@ export interface AdapterGroup<
150
152
  /**
151
153
  * Declares the API for an adapter.
152
154
  */
153
- export interface Adapter<TAdapterOptions: {...}, TAdapterExports: {...}> {
155
+ export interface FixturesAdapter<
156
+ TAdapterOptions: {...},
157
+ TAdapterExports: {...},
158
+ > {
154
159
  /**
155
160
  * The name of the adapter.
156
161
  */
@@ -163,18 +168,21 @@ export interface Adapter<TAdapterOptions: {...}, TAdapterExports: {...}> {
163
168
  * declared group.
164
169
  */
165
170
  declareGroup<TProps: {...}>(
166
- options: $ReadOnly<AdapterGroupOptions>,
167
- ): AdapterGroup<TProps, TAdapterOptions, TAdapterExports>;
171
+ options: $ReadOnly<FixturesAdapterGroupOptions>,
172
+ ): FixturesAdapterGroup<TProps, TAdapterOptions, TAdapterExports>;
168
173
  }
169
174
 
170
175
  /**
171
176
  * Describes the configuration for the fixture framework.
172
177
  */
173
- export type Configuration<TAdapterOptions: {...}, TAdapterExports: {...}> = {|
178
+ export type FixturesConfiguration<
179
+ TAdapterOptions: {...},
180
+ TAdapterExports: {...},
181
+ > = {|
174
182
  /**
175
183
  * The adapter to use for declaring fixtures.
176
184
  */
177
- +adapter: Adapter<TAdapterOptions, TAdapterExports>,
185
+ +adapter: FixturesAdapter<TAdapterOptions, TAdapterExports>,
178
186
 
179
187
  /**
180
188
  * Default options to apply to every fixture group.
@@ -186,6 +194,9 @@ export type Configuration<TAdapterOptions: {...}, TAdapterExports: {...}> = {|
186
194
  +defaultAdapterOptions?: $ReadOnly<Partial<TAdapterOptions>>,
187
195
  |};
188
196
 
189
- export type AdapterFactory<TAdapterOptions: {...}, TAdapterExports: {...}> = (
190
- MountingComponent: ?React.ComponentType<CustomWrapperProps<any>>,
191
- ) => Adapter<TAdapterOptions, TAdapterExports>;
197
+ export type FixturesAdapterFactory<
198
+ TAdapterOptions: {...},
199
+ TAdapterExports: {...},
200
+ > = (
201
+ MountingComponent: ?React.ComponentType<CustomMountProps<any>>,
202
+ ) => FixturesAdapter<TAdapterOptions, TAdapterExports>;
package/src/gql/types.js CHANGED
@@ -1,6 +1,6 @@
1
1
  //@flow
2
2
  import type {GqlOperation, GqlContext} from "@khanacademy/wonder-blocks-data";
3
- import type {OperationMock, GraphQLJson} from "../types.js";
3
+ import type {GraphQLJson} from "../types.js";
4
4
  import type {MockResponse} from "../make-mock-response.js";
5
5
 
6
6
  export type GqlMockOperation<
@@ -32,5 +32,3 @@ export type GqlFetchMockFn = {|
32
32
  mockOperation: GqlMockOperationFn,
33
33
  mockOperationOnce: GqlMockOperationFn,
34
34
  |};
35
-
36
- export type GqlMock = OperationMock<GqlMockOperation<any, any, any>>;
@@ -0,0 +1,72 @@
1
+ // @flow
2
+ import {jest as ws} from "@khanacademy/wonder-stuff-testing";
3
+ import * as MHH from "../make-hook-harness.js";
4
+ import {DefaultAdapters, DefaultConfigs} from "../adapters/adapters.js";
5
+
6
+ jest.mock("../make-hook-harness.js", () => {
7
+ const returnValueFake = {
8
+ thisisa: "PRETEND REACT COMPONENT",
9
+ };
10
+ const harnessFake = jest.fn().mockReturnValue(returnValueFake);
11
+ return {
12
+ harnessFake,
13
+ returnValueFake,
14
+ makeHookHarness: jest.fn().mockReturnValue(harnessFake),
15
+ };
16
+ });
17
+
18
+ describe("#hookHarness", () => {
19
+ it("should be created by calling makeHookHarness with the DefaultAdapters and DefaultConfigs", async () => {
20
+ // Arrange
21
+ const makeHookHarnessSpy = jest.spyOn(MHH, "makeHookHarness");
22
+
23
+ // Act
24
+ await ws.isolateModules(() => import("../hook-harness.js"));
25
+
26
+ // Assert
27
+ expect(makeHookHarnessSpy).toHaveBeenCalledWith(
28
+ DefaultAdapters,
29
+ DefaultConfigs,
30
+ );
31
+ });
32
+
33
+ it("should invoke the function made by makeHookHarness", async () => {
34
+ // Arrange
35
+ const config = {
36
+ router: "/boo",
37
+ };
38
+ // $FlowIgnore[prop-missing] - we add this into our mock at the top.
39
+ const [{harnessFake}, {hookHarness}] = await ws.isolateModules(() =>
40
+ Promise.all([
41
+ import("../make-hook-harness.js"),
42
+ import("../hook-harness.js"),
43
+ ]),
44
+ );
45
+
46
+ // Act
47
+ hookHarness(config);
48
+
49
+ // Assert
50
+ expect(harnessFake).toHaveBeenCalledWith(config);
51
+ });
52
+
53
+ it("should return the returned value of the function made by makeHookHarness", async () => {
54
+ // Arrange
55
+ const config = {
56
+ router: "/boo",
57
+ };
58
+ // $FlowIgnore[prop-missing] - we add this into our mock at the top.
59
+ const [{returnValueFake}, {hookHarness}] = await ws.isolateModules(() =>
60
+ Promise.all([
61
+ import("../make-hook-harness.js"),
62
+ import("../hook-harness.js"),
63
+ ]),
64
+ );
65
+
66
+ // Act
67
+ const result = hookHarness(config);
68
+
69
+ // Assert
70
+ expect(result).toBe(returnValueFake);
71
+ });
72
+ });
@@ -0,0 +1,94 @@
1
+ // @flow
2
+ import * as React from "react";
3
+ import {render} from "@testing-library/react";
4
+ import {makeHookHarness} from "../make-hook-harness.js";
5
+ import * as MTH from "../make-test-harness.js";
6
+
7
+ describe("#makeHookHarness", () => {
8
+ it("should call makeTestHarness", () => {
9
+ // Arrange
10
+ const makeTestHarnessSpy = jest.spyOn(MTH, "makeTestHarness");
11
+ const adapters = {
12
+ adapter: jest.fn(),
13
+ };
14
+ const defaultConfigs = {
15
+ adapter: {},
16
+ };
17
+
18
+ // Act
19
+ makeHookHarness(adapters, defaultConfigs);
20
+
21
+ // Assert
22
+ expect(makeTestHarnessSpy).toHaveBeenCalledWith(
23
+ adapters,
24
+ defaultConfigs,
25
+ );
26
+ });
27
+
28
+ it("should return a function", () => {
29
+ const adapters = {
30
+ adapter: jest.fn(),
31
+ };
32
+ const defaultConfigs = {
33
+ adapter: {},
34
+ };
35
+
36
+ // Act
37
+ const result = makeHookHarness(adapters, defaultConfigs);
38
+
39
+ // Assert
40
+ expect(result).toBeFunction();
41
+ });
42
+
43
+ describe("returned function", () => {
44
+ it("should invoke the function returned by makeTestHarness with component and the configs", () => {
45
+ // Arrange
46
+ const harnessSpy = jest.fn();
47
+ jest.spyOn(MTH, "makeTestHarness").mockReturnValue(harnessSpy);
48
+ const adapters = {
49
+ adapter: jest.fn(),
50
+ };
51
+ const defaultConfigs = {
52
+ adapter: {},
53
+ };
54
+ const configs = {
55
+ adapter: {},
56
+ };
57
+ const hookHarness = makeHookHarness(adapters, defaultConfigs);
58
+
59
+ // Act
60
+ hookHarness(configs);
61
+
62
+ // Assert
63
+ expect(harnessSpy).toHaveBeenCalledWith(
64
+ expect.any(Function),
65
+ configs,
66
+ );
67
+ });
68
+
69
+ it("should pass a component that just renders the children it is given", () => {
70
+ // Arrange
71
+ const harnessSpy = jest.fn();
72
+ jest.spyOn(MTH, "makeTestHarness").mockReturnValue(harnessSpy);
73
+ const adapters = {
74
+ adapter: jest.fn(),
75
+ };
76
+ const defaultConfigs = {
77
+ adapter: {},
78
+ };
79
+ const configs = {
80
+ adapter: {},
81
+ };
82
+ const children = "THE CHILDREN";
83
+
84
+ // Act
85
+ const hookHarness = makeHookHarness(adapters, defaultConfigs);
86
+ hookHarness(configs);
87
+ const Component = harnessSpy.mock.calls[0][0];
88
+ const {container} = render(<Component>{children}</Component>);
89
+
90
+ // Assert
91
+ expect(container).toHaveTextContent(children);
92
+ });
93
+ });
94
+ });