@khanacademy/wonder-blocks-testing 10.1.1 → 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 +17 -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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-testing
|
|
2
2
|
|
|
3
|
+
## 11.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 2a6c85df: New package containing core Testing functionality without dependencies on other WB packages
|
|
8
|
+
- 2a6c85df: - Minimum version for Storybook actions addon increased to 7
|
|
9
|
+
- Added new `renderHookStatic` utility to replace deprecated `renderHookServer` from `@testing-library/react-hooks`; ready for React 18 updates
|
|
10
|
+
- Added new `boundary` error boundary adapter for the test harness to capture errors during tests; ready for React 18 updates
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies [2a6c85df]
|
|
15
|
+
- Updated dependencies [eab37b8b]
|
|
16
|
+
- @khanacademy/wonder-blocks-testing-core@1.0.0
|
|
17
|
+
- @khanacademy/wonder-blocks-core@6.4.2
|
|
18
|
+
- @khanacademy/wonder-blocks-data@13.0.9
|
|
19
|
+
|
|
3
20
|
## 10.1.1
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/dist/es/index.js
CHANGED
|
@@ -1,90 +1,10 @@
|
|
|
1
|
+
import { mockRequester, harnessAdapters } from '@khanacademy/wonder-blocks-testing-core';
|
|
2
|
+
export { RespondWith, SettleController, fixtures, hookHarness, makeHookHarness, makeTestHarness, mockFetch, renderHookStatic, testHarness } from '@khanacademy/wonder-blocks-testing-core';
|
|
1
3
|
import * as React from 'react';
|
|
2
|
-
import { action } from '@storybook/addon-actions';
|
|
3
4
|
import { InterceptRequests } from '@khanacademy/wonder-blocks-data';
|
|
4
|
-
import { StaticRouter, MemoryRouter, Switch, Route } from 'react-router-dom';
|
|
5
5
|
import { KindError, Errors } from '@khanacademy/wonder-stuff-core';
|
|
6
6
|
import { RenderStateRoot } from '@khanacademy/wonder-blocks-core';
|
|
7
7
|
|
|
8
|
-
const fixtures = Component => {
|
|
9
|
-
const templateMap = new WeakMap();
|
|
10
|
-
let storyNumber = 1;
|
|
11
|
-
const getPropsOptions = {
|
|
12
|
-
log: (message, ...args) => action(message)(...args),
|
|
13
|
-
logHandler: action
|
|
14
|
-
};
|
|
15
|
-
const makeStory = (description, props, wrapper = null) => {
|
|
16
|
-
const storyName = `${storyNumber++} ${description}`;
|
|
17
|
-
const getProps = options => typeof props === "function" ? props(options) : props;
|
|
18
|
-
const RealComponent = wrapper || Component;
|
|
19
|
-
let Template = templateMap.get(RealComponent);
|
|
20
|
-
if (Template == null) {
|
|
21
|
-
Template = args => React.createElement(RealComponent, args);
|
|
22
|
-
templateMap.set(RealComponent, Template);
|
|
23
|
-
}
|
|
24
|
-
const story = Template.bind({});
|
|
25
|
-
story.args = getProps(getPropsOptions);
|
|
26
|
-
story.storyName = storyName;
|
|
27
|
-
return story;
|
|
28
|
-
};
|
|
29
|
-
return makeStory;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const getHref = input => {
|
|
33
|
-
if (typeof input === "string") {
|
|
34
|
-
return input;
|
|
35
|
-
} else if (typeof input.url === "string") {
|
|
36
|
-
return input.url;
|
|
37
|
-
} else if (typeof input.href === "string") {
|
|
38
|
-
return input.href;
|
|
39
|
-
} else {
|
|
40
|
-
throw new Error(`Unsupported input type`);
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
const fetchRequestMatchesMock = (mock, input, init) => {
|
|
44
|
-
const href = getHref(input);
|
|
45
|
-
if (typeof mock === "string") {
|
|
46
|
-
return href === mock;
|
|
47
|
-
} else if (mock instanceof RegExp) {
|
|
48
|
-
return mock.test(href);
|
|
49
|
-
} else {
|
|
50
|
-
throw new Error(`Unsupported mock operation: ${JSON.stringify(mock)}`);
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const mockRequester = (operationMatcher, operationToString) => {
|
|
55
|
-
const mocks = [];
|
|
56
|
-
const mockFn = (...args) => {
|
|
57
|
-
for (const mock of mocks) {
|
|
58
|
-
if (mock.onceOnly && mock.used) {
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
if (operationMatcher(mock.operation, ...args)) {
|
|
62
|
-
mock.used = true;
|
|
63
|
-
return mock.response();
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
const operation = operationToString(...args);
|
|
67
|
-
return Promise.reject(new Error(`No matching mock response found for request:
|
|
68
|
-
${operation}`));
|
|
69
|
-
};
|
|
70
|
-
const addMockedOperation = (operation, response, onceOnly) => {
|
|
71
|
-
const mockResponse = () => response.toPromise();
|
|
72
|
-
mocks.push({
|
|
73
|
-
operation,
|
|
74
|
-
response: mockResponse,
|
|
75
|
-
onceOnly,
|
|
76
|
-
used: false
|
|
77
|
-
});
|
|
78
|
-
return mockFn;
|
|
79
|
-
};
|
|
80
|
-
mockFn.mockOperation = (operation, response) => addMockedOperation(operation, response, false);
|
|
81
|
-
mockFn.mockOperationOnce = (operation, response) => addMockedOperation(operation, response, true);
|
|
82
|
-
return mockFn;
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const mockFetch = () => mockRequester(fetchRequestMatchesMock, (input, init) => `Input: ${typeof input === "string" ? input : JSON.stringify(input, null, 2)}
|
|
86
|
-
Options: ${init == null ? "None" : JSON.stringify(init, null, 2)}`);
|
|
87
|
-
|
|
88
8
|
const safeHasOwnProperty = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
|
|
89
9
|
const areObjectsEqual = (a, b) => {
|
|
90
10
|
if (a === b) {
|
|
@@ -130,169 +50,23 @@ const mockGqlFetch = () => mockRequester(gqlRequestMatchesMock, (operation, vari
|
|
|
130
50
|
Variables: ${variables == null ? "None" : JSON.stringify(variables, null, 2)}
|
|
131
51
|
Context: ${JSON.stringify(context, null, 2)}`);
|
|
132
52
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
});
|
|
143
|
-
const rejectResponse = (error, signal) => ({
|
|
144
|
-
toPromise: () => makeMockResponse({
|
|
145
|
-
type: "reject",
|
|
146
|
-
error,
|
|
147
|
-
signal
|
|
148
|
-
})
|
|
149
|
-
});
|
|
150
|
-
const RespondWith = Object.freeze({
|
|
151
|
-
text: (text, statusCode = 200, signal = null) => textResponse(text, statusCode, signal),
|
|
152
|
-
json: (json, signal = null) => textResponse(() => JSON.stringify(json), 200, signal),
|
|
153
|
-
graphQLData: (data, signal = null) => textResponse(() => JSON.stringify({
|
|
154
|
-
data
|
|
155
|
-
}), 200, signal),
|
|
156
|
-
unparseableBody: (signal = null) => textResponse("INVALID JSON", 200, signal),
|
|
157
|
-
abortedRequest: (signal = null) => rejectResponse(() => {
|
|
158
|
-
const abortError = new Error("Mock request aborted");
|
|
159
|
-
abortError.name = "AbortError";
|
|
160
|
-
return abortError;
|
|
161
|
-
}, signal),
|
|
162
|
-
reject: (error, signal = null) => rejectResponse(error, signal),
|
|
163
|
-
errorStatusCode: (statusCode, signal = null) => {
|
|
164
|
-
if (statusCode < 300) {
|
|
165
|
-
throw new Error(`${statusCode} is not a valid error status code`);
|
|
53
|
+
function _extends() {
|
|
54
|
+
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
55
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
56
|
+
var source = arguments[i];
|
|
57
|
+
for (var key in source) {
|
|
58
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
59
|
+
target[key] = source[key];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
166
62
|
}
|
|
167
|
-
return
|
|
168
|
-
},
|
|
169
|
-
nonGraphQLBody: (signal = null) => textResponse(() => JSON.stringify({
|
|
170
|
-
valid: "json",
|
|
171
|
-
that: "is not a valid graphql response"
|
|
172
|
-
}), 200, signal),
|
|
173
|
-
graphQLErrors: (errorMessages, signal = null) => textResponse(() => JSON.stringify({
|
|
174
|
-
errors: errorMessages.map(e => ({
|
|
175
|
-
message: e
|
|
176
|
-
}))
|
|
177
|
-
}), 200, signal)
|
|
178
|
-
});
|
|
179
|
-
const callOnSettled = (signal, fn) => {
|
|
180
|
-
if (signal == null || signal.settled) {
|
|
181
|
-
fn();
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
const onSettled = () => {
|
|
185
|
-
signal.removeEventListener("settled", onSettled);
|
|
186
|
-
fn();
|
|
63
|
+
return target;
|
|
187
64
|
};
|
|
188
|
-
|
|
189
|
-
};
|
|
190
|
-
const makeMockResponse = response => {
|
|
191
|
-
const {
|
|
192
|
-
signal
|
|
193
|
-
} = response;
|
|
194
|
-
switch (response.type) {
|
|
195
|
-
case "text":
|
|
196
|
-
return new Promise((resolve, reject) => {
|
|
197
|
-
callOnSettled(signal, () => {
|
|
198
|
-
const text = typeof response.text === "function" ? response.text() : response.text;
|
|
199
|
-
resolve(new ResponseImpl(text, {
|
|
200
|
-
status: response.statusCode
|
|
201
|
-
}));
|
|
202
|
-
});
|
|
203
|
-
});
|
|
204
|
-
case "reject":
|
|
205
|
-
return new Promise((resolve, reject) => {
|
|
206
|
-
callOnSettled(signal, () => reject(response.error instanceof Error ? response.error : response.error()));
|
|
207
|
-
});
|
|
208
|
-
default:
|
|
209
|
-
if (process.env.NODE_ENV !== "production") {
|
|
210
|
-
throw new Error(`Unknown response type: ${response.type}`);
|
|
211
|
-
}
|
|
212
|
-
return makeMockResponse({
|
|
213
|
-
type: "reject",
|
|
214
|
-
error: new Error("Unknown response type"),
|
|
215
|
-
signal
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
class SettleSignal extends EventTarget {
|
|
221
|
-
constructor(setSettleFn = null) {
|
|
222
|
-
super();
|
|
223
|
-
this._settled = false;
|
|
224
|
-
setSettleFn == null ? void 0 : setSettleFn(() => {
|
|
225
|
-
if (this._settled) {
|
|
226
|
-
throw new Error("SettleSignal already settled");
|
|
227
|
-
}
|
|
228
|
-
this._settled = true;
|
|
229
|
-
this.dispatchEvent(new Event("settled"));
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
static settle() {
|
|
233
|
-
const signal = new SettleSignal();
|
|
234
|
-
signal._settled = true;
|
|
235
|
-
return signal;
|
|
236
|
-
}
|
|
237
|
-
get settled() {
|
|
238
|
-
return this._settled;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
class SettleController {
|
|
243
|
-
constructor() {
|
|
244
|
-
this._settleFn = void 0;
|
|
245
|
-
this._signal = void 0;
|
|
246
|
-
this._signal = new SettleSignal(settleFn => this._settleFn = settleFn);
|
|
247
|
-
}
|
|
248
|
-
get signal() {
|
|
249
|
-
return this._signal;
|
|
250
|
-
}
|
|
251
|
-
settle() {
|
|
252
|
-
var _this$_settleFn;
|
|
253
|
-
(_this$_settleFn = this._settleFn) == null ? void 0 : _this$_settleFn.call(this);
|
|
254
|
-
}
|
|
65
|
+
return _extends.apply(this, arguments);
|
|
255
66
|
}
|
|
256
67
|
|
|
257
|
-
const defaultConfig$
|
|
258
|
-
const
|
|
259
|
-
if (typeof config === "string") {
|
|
260
|
-
return {
|
|
261
|
-
classes: [config],
|
|
262
|
-
style: {}
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
if (Array.isArray(config)) {
|
|
266
|
-
return {
|
|
267
|
-
classes: config,
|
|
268
|
-
style: {}
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
if (typeof config === "object") {
|
|
272
|
-
if ("classes" in config && config.classes != null && "style" in config && config.style != null) {
|
|
273
|
-
return config;
|
|
274
|
-
}
|
|
275
|
-
return {
|
|
276
|
-
classes: [],
|
|
277
|
-
style: config
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
throw new Error(`Invalid config: ${config}`);
|
|
281
|
-
};
|
|
282
|
-
const adapter$4 = (children, config) => {
|
|
283
|
-
const {
|
|
284
|
-
classes,
|
|
285
|
-
style
|
|
286
|
-
} = normalizeConfig(config);
|
|
287
|
-
return React.createElement("div", {
|
|
288
|
-
"data-testid": "css-adapter-container",
|
|
289
|
-
className: classes.join(" "),
|
|
290
|
-
style: style
|
|
291
|
-
}, children);
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
const defaultConfig$3 = [];
|
|
295
|
-
const adapter$3 = (children, config) => {
|
|
68
|
+
const defaultConfig$1 = [];
|
|
69
|
+
const adapter$1 = (children, config) => {
|
|
296
70
|
let currentChildren = children;
|
|
297
71
|
const interceptors = Array.isArray(config) ? config : [config];
|
|
298
72
|
for (const interceptor of interceptors) {
|
|
@@ -303,63 +77,6 @@ const adapter$3 = (children, config) => {
|
|
|
303
77
|
return React.createElement(React.Fragment, null, currentChildren);
|
|
304
78
|
};
|
|
305
79
|
|
|
306
|
-
const defaultConfig$2 = null;
|
|
307
|
-
const adapter$2 = (children, config) => React.createElement(React.Fragment, null, React.createElement("div", {
|
|
308
|
-
id: config,
|
|
309
|
-
"data-testid": config
|
|
310
|
-
}), children);
|
|
311
|
-
|
|
312
|
-
const defaultConfig$1 = {
|
|
313
|
-
location: "/"
|
|
314
|
-
};
|
|
315
|
-
const maybeWithRoute = (children, path) => {
|
|
316
|
-
if (path == null) {
|
|
317
|
-
return React.createElement(React.Fragment, null, children);
|
|
318
|
-
}
|
|
319
|
-
return React.createElement(Switch, null, React.createElement(Route, {
|
|
320
|
-
exact: true,
|
|
321
|
-
path: path
|
|
322
|
-
}, children), React.createElement(Route, {
|
|
323
|
-
path: "*",
|
|
324
|
-
render: () => {
|
|
325
|
-
throw new Error("The configured path must match the configured location or your harnessed component will not render.");
|
|
326
|
-
}
|
|
327
|
-
}));
|
|
328
|
-
};
|
|
329
|
-
const adapter$1 = (children, config) => {
|
|
330
|
-
if (typeof config === "string") {
|
|
331
|
-
config = {
|
|
332
|
-
location: config
|
|
333
|
-
};
|
|
334
|
-
}
|
|
335
|
-
const wrappedWithRoute = maybeWithRoute(children, config.path);
|
|
336
|
-
if ("forceStatic" in config && config.forceStatic) {
|
|
337
|
-
return React.createElement(StaticRouter, {
|
|
338
|
-
location: config.location,
|
|
339
|
-
context: {}
|
|
340
|
-
}, wrappedWithRoute);
|
|
341
|
-
}
|
|
342
|
-
if ("location" in config && config.location !== undefined) {
|
|
343
|
-
return React.createElement(MemoryRouter, {
|
|
344
|
-
initialEntries: [config.location]
|
|
345
|
-
}, wrappedWithRoute);
|
|
346
|
-
}
|
|
347
|
-
if (!("initialEntries" in config) || config.initialEntries === undefined) {
|
|
348
|
-
throw new Error("A location or initial history entries must be provided.");
|
|
349
|
-
}
|
|
350
|
-
const entries = config.initialEntries.length === 0 ? [defaultConfig$1.location] : config.initialEntries;
|
|
351
|
-
const routerProps = {
|
|
352
|
-
initialEntries: entries
|
|
353
|
-
};
|
|
354
|
-
if (config.initialIndex != null) {
|
|
355
|
-
routerProps.initialIndex = config.initialIndex;
|
|
356
|
-
}
|
|
357
|
-
if (config.getUserConfirmation != null) {
|
|
358
|
-
routerProps.getUserConfirmation = config.getUserConfirmation;
|
|
359
|
-
}
|
|
360
|
-
return React.createElement(MemoryRouter, routerProps, wrappedWithRoute);
|
|
361
|
-
};
|
|
362
|
-
|
|
363
80
|
const defaultConfig = null;
|
|
364
81
|
const adapter = (children, config) => {
|
|
365
82
|
if (config !== true) {
|
|
@@ -375,100 +92,22 @@ const adapter = (children, config) => {
|
|
|
375
92
|
};
|
|
376
93
|
|
|
377
94
|
const DefaultAdapters = {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
95
|
+
boundary: harnessAdapters.DefaultAdapters.boundary,
|
|
96
|
+
css: harnessAdapters.DefaultAdapters.css,
|
|
97
|
+
data: adapter$1,
|
|
98
|
+
portal: harnessAdapters.DefaultAdapters.portal,
|
|
99
|
+
router: harnessAdapters.DefaultAdapters.router,
|
|
382
100
|
ssr: adapter
|
|
383
101
|
};
|
|
384
|
-
const DefaultConfigs = {
|
|
385
|
-
|
|
386
|
-
data: defaultConfig$3,
|
|
387
|
-
portal: defaultConfig$2,
|
|
388
|
-
router: defaultConfig$1,
|
|
102
|
+
const DefaultConfigs = _extends({}, harnessAdapters.DefaultConfigs, {
|
|
103
|
+
data: defaultConfig$1,
|
|
389
104
|
ssr: defaultConfig
|
|
390
|
-
};
|
|
105
|
+
});
|
|
391
106
|
|
|
392
|
-
var
|
|
107
|
+
var index = /*#__PURE__*/Object.freeze({
|
|
393
108
|
__proto__: null,
|
|
394
109
|
DefaultAdapters: DefaultAdapters,
|
|
395
110
|
DefaultConfigs: DefaultConfigs
|
|
396
111
|
});
|
|
397
112
|
|
|
398
|
-
|
|
399
|
-
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
400
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
401
|
-
var source = arguments[i];
|
|
402
|
-
for (var key in source) {
|
|
403
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
404
|
-
target[key] = source[key];
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
return target;
|
|
409
|
-
};
|
|
410
|
-
return _extends.apply(this, arguments);
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
const componentCache = new Map();
|
|
414
|
-
const getNamedAdapterComponent = name => {
|
|
415
|
-
const existing = componentCache.get(name);
|
|
416
|
-
if (existing != null) {
|
|
417
|
-
return existing;
|
|
418
|
-
}
|
|
419
|
-
const newComponent = ({
|
|
420
|
-
children,
|
|
421
|
-
config,
|
|
422
|
-
adapter
|
|
423
|
-
}) => adapter(children, config);
|
|
424
|
-
newComponent.displayName = `Adapter(${name})`;
|
|
425
|
-
componentCache.set(name, newComponent);
|
|
426
|
-
return newComponent;
|
|
427
|
-
};
|
|
428
|
-
|
|
429
|
-
const Adapt = ({
|
|
430
|
-
children,
|
|
431
|
-
adapters,
|
|
432
|
-
configs
|
|
433
|
-
}) => {
|
|
434
|
-
return Object.entries(adapters).reduce((newChildren, [name, adapter]) => {
|
|
435
|
-
const theConfig = configs[name];
|
|
436
|
-
if (theConfig == null) {
|
|
437
|
-
return newChildren;
|
|
438
|
-
}
|
|
439
|
-
const Adapter = getNamedAdapterComponent(name);
|
|
440
|
-
return React.createElement(Adapter, {
|
|
441
|
-
key: name,
|
|
442
|
-
adapter: adapter,
|
|
443
|
-
config: theConfig
|
|
444
|
-
}, newChildren);
|
|
445
|
-
}, React.createElement(React.Fragment, null, children));
|
|
446
|
-
};
|
|
447
|
-
|
|
448
|
-
const makeTestHarness = (adapters, defaultConfigs) => {
|
|
449
|
-
return (Component, configs) => {
|
|
450
|
-
const fullConfig = _extends({}, defaultConfigs, configs);
|
|
451
|
-
const harnessedComponent = React.forwardRef((props, ref) => React.createElement(Adapt, {
|
|
452
|
-
adapters: adapters,
|
|
453
|
-
configs: fullConfig
|
|
454
|
-
}, React.createElement(Component, _extends({}, props, {
|
|
455
|
-
ref: ref
|
|
456
|
-
}))));
|
|
457
|
-
harnessedComponent.displayName = `testHarness(${Component.displayName || Component.name || "Component"})`;
|
|
458
|
-
return harnessedComponent;
|
|
459
|
-
};
|
|
460
|
-
};
|
|
461
|
-
|
|
462
|
-
const HookHarness = ({
|
|
463
|
-
children
|
|
464
|
-
}) => React.createElement(React.Fragment, null, children);
|
|
465
|
-
const makeHookHarness = (adapters, defaultConfigs) => {
|
|
466
|
-
const testHarness = makeTestHarness(adapters, defaultConfigs);
|
|
467
|
-
return configs => testHarness(HookHarness, configs);
|
|
468
|
-
};
|
|
469
|
-
|
|
470
|
-
const hookHarness = makeHookHarness(DefaultAdapters, DefaultConfigs);
|
|
471
|
-
|
|
472
|
-
const testHarness = makeTestHarness(DefaultAdapters, DefaultConfigs);
|
|
473
|
-
|
|
474
|
-
export { RespondWith, SettleController, fixtures, adapters as harnessAdapters, hookHarness, makeHookHarness, makeTestHarness, mockFetch, mockGqlFetch, testHarness };
|
|
113
|
+
export { index as harnessAdapters, mockGqlFetch };
|
package/dist/gql/types.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { GqlOperation, GqlContext } from "@khanacademy/wonder-blocks-data";
|
|
2
|
-
import type { GraphQLJson } from "
|
|
3
|
-
import type { MockResponse } from "../respond-with";
|
|
2
|
+
import type { GraphQLJson, MockResponse } from "@khanacademy/wonder-blocks-testing-core";
|
|
4
3
|
export type GqlMockOperation<TData extends Record<any, any>, TVariables extends Record<any, any>, TContext extends GqlContext> = {
|
|
5
4
|
operation: GqlOperation<TData, TVariables>;
|
|
6
5
|
variables?: TVariables;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { InterceptRequests } from "@khanacademy/wonder-blocks-data";
|
|
3
|
-
import type { TestHarnessAdapter } from "
|
|
3
|
+
import type { TestHarnessAdapter } from "@khanacademy/wonder-blocks-testing-core";
|
|
4
4
|
type Interceptor = JSX.LibraryManagedAttributes<typeof InterceptRequests, React.ComponentProps<typeof InterceptRequests>>["interceptor"];
|
|
5
5
|
type Config = Interceptor | Array<Interceptor>;
|
|
6
6
|
/**
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/// <reference path="../../../../wonder-blocks-testing-core/types/aphrodite.d.ts" />
|
|
2
|
+
/// <reference path="../../../types/aphrodite.d.ts" />
|
|
3
|
+
/// <reference types="react" />
|
|
4
|
+
import type { TestHarnessConfigs } from "@khanacademy/wonder-blocks-testing-core";
|
|
5
|
+
/**
|
|
6
|
+
* NOTE: We do not type `DefaultAdapters` with `Adapters` here because we want
|
|
7
|
+
* the individual config types of each adapter to remain intact rather than
|
|
8
|
+
* getting changed to `any`.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* The default adapters provided by Wonder Blocks.
|
|
12
|
+
*/
|
|
13
|
+
export declare const DefaultAdapters: {
|
|
14
|
+
readonly boundary: import("@khanacademy/wonder-blocks-testing-core").TestHarnessAdapter<(error: Error | null | undefined, errorInfo: {
|
|
15
|
+
componentStack: string;
|
|
16
|
+
}) => import("react").ReactNode>;
|
|
17
|
+
readonly css: import("@khanacademy/wonder-blocks-testing-core").TestHarnessAdapter<string | string[] | import("aphrodite").CSSProperties | {
|
|
18
|
+
classes: string[];
|
|
19
|
+
style: import("aphrodite").CSSProperties;
|
|
20
|
+
}>;
|
|
21
|
+
readonly data: import("@khanacademy/wonder-blocks-testing-core").TestHarnessAdapter<((requestId: string) => Promise<import("@khanacademy/wonder-blocks-data").ValidCacheData> | null | undefined) | ((requestId: string) => Promise<import("@khanacademy/wonder-blocks-data").ValidCacheData> | null | undefined)[]>;
|
|
22
|
+
readonly portal: import("@khanacademy/wonder-blocks-testing-core").TestHarnessAdapter<string>;
|
|
23
|
+
readonly router: import("@khanacademy/wonder-blocks-testing-core").TestHarnessAdapter<string | Readonly<{
|
|
24
|
+
initialEntries: import("history").LocationDescriptor<unknown>[] | undefined;
|
|
25
|
+
initialIndex?: number | undefined;
|
|
26
|
+
getUserConfirmation?: ((message: string, callback: (ok: boolean) => void) => void) | undefined;
|
|
27
|
+
path?: string | undefined;
|
|
28
|
+
} | {
|
|
29
|
+
location: import("history").LocationDescriptor<unknown>;
|
|
30
|
+
forceStatic: true;
|
|
31
|
+
path?: string | undefined;
|
|
32
|
+
} | {
|
|
33
|
+
location: import("history").LocationDescriptor<unknown>;
|
|
34
|
+
path?: string | undefined;
|
|
35
|
+
}>>;
|
|
36
|
+
readonly ssr: import("@khanacademy/wonder-blocks-testing-core").TestHarnessAdapter<true>;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* The default configurations to use with the `DefaultAdapters`.
|
|
40
|
+
*/
|
|
41
|
+
export declare const DefaultConfigs: TestHarnessConfigs<typeof DefaultAdapters>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
export { fixtures } from "
|
|
2
|
-
export type { FixtureFn, FixtureProps, GetPropsOptions } from "
|
|
3
|
-
export { mockFetch } from "
|
|
1
|
+
export { fixtures } from "@khanacademy/wonder-blocks-testing-core";
|
|
2
|
+
export type { FixtureFn, FixtureProps, GetPropsOptions, } from "@khanacademy/wonder-blocks-testing-core";
|
|
3
|
+
export { mockFetch, RespondWith, SettleController, } from "@khanacademy/wonder-blocks-testing-core";
|
|
4
4
|
export { mockGqlFetch } from "./gql/mock-gql-fetch";
|
|
5
|
-
export {
|
|
6
|
-
export { SettleController } from "./settle-controller";
|
|
7
|
-
export type { MockResponse } from "./respond-with";
|
|
8
|
-
export type { FetchMockFn, FetchMockOperation } from "./fetch/types";
|
|
5
|
+
export type { MockResponse, FetchMockFn, FetchMockOperation, } from "@khanacademy/wonder-blocks-testing-core";
|
|
9
6
|
export type { GqlFetchMockFn, GqlMockOperation } from "./gql/types";
|
|
10
|
-
export
|
|
11
|
-
export * as harnessAdapters from "./harness/adapters
|
|
12
|
-
export { makeHookHarness } from "
|
|
13
|
-
export {
|
|
14
|
-
export { hookHarness } from "./harness/hook-harness";
|
|
15
|
-
export { testHarness } from "./harness/test-harness";
|
|
7
|
+
export type { TestHarnessAdapter, TestHarnessAdapters, TestHarnessConfig, TestHarnessConfigs, } from "@khanacademy/wonder-blocks-testing-core";
|
|
8
|
+
export * as harnessAdapters from "./harness/adapters";
|
|
9
|
+
export { makeHookHarness, makeTestHarness, hookHarness, testHarness, } from "@khanacademy/wonder-blocks-testing-core";
|
|
10
|
+
export { renderHookStatic } from "@khanacademy/wonder-blocks-testing-core";
|