@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
package/dist/index.js
CHANGED
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
+
var wonderBlocksTestingCore = require('@khanacademy/wonder-blocks-testing-core');
|
|
5
6
|
var React = require('react');
|
|
6
|
-
var addonActions = require('@storybook/addon-actions');
|
|
7
7
|
var wonderBlocksData = require('@khanacademy/wonder-blocks-data');
|
|
8
|
-
var reactRouterDom = require('react-router-dom');
|
|
9
8
|
var wonderStuffCore = require('@khanacademy/wonder-stuff-core');
|
|
10
9
|
var wonderBlocksCore = require('@khanacademy/wonder-blocks-core');
|
|
11
10
|
|
|
@@ -29,86 +28,6 @@ function _interopNamespace(e) {
|
|
|
29
28
|
|
|
30
29
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
31
30
|
|
|
32
|
-
const fixtures = Component => {
|
|
33
|
-
const templateMap = new WeakMap();
|
|
34
|
-
let storyNumber = 1;
|
|
35
|
-
const getPropsOptions = {
|
|
36
|
-
log: (message, ...args) => addonActions.action(message)(...args),
|
|
37
|
-
logHandler: addonActions.action
|
|
38
|
-
};
|
|
39
|
-
const makeStory = (description, props, wrapper = null) => {
|
|
40
|
-
const storyName = `${storyNumber++} ${description}`;
|
|
41
|
-
const getProps = options => typeof props === "function" ? props(options) : props;
|
|
42
|
-
const RealComponent = wrapper || Component;
|
|
43
|
-
let Template = templateMap.get(RealComponent);
|
|
44
|
-
if (Template == null) {
|
|
45
|
-
Template = args => React__namespace.createElement(RealComponent, args);
|
|
46
|
-
templateMap.set(RealComponent, Template);
|
|
47
|
-
}
|
|
48
|
-
const story = Template.bind({});
|
|
49
|
-
story.args = getProps(getPropsOptions);
|
|
50
|
-
story.storyName = storyName;
|
|
51
|
-
return story;
|
|
52
|
-
};
|
|
53
|
-
return makeStory;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
const getHref = input => {
|
|
57
|
-
if (typeof input === "string") {
|
|
58
|
-
return input;
|
|
59
|
-
} else if (typeof input.url === "string") {
|
|
60
|
-
return input.url;
|
|
61
|
-
} else if (typeof input.href === "string") {
|
|
62
|
-
return input.href;
|
|
63
|
-
} else {
|
|
64
|
-
throw new Error(`Unsupported input type`);
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
const fetchRequestMatchesMock = (mock, input, init) => {
|
|
68
|
-
const href = getHref(input);
|
|
69
|
-
if (typeof mock === "string") {
|
|
70
|
-
return href === mock;
|
|
71
|
-
} else if (mock instanceof RegExp) {
|
|
72
|
-
return mock.test(href);
|
|
73
|
-
} else {
|
|
74
|
-
throw new Error(`Unsupported mock operation: ${JSON.stringify(mock)}`);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const mockRequester = (operationMatcher, operationToString) => {
|
|
79
|
-
const mocks = [];
|
|
80
|
-
const mockFn = (...args) => {
|
|
81
|
-
for (const mock of mocks) {
|
|
82
|
-
if (mock.onceOnly && mock.used) {
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
if (operationMatcher(mock.operation, ...args)) {
|
|
86
|
-
mock.used = true;
|
|
87
|
-
return mock.response();
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
const operation = operationToString(...args);
|
|
91
|
-
return Promise.reject(new Error(`No matching mock response found for request:
|
|
92
|
-
${operation}`));
|
|
93
|
-
};
|
|
94
|
-
const addMockedOperation = (operation, response, onceOnly) => {
|
|
95
|
-
const mockResponse = () => response.toPromise();
|
|
96
|
-
mocks.push({
|
|
97
|
-
operation,
|
|
98
|
-
response: mockResponse,
|
|
99
|
-
onceOnly,
|
|
100
|
-
used: false
|
|
101
|
-
});
|
|
102
|
-
return mockFn;
|
|
103
|
-
};
|
|
104
|
-
mockFn.mockOperation = (operation, response) => addMockedOperation(operation, response, false);
|
|
105
|
-
mockFn.mockOperationOnce = (operation, response) => addMockedOperation(operation, response, true);
|
|
106
|
-
return mockFn;
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const mockFetch = () => mockRequester(fetchRequestMatchesMock, (input, init) => `Input: ${typeof input === "string" ? input : JSON.stringify(input, null, 2)}
|
|
110
|
-
Options: ${init == null ? "None" : JSON.stringify(init, null, 2)}`);
|
|
111
|
-
|
|
112
31
|
const safeHasOwnProperty = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
|
|
113
32
|
const areObjectsEqual = (a, b) => {
|
|
114
33
|
if (a === b) {
|
|
@@ -150,173 +69,27 @@ const gqlRequestMatchesMock = (mock, operation, variables, context) => {
|
|
|
150
69
|
return true;
|
|
151
70
|
};
|
|
152
71
|
|
|
153
|
-
const mockGqlFetch = () => mockRequester(gqlRequestMatchesMock, (operation, variables, context) => `Operation: ${operation.type} ${operation.id}
|
|
72
|
+
const mockGqlFetch = () => wonderBlocksTestingCore.mockRequester(gqlRequestMatchesMock, (operation, variables, context) => `Operation: ${operation.type} ${operation.id}
|
|
154
73
|
Variables: ${variables == null ? "None" : JSON.stringify(variables, null, 2)}
|
|
155
74
|
Context: ${JSON.stringify(context, null, 2)}`);
|
|
156
75
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
});
|
|
167
|
-
const rejectResponse = (error, signal) => ({
|
|
168
|
-
toPromise: () => makeMockResponse({
|
|
169
|
-
type: "reject",
|
|
170
|
-
error,
|
|
171
|
-
signal
|
|
172
|
-
})
|
|
173
|
-
});
|
|
174
|
-
const RespondWith = Object.freeze({
|
|
175
|
-
text: (text, statusCode = 200, signal = null) => textResponse(text, statusCode, signal),
|
|
176
|
-
json: (json, signal = null) => textResponse(() => JSON.stringify(json), 200, signal),
|
|
177
|
-
graphQLData: (data, signal = null) => textResponse(() => JSON.stringify({
|
|
178
|
-
data
|
|
179
|
-
}), 200, signal),
|
|
180
|
-
unparseableBody: (signal = null) => textResponse("INVALID JSON", 200, signal),
|
|
181
|
-
abortedRequest: (signal = null) => rejectResponse(() => {
|
|
182
|
-
const abortError = new Error("Mock request aborted");
|
|
183
|
-
abortError.name = "AbortError";
|
|
184
|
-
return abortError;
|
|
185
|
-
}, signal),
|
|
186
|
-
reject: (error, signal = null) => rejectResponse(error, signal),
|
|
187
|
-
errorStatusCode: (statusCode, signal = null) => {
|
|
188
|
-
if (statusCode < 300) {
|
|
189
|
-
throw new Error(`${statusCode} is not a valid error status code`);
|
|
76
|
+
function _extends() {
|
|
77
|
+
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
78
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
79
|
+
var source = arguments[i];
|
|
80
|
+
for (var key in source) {
|
|
81
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
82
|
+
target[key] = source[key];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
190
85
|
}
|
|
191
|
-
return
|
|
192
|
-
},
|
|
193
|
-
nonGraphQLBody: (signal = null) => textResponse(() => JSON.stringify({
|
|
194
|
-
valid: "json",
|
|
195
|
-
that: "is not a valid graphql response"
|
|
196
|
-
}), 200, signal),
|
|
197
|
-
graphQLErrors: (errorMessages, signal = null) => textResponse(() => JSON.stringify({
|
|
198
|
-
errors: errorMessages.map(e => ({
|
|
199
|
-
message: e
|
|
200
|
-
}))
|
|
201
|
-
}), 200, signal)
|
|
202
|
-
});
|
|
203
|
-
const callOnSettled = (signal, fn) => {
|
|
204
|
-
if (signal == null || signal.settled) {
|
|
205
|
-
fn();
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
const onSettled = () => {
|
|
209
|
-
signal.removeEventListener("settled", onSettled);
|
|
210
|
-
fn();
|
|
86
|
+
return target;
|
|
211
87
|
};
|
|
212
|
-
|
|
213
|
-
};
|
|
214
|
-
const makeMockResponse = response => {
|
|
215
|
-
const {
|
|
216
|
-
signal
|
|
217
|
-
} = response;
|
|
218
|
-
switch (response.type) {
|
|
219
|
-
case "text":
|
|
220
|
-
return new Promise((resolve, reject) => {
|
|
221
|
-
callOnSettled(signal, () => {
|
|
222
|
-
const text = typeof response.text === "function" ? response.text() : response.text;
|
|
223
|
-
resolve(new ResponseImpl(text, {
|
|
224
|
-
status: response.statusCode
|
|
225
|
-
}));
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
case "reject":
|
|
229
|
-
return new Promise((resolve, reject) => {
|
|
230
|
-
callOnSettled(signal, () => reject(response.error instanceof Error ? response.error : response.error()));
|
|
231
|
-
});
|
|
232
|
-
default:
|
|
233
|
-
if (process.env.NODE_ENV !== "production") {
|
|
234
|
-
throw new Error(`Unknown response type: ${response.type}`);
|
|
235
|
-
}
|
|
236
|
-
return makeMockResponse({
|
|
237
|
-
type: "reject",
|
|
238
|
-
error: new Error("Unknown response type"),
|
|
239
|
-
signal
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
class SettleSignal extends EventTarget {
|
|
245
|
-
constructor(setSettleFn = null) {
|
|
246
|
-
super();
|
|
247
|
-
this._settled = false;
|
|
248
|
-
setSettleFn == null ? void 0 : setSettleFn(() => {
|
|
249
|
-
if (this._settled) {
|
|
250
|
-
throw new Error("SettleSignal already settled");
|
|
251
|
-
}
|
|
252
|
-
this._settled = true;
|
|
253
|
-
this.dispatchEvent(new Event("settled"));
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
static settle() {
|
|
257
|
-
const signal = new SettleSignal();
|
|
258
|
-
signal._settled = true;
|
|
259
|
-
return signal;
|
|
260
|
-
}
|
|
261
|
-
get settled() {
|
|
262
|
-
return this._settled;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
class SettleController {
|
|
267
|
-
constructor() {
|
|
268
|
-
this._settleFn = void 0;
|
|
269
|
-
this._signal = void 0;
|
|
270
|
-
this._signal = new SettleSignal(settleFn => this._settleFn = settleFn);
|
|
271
|
-
}
|
|
272
|
-
get signal() {
|
|
273
|
-
return this._signal;
|
|
274
|
-
}
|
|
275
|
-
settle() {
|
|
276
|
-
var _this$_settleFn;
|
|
277
|
-
(_this$_settleFn = this._settleFn) == null ? void 0 : _this$_settleFn.call(this);
|
|
278
|
-
}
|
|
88
|
+
return _extends.apply(this, arguments);
|
|
279
89
|
}
|
|
280
90
|
|
|
281
|
-
const defaultConfig$
|
|
282
|
-
const
|
|
283
|
-
if (typeof config === "string") {
|
|
284
|
-
return {
|
|
285
|
-
classes: [config],
|
|
286
|
-
style: {}
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
if (Array.isArray(config)) {
|
|
290
|
-
return {
|
|
291
|
-
classes: config,
|
|
292
|
-
style: {}
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
if (typeof config === "object") {
|
|
296
|
-
if ("classes" in config && config.classes != null && "style" in config && config.style != null) {
|
|
297
|
-
return config;
|
|
298
|
-
}
|
|
299
|
-
return {
|
|
300
|
-
classes: [],
|
|
301
|
-
style: config
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
throw new Error(`Invalid config: ${config}`);
|
|
305
|
-
};
|
|
306
|
-
const adapter$4 = (children, config) => {
|
|
307
|
-
const {
|
|
308
|
-
classes,
|
|
309
|
-
style
|
|
310
|
-
} = normalizeConfig(config);
|
|
311
|
-
return React__namespace.createElement("div", {
|
|
312
|
-
"data-testid": "css-adapter-container",
|
|
313
|
-
className: classes.join(" "),
|
|
314
|
-
style: style
|
|
315
|
-
}, children);
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
const defaultConfig$3 = [];
|
|
319
|
-
const adapter$3 = (children, config) => {
|
|
91
|
+
const defaultConfig$1 = [];
|
|
92
|
+
const adapter$1 = (children, config) => {
|
|
320
93
|
let currentChildren = children;
|
|
321
94
|
const interceptors = Array.isArray(config) ? config : [config];
|
|
322
95
|
for (const interceptor of interceptors) {
|
|
@@ -327,63 +100,6 @@ const adapter$3 = (children, config) => {
|
|
|
327
100
|
return React__namespace.createElement(React__namespace.Fragment, null, currentChildren);
|
|
328
101
|
};
|
|
329
102
|
|
|
330
|
-
const defaultConfig$2 = null;
|
|
331
|
-
const adapter$2 = (children, config) => React__namespace.createElement(React__namespace.Fragment, null, React__namespace.createElement("div", {
|
|
332
|
-
id: config,
|
|
333
|
-
"data-testid": config
|
|
334
|
-
}), children);
|
|
335
|
-
|
|
336
|
-
const defaultConfig$1 = {
|
|
337
|
-
location: "/"
|
|
338
|
-
};
|
|
339
|
-
const maybeWithRoute = (children, path) => {
|
|
340
|
-
if (path == null) {
|
|
341
|
-
return React__namespace.createElement(React__namespace.Fragment, null, children);
|
|
342
|
-
}
|
|
343
|
-
return React__namespace.createElement(reactRouterDom.Switch, null, React__namespace.createElement(reactRouterDom.Route, {
|
|
344
|
-
exact: true,
|
|
345
|
-
path: path
|
|
346
|
-
}, children), React__namespace.createElement(reactRouterDom.Route, {
|
|
347
|
-
path: "*",
|
|
348
|
-
render: () => {
|
|
349
|
-
throw new Error("The configured path must match the configured location or your harnessed component will not render.");
|
|
350
|
-
}
|
|
351
|
-
}));
|
|
352
|
-
};
|
|
353
|
-
const adapter$1 = (children, config) => {
|
|
354
|
-
if (typeof config === "string") {
|
|
355
|
-
config = {
|
|
356
|
-
location: config
|
|
357
|
-
};
|
|
358
|
-
}
|
|
359
|
-
const wrappedWithRoute = maybeWithRoute(children, config.path);
|
|
360
|
-
if ("forceStatic" in config && config.forceStatic) {
|
|
361
|
-
return React__namespace.createElement(reactRouterDom.StaticRouter, {
|
|
362
|
-
location: config.location,
|
|
363
|
-
context: {}
|
|
364
|
-
}, wrappedWithRoute);
|
|
365
|
-
}
|
|
366
|
-
if ("location" in config && config.location !== undefined) {
|
|
367
|
-
return React__namespace.createElement(reactRouterDom.MemoryRouter, {
|
|
368
|
-
initialEntries: [config.location]
|
|
369
|
-
}, wrappedWithRoute);
|
|
370
|
-
}
|
|
371
|
-
if (!("initialEntries" in config) || config.initialEntries === undefined) {
|
|
372
|
-
throw new Error("A location or initial history entries must be provided.");
|
|
373
|
-
}
|
|
374
|
-
const entries = config.initialEntries.length === 0 ? [defaultConfig$1.location] : config.initialEntries;
|
|
375
|
-
const routerProps = {
|
|
376
|
-
initialEntries: entries
|
|
377
|
-
};
|
|
378
|
-
if (config.initialIndex != null) {
|
|
379
|
-
routerProps.initialIndex = config.initialIndex;
|
|
380
|
-
}
|
|
381
|
-
if (config.getUserConfirmation != null) {
|
|
382
|
-
routerProps.getUserConfirmation = config.getUserConfirmation;
|
|
383
|
-
}
|
|
384
|
-
return React__namespace.createElement(reactRouterDom.MemoryRouter, routerProps, wrappedWithRoute);
|
|
385
|
-
};
|
|
386
|
-
|
|
387
103
|
const defaultConfig = null;
|
|
388
104
|
const adapter = (children, config) => {
|
|
389
105
|
if (config !== true) {
|
|
@@ -399,109 +115,59 @@ const adapter = (children, config) => {
|
|
|
399
115
|
};
|
|
400
116
|
|
|
401
117
|
const DefaultAdapters = {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
118
|
+
boundary: wonderBlocksTestingCore.harnessAdapters.DefaultAdapters.boundary,
|
|
119
|
+
css: wonderBlocksTestingCore.harnessAdapters.DefaultAdapters.css,
|
|
120
|
+
data: adapter$1,
|
|
121
|
+
portal: wonderBlocksTestingCore.harnessAdapters.DefaultAdapters.portal,
|
|
122
|
+
router: wonderBlocksTestingCore.harnessAdapters.DefaultAdapters.router,
|
|
406
123
|
ssr: adapter
|
|
407
124
|
};
|
|
408
|
-
const DefaultConfigs = {
|
|
409
|
-
|
|
410
|
-
data: defaultConfig$3,
|
|
411
|
-
portal: defaultConfig$2,
|
|
412
|
-
router: defaultConfig$1,
|
|
125
|
+
const DefaultConfigs = _extends({}, wonderBlocksTestingCore.harnessAdapters.DefaultConfigs, {
|
|
126
|
+
data: defaultConfig$1,
|
|
413
127
|
ssr: defaultConfig
|
|
414
|
-
};
|
|
128
|
+
});
|
|
415
129
|
|
|
416
|
-
var
|
|
130
|
+
var index = /*#__PURE__*/Object.freeze({
|
|
417
131
|
__proto__: null,
|
|
418
132
|
DefaultAdapters: DefaultAdapters,
|
|
419
133
|
DefaultConfigs: DefaultConfigs
|
|
420
134
|
});
|
|
421
135
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
return
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
})
|
|
458
|
-
|
|
459
|
-
const theConfig = configs[name];
|
|
460
|
-
if (theConfig == null) {
|
|
461
|
-
return newChildren;
|
|
462
|
-
}
|
|
463
|
-
const Adapter = getNamedAdapterComponent(name);
|
|
464
|
-
return React__namespace.createElement(Adapter, {
|
|
465
|
-
key: name,
|
|
466
|
-
adapter: adapter,
|
|
467
|
-
config: theConfig
|
|
468
|
-
}, newChildren);
|
|
469
|
-
}, React__namespace.createElement(React__namespace.Fragment, null, children));
|
|
470
|
-
};
|
|
471
|
-
|
|
472
|
-
const makeTestHarness = (adapters, defaultConfigs) => {
|
|
473
|
-
return (Component, configs) => {
|
|
474
|
-
const fullConfig = _extends({}, defaultConfigs, configs);
|
|
475
|
-
const harnessedComponent = React__namespace.forwardRef((props, ref) => React__namespace.createElement(Adapt, {
|
|
476
|
-
adapters: adapters,
|
|
477
|
-
configs: fullConfig
|
|
478
|
-
}, React__namespace.createElement(Component, _extends({}, props, {
|
|
479
|
-
ref: ref
|
|
480
|
-
}))));
|
|
481
|
-
harnessedComponent.displayName = `testHarness(${Component.displayName || Component.name || "Component"})`;
|
|
482
|
-
return harnessedComponent;
|
|
483
|
-
};
|
|
484
|
-
};
|
|
485
|
-
|
|
486
|
-
const HookHarness = ({
|
|
487
|
-
children
|
|
488
|
-
}) => React__namespace.createElement(React__namespace.Fragment, null, children);
|
|
489
|
-
const makeHookHarness = (adapters, defaultConfigs) => {
|
|
490
|
-
const testHarness = makeTestHarness(adapters, defaultConfigs);
|
|
491
|
-
return configs => testHarness(HookHarness, configs);
|
|
492
|
-
};
|
|
493
|
-
|
|
494
|
-
const hookHarness = makeHookHarness(DefaultAdapters, DefaultConfigs);
|
|
495
|
-
|
|
496
|
-
const testHarness = makeTestHarness(DefaultAdapters, DefaultConfigs);
|
|
497
|
-
|
|
498
|
-
exports.RespondWith = RespondWith;
|
|
499
|
-
exports.SettleController = SettleController;
|
|
500
|
-
exports.fixtures = fixtures;
|
|
501
|
-
exports.harnessAdapters = adapters;
|
|
502
|
-
exports.hookHarness = hookHarness;
|
|
503
|
-
exports.makeHookHarness = makeHookHarness;
|
|
504
|
-
exports.makeTestHarness = makeTestHarness;
|
|
505
|
-
exports.mockFetch = mockFetch;
|
|
136
|
+
Object.defineProperty(exports, 'RespondWith', {
|
|
137
|
+
enumerable: true,
|
|
138
|
+
get: function () { return wonderBlocksTestingCore.RespondWith; }
|
|
139
|
+
});
|
|
140
|
+
Object.defineProperty(exports, 'SettleController', {
|
|
141
|
+
enumerable: true,
|
|
142
|
+
get: function () { return wonderBlocksTestingCore.SettleController; }
|
|
143
|
+
});
|
|
144
|
+
Object.defineProperty(exports, 'fixtures', {
|
|
145
|
+
enumerable: true,
|
|
146
|
+
get: function () { return wonderBlocksTestingCore.fixtures; }
|
|
147
|
+
});
|
|
148
|
+
Object.defineProperty(exports, 'hookHarness', {
|
|
149
|
+
enumerable: true,
|
|
150
|
+
get: function () { return wonderBlocksTestingCore.hookHarness; }
|
|
151
|
+
});
|
|
152
|
+
Object.defineProperty(exports, 'makeHookHarness', {
|
|
153
|
+
enumerable: true,
|
|
154
|
+
get: function () { return wonderBlocksTestingCore.makeHookHarness; }
|
|
155
|
+
});
|
|
156
|
+
Object.defineProperty(exports, 'makeTestHarness', {
|
|
157
|
+
enumerable: true,
|
|
158
|
+
get: function () { return wonderBlocksTestingCore.makeTestHarness; }
|
|
159
|
+
});
|
|
160
|
+
Object.defineProperty(exports, 'mockFetch', {
|
|
161
|
+
enumerable: true,
|
|
162
|
+
get: function () { return wonderBlocksTestingCore.mockFetch; }
|
|
163
|
+
});
|
|
164
|
+
Object.defineProperty(exports, 'renderHookStatic', {
|
|
165
|
+
enumerable: true,
|
|
166
|
+
get: function () { return wonderBlocksTestingCore.renderHookStatic; }
|
|
167
|
+
});
|
|
168
|
+
Object.defineProperty(exports, 'testHarness', {
|
|
169
|
+
enumerable: true,
|
|
170
|
+
get: function () { return wonderBlocksTestingCore.testHarness; }
|
|
171
|
+
});
|
|
172
|
+
exports.harnessAdapters = index;
|
|
506
173
|
exports.mockGqlFetch = mockGqlFetch;
|
|
507
|
-
exports.testHarness = testHarness;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanacademy/wonder-blocks-testing",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "11.0.0",
|
|
4
4
|
"design": "v1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -14,15 +14,17 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@babel/runtime": "^7.18.6",
|
|
17
|
-
"@khanacademy/wonder-blocks-core": "^6.4.
|
|
18
|
-
"@khanacademy/wonder-blocks-data": "^13.0.
|
|
17
|
+
"@khanacademy/wonder-blocks-core": "^6.4.2",
|
|
18
|
+
"@khanacademy/wonder-blocks-data": "^13.0.9",
|
|
19
|
+
"@khanacademy/wonder-blocks-testing-core": "^1.0.0"
|
|
19
20
|
},
|
|
20
21
|
"peerDependencies": {
|
|
21
22
|
"@khanacademy/wonder-stuff-core": "^1.2.2",
|
|
22
|
-
"@storybook/addon-actions": "^
|
|
23
|
-
"node-fetch": "^2.6.7",
|
|
23
|
+
"@storybook/addon-actions": "^7.0.0",
|
|
24
24
|
"aphrodite": "^1.2.5",
|
|
25
|
+
"node-fetch": "^2.6.7",
|
|
25
26
|
"react": "16.14.0",
|
|
27
|
+
"react-dom": "16.14.0",
|
|
26
28
|
"react-router-dom": "5.3.0"
|
|
27
29
|
},
|
|
28
30
|
"devDependencies": {
|
|
@@ -31,4 +33,4 @@
|
|
|
31
33
|
},
|
|
32
34
|
"author": "",
|
|
33
35
|
"license": "MIT"
|
|
34
|
-
}
|
|
36
|
+
}
|
|
@@ -2,7 +2,7 @@ import * as React from "react";
|
|
|
2
2
|
import {render, screen, waitFor} from "@testing-library/react";
|
|
3
3
|
|
|
4
4
|
import {GqlRouter, useGql} from "@khanacademy/wonder-blocks-data";
|
|
5
|
-
import {RespondWith} from "
|
|
5
|
+
import {RespondWith} from "@khanacademy/wonder-blocks-testing-core";
|
|
6
6
|
import {mockGqlFetch} from "../mock-gql-fetch";
|
|
7
7
|
|
|
8
8
|
describe("#mockGqlFetch", () => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {GqlOperation} from "@khanacademy/wonder-blocks-data";
|
|
2
|
+
import {RespondWith} from "@khanacademy/wonder-blocks-testing-core";
|
|
2
3
|
import type {GqlFetchMockFn} from "../types";
|
|
3
|
-
import {RespondWith} from "../../respond-with";
|
|
4
4
|
|
|
5
5
|
type SomeGqlData = {
|
|
6
6
|
a: string;
|
|
@@ -2,7 +2,7 @@ import * as React from "react";
|
|
|
2
2
|
import {render, screen, waitFor} from "@testing-library/react";
|
|
3
3
|
|
|
4
4
|
import {GqlRouter, useGql} from "@khanacademy/wonder-blocks-data";
|
|
5
|
-
import {RespondWith} from "
|
|
5
|
+
import {RespondWith} from "@khanacademy/wonder-blocks-testing-core";
|
|
6
6
|
import {mockGqlFetch} from "../mock-gql-fetch";
|
|
7
7
|
|
|
8
8
|
describe("integrating mockGqlFetch, RespondWith, GqlRouter and useGql", () => {
|
package/src/gql/types.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type {GqlOperation, GqlContext} from "@khanacademy/wonder-blocks-data";
|
|
2
|
-
import type {
|
|
3
|
-
|
|
2
|
+
import type {
|
|
3
|
+
GraphQLJson,
|
|
4
|
+
MockResponse,
|
|
5
|
+
} from "@khanacademy/wonder-blocks-testing-core";
|
|
4
6
|
|
|
5
7
|
export type GqlMockOperation<
|
|
6
8
|
TData extends Record<any, any>,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import {render, screen} from "@testing-library/react";
|
|
3
3
|
import * as WBCore from "@khanacademy/wonder-blocks-core";
|
|
4
|
-
import {makeTestHarness} from "
|
|
4
|
+
import {makeTestHarness} from "@khanacademy/wonder-blocks-testing-core";
|
|
5
5
|
|
|
6
6
|
import * as SSR from "../ssr";
|
|
7
7
|
|
|
@@ -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
|
|
|
5
5
|
type Interceptor = JSX.LibraryManagedAttributes<
|
|
6
6
|
typeof InterceptRequests,
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {harnessAdapters} from "@khanacademy/wonder-blocks-testing-core";
|
|
2
|
+
import type {TestHarnessConfigs} from "@khanacademy/wonder-blocks-testing-core";
|
|
2
3
|
import * as data from "./data";
|
|
3
|
-
import * as portal from "./portal";
|
|
4
|
-
import * as router from "./router";
|
|
5
4
|
import * as ssr from "./ssr";
|
|
6
5
|
|
|
7
|
-
import type {TestHarnessConfigs} from "../types";
|
|
8
|
-
|
|
9
6
|
/**
|
|
10
7
|
* NOTE: We do not type `DefaultAdapters` with `Adapters` here because we want
|
|
11
8
|
* the individual config types of each adapter to remain intact rather than
|
|
@@ -16,10 +13,14 @@ import type {TestHarnessConfigs} from "../types";
|
|
|
16
13
|
* The default adapters provided by Wonder Blocks.
|
|
17
14
|
*/
|
|
18
15
|
export const DefaultAdapters = {
|
|
19
|
-
|
|
16
|
+
// The error boundary is as close to the component under test as possible,
|
|
17
|
+
// so that other adapters don't soil it with their own errors, if that
|
|
18
|
+
// should happen.
|
|
19
|
+
boundary: harnessAdapters.DefaultAdapters.boundary,
|
|
20
|
+
css: harnessAdapters.DefaultAdapters.css,
|
|
20
21
|
data: data.adapter,
|
|
21
|
-
portal: portal
|
|
22
|
-
router: router
|
|
22
|
+
portal: harnessAdapters.DefaultAdapters.portal,
|
|
23
|
+
router: harnessAdapters.DefaultAdapters.router,
|
|
23
24
|
ssr: ssr.adapter,
|
|
24
25
|
} as const;
|
|
25
26
|
|
|
@@ -27,9 +28,7 @@ export const DefaultAdapters = {
|
|
|
27
28
|
* The default configurations to use with the `DefaultAdapters`.
|
|
28
29
|
*/
|
|
29
30
|
export const DefaultConfigs: TestHarnessConfigs<typeof DefaultAdapters> = {
|
|
30
|
-
|
|
31
|
+
...harnessAdapters.DefaultConfigs,
|
|
31
32
|
data: data.defaultConfig,
|
|
32
|
-
portal: portal.defaultConfig,
|
|
33
|
-
router: router.defaultConfig,
|
|
34
33
|
ssr: ssr.defaultConfig,
|
|
35
34
|
} as const;
|
|
@@ -2,7 +2,7 @@ import * as React from "react";
|
|
|
2
2
|
import {KindError, Errors} from "@khanacademy/wonder-stuff-core";
|
|
3
3
|
import {RenderStateRoot} from "@khanacademy/wonder-blocks-core";
|
|
4
4
|
|
|
5
|
-
import type {TestHarnessAdapter} from "
|
|
5
|
+
import type {TestHarnessAdapter} from "@khanacademy/wonder-blocks-testing-core";
|
|
6
6
|
|
|
7
7
|
//
|
|
8
8
|
type Config = true;
|