@khanacademy/wonder-blocks-testing 9.0.0 → 9.2.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.
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
  import {Route} from "react-router-dom";
3
3
  import {render} from "@testing-library/react";
4
4
 
5
- import * as RA from "../render-adapters";
5
+ import * as RA from "../adapt";
6
6
  import {makeTestHarness} from "../make-test-harness";
7
7
  import {DefaultConfigs, DefaultAdapters} from "../adapters/adapters";
8
8
 
@@ -75,7 +75,7 @@ describe("#makeTestHarness", () => {
75
75
  DefaultConfigs,
76
76
  );
77
77
  const Component = () => <div>test</div>;
78
- const renderSpy = jest.spyOn(RA, "renderAdapters");
78
+ const renderSpy = jest.spyOn(RA, "Adapt");
79
79
 
80
80
  // Act
81
81
  const HarnessedComponent = testHarness(Component);
@@ -83,9 +83,12 @@ describe("#makeTestHarness", () => {
83
83
 
84
84
  // Assert
85
85
  expect(renderSpy).toHaveBeenCalledWith(
86
- DefaultAdapters,
87
- DefaultConfigs,
88
- expect.anything(),
86
+ {
87
+ adapters: DefaultAdapters,
88
+ configs: DefaultConfigs,
89
+ children: expect.anything(),
90
+ },
91
+ {},
89
92
  );
90
93
  });
91
94
 
@@ -132,7 +135,7 @@ describe("#makeTestHarness", () => {
132
135
  router: "/mysecretplace",
133
136
  };
134
137
  const Component = () => <div>test</div>;
135
- const renderSpy = jest.spyOn(RA, "renderAdapters");
138
+ const renderSpy = jest.spyOn(RA, "Adapt");
136
139
 
137
140
  // Act
138
141
  const HarnessedComponent = testHarness(
@@ -143,12 +146,15 @@ describe("#makeTestHarness", () => {
143
146
 
144
147
  // Assert
145
148
  expect(renderSpy).toHaveBeenCalledWith(
146
- DefaultAdapters,
147
149
  {
148
- ...DefaultConfigs,
149
- router: configOverrides.router,
150
+ adapters: DefaultAdapters,
151
+ configs: {
152
+ ...DefaultConfigs,
153
+ router: configOverrides.router,
154
+ },
155
+ children: expect.anything(),
150
156
  },
151
- expect.anything(),
157
+ {},
152
158
  );
153
159
  });
154
160
 
@@ -0,0 +1,36 @@
1
+ import * as React from "react";
2
+
3
+ import type {TestHarnessConfigs, TestHarnessAdapters} from "./types";
4
+
5
+ type Props<TAdapters extends TestHarnessAdapters> = {
6
+ children: React.ReactNode;
7
+ adapters: TAdapters;
8
+ configs: TestHarnessConfigs<TAdapters>;
9
+ };
10
+
11
+ /**
12
+ * Render a set of adapters around the given children.
13
+ *
14
+ * Adapters are rendered with the last adapter being the outermost and the first
15
+ * adapter being the innermost, with children being the innermost of all. This
16
+ * ensures that we are backwards compatible with previous releases of the
17
+ * test harness.
18
+ */
19
+ export const Adapt = <TAdapters extends TestHarnessAdapters>({
20
+ children,
21
+ adapters,
22
+ configs,
23
+ }: Props<TAdapters>): React.ReactElement =>
24
+ // Here we reduce the adapters in order, such that each one becomes the
25
+ // child of the next, that way the first adapter in the list is the
26
+ // innermost and the last is the outermost.
27
+ Object.entries(adapters).reduce((newChildren, [name, adapter]) => {
28
+ const config = configs[name];
29
+ if (config == null) {
30
+ return newChildren;
31
+ }
32
+ const Adapter: React.FunctionComponent = ({children}) =>
33
+ adapter(children, config);
34
+ Adapter.displayName = `Adapter(${name})`;
35
+ return <Adapter>{newChildren}</Adapter>;
36
+ }, <>{children}</>);
@@ -1,14 +1,19 @@
1
1
  import * as React from "react";
2
2
  import {render, screen} from "@testing-library/react";
3
-
4
3
  import * as WBCore from "@khanacademy/wonder-blocks-core";
4
+ import {makeTestHarness} from "../../make-test-harness";
5
5
 
6
6
  import * as SSR from "../ssr";
7
7
 
8
- jest.mock("@khanacademy/wonder-stuff-core", () => ({
9
- ...jest.requireActual("@khanacademy/wonder-stuff-core"),
10
- RenderStateRoot: (props: any) => <div {...props} />,
11
- }));
8
+ jest.mock("@khanacademy/wonder-stuff-core", () => {
9
+ const actualCore = jest.requireActual("@khanacademy/wonder-stuff-core");
10
+ return {
11
+ ...actualCore,
12
+ RenderStateRoot: (props: any) => (
13
+ <actualCore.RenderStateRoot {...props} />
14
+ ),
15
+ };
16
+ });
12
17
 
13
18
  describe("SSR.adapter", () => {
14
19
  it("should render the RenderStateRoot", () => {
@@ -38,4 +43,40 @@ describe("SSR.adapter", () => {
38
43
  // Assert
39
44
  expect(screen.getByText("CHILDREN!")).toBeInTheDocument();
40
45
  });
46
+
47
+ it("should enable harnessing of components that require RenderStateRoot", () => {
48
+ // Arrange
49
+ const ComponentNeedsSsr = (props: any) => {
50
+ const idf = WBCore.useUniqueIdWithoutMock();
51
+ return <div>{idf?.get("my-id")}</div>;
52
+ };
53
+ const testHarness = makeTestHarness(
54
+ {
55
+ ssr: SSR.adapter,
56
+ },
57
+ {
58
+ ssr: true,
59
+ },
60
+ );
61
+ const Harnessed = testHarness(ComponentNeedsSsr);
62
+
63
+ // Act
64
+ const underTest = () => render(<Harnessed />);
65
+
66
+ // Assert
67
+ expect(underTest).not.toThrowError();
68
+ });
69
+
70
+ it("should throw on bad configuration", () => {
71
+ // Arrange
72
+ const children = <div>CHILDREN!</div>;
73
+
74
+ // Act
75
+ const underTest = () => render(SSR.adapter(children, false as any));
76
+
77
+ // Assert
78
+ expect(underTest).toThrowErrorMatchingInlineSnapshot(
79
+ `"Unexpected configuration: set config to null to turn this adapter off"`,
80
+ );
81
+ });
41
82
  });
@@ -25,9 +25,13 @@ export const adapter: TestHarnessAdapter<Config> = (
25
25
  config: Config,
26
26
  ): React.ReactElement<any> => {
27
27
  if (config !== true) {
28
- throw new KindError("Unexpected configuraiton", Errors.InvalidInput, {
29
- metadata: {config},
30
- });
28
+ throw new KindError(
29
+ "Unexpected configuration: set config to null to turn this adapter off",
30
+ Errors.InvalidInput,
31
+ {
32
+ metadata: {config},
33
+ },
34
+ );
31
35
  }
32
36
  return <RenderStateRoot>{children}</RenderStateRoot>;
33
37
  };
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
 
3
- import {renderAdapters} from "./render-adapters";
3
+ import {Adapt} from "./adapt";
4
4
 
5
5
  import type {TestHarnessAdapters, TestHarnessConfigs} from "./types";
6
6
 
@@ -43,13 +43,11 @@ export const makeTestHarness = <TAdapters extends TestHarnessAdapters>(
43
43
  ...defaultConfigs,
44
44
  ...configs,
45
45
  };
46
- const harnessedComponent = React.forwardRef((props: TProps, ref) =>
47
- renderAdapters<TAdapters>(
48
- adapters,
49
- fullConfig,
50
- <Component {...(props as TProps)} ref={ref} />,
51
- ),
52
- );
46
+ const harnessedComponent = React.forwardRef((props: TProps, ref) => (
47
+ <Adapt adapters={adapters} configs={fullConfig}>
48
+ <Component {...(props as TProps)} ref={ref} />
49
+ </Adapt>
50
+ ));
53
51
 
54
52
  // We add a name for the component here so that we can detect that
55
53
  // later and also see it in traces and what have you.
@@ -6,6 +6,7 @@
6
6
  "rootDir": "src",
7
7
  },
8
8
  "references": [
9
+ {"path": "../wonder-blocks-core/tsconfig-build.json"},
9
10
  {"path": "../wonder-blocks-data/tsconfig-build.json"},
10
11
  ]
11
12
  }