@khanacademy/wonder-blocks-testing-core 3.0.1 → 4.0.1
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 +12 -0
- package/dist/es/index.js +23 -448
- package/dist/index.d.ts +0 -2
- package/dist/index.js +22 -451
- package/package.json +4 -7
- package/dist/fixtures/fixtures.basic.stories.d.ts +0 -13
- package/dist/fixtures/fixtures.d.ts +0 -16
- package/dist/fixtures/fixtures.defaultwrapper.stories.d.ts +0 -9
- package/dist/fixtures/types.d.ts +0 -48
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-testing-core
|
|
2
2
|
|
|
3
|
+
## 4.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 4c03506: Upgrade wonder-blocks infrastructure to use Storybook v9
|
|
8
|
+
|
|
9
|
+
## 4.0.0
|
|
10
|
+
|
|
11
|
+
### Major Changes
|
|
12
|
+
|
|
13
|
+
- 82b5970: Removed Fixtures framework - please use the native Storybook CSFv3 format for stories
|
|
14
|
+
|
|
3
15
|
## 3.0.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/es/index.js
CHANGED
|
@@ -1,389 +1,34 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import { StaticRouter, MemoryRouter, Switch, Route } from 'react-router-dom';
|
|
4
4
|
import { CompatRouter, useLocation } from 'react-router-dom-v5-compat';
|
|
5
|
-
import _extends from '@babel/runtime/helpers/extends';
|
|
6
5
|
import * as ReactDOMServer from 'react-dom/server';
|
|
7
6
|
|
|
8
|
-
const
|
|
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
|
-
};
|
|
7
|
+
const getHref=input=>{if(typeof input==="string"){return input}else if(typeof input.url==="string"){return input.url}else if(typeof input.href==="string"){return input.href}else {throw new Error(`Unsupported input type`)}};const fetchRequestMatchesMock=(mock,input,init)=>{const href=getHref(input);if(typeof mock==="string"){return href===mock}else if(mock instanceof RegExp){return mock.test(href)}else {throw new Error(`Unsupported mock operation: ${JSON.stringify(mock)}`)}};
|
|
31
8
|
|
|
32
|
-
const
|
|
33
|
-
|
|
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
|
-
};
|
|
9
|
+
const mockRequester=(operationMatcher,operationToString)=>{const mocks=[];const configuration={hardFailOnUnmockedRequests:false};const getMatchingMock=(...args)=>{for(const mock of mocks){if(mock.onceOnly&&mock.used){continue}if(operationMatcher(mock.operation,...args)){mock.used=true;return mock}}return null};const mockFn=(...args)=>{const matchingMock=getMatchingMock(...args);if(matchingMock){return matchingMock.response()}const operation=operationToString(...args);const noMatchError=new Error(`No matching mock response found for request:
|
|
10
|
+
${operation}`);if(configuration.hardFailOnUnmockedRequests){throw noMatchError}return Promise.reject(noMatchError)};const addMockedOperation=(operation,response,onceOnly)=>{const mockResponse=()=>response.toPromise();mocks.push({operation,response:mockResponse,onceOnly,used:false});return mockFn};mockFn.mockOperation=(operation,response)=>addMockedOperation(operation,response,false);mockFn.mockOperationOnce=(operation,response)=>addMockedOperation(operation,response,true);mockFn.configure=config=>{Object.assign(configuration,config);return mockFn};return mockFn};
|
|
53
11
|
|
|
54
|
-
const mockRequester
|
|
55
|
-
|
|
56
|
-
const configuration = {
|
|
57
|
-
hardFailOnUnmockedRequests: false
|
|
58
|
-
};
|
|
59
|
-
const getMatchingMock = (...args) => {
|
|
60
|
-
for (const mock of mocks) {
|
|
61
|
-
if (mock.onceOnly && mock.used) {
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
if (operationMatcher(mock.operation, ...args)) {
|
|
65
|
-
mock.used = true;
|
|
66
|
-
return mock;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return null;
|
|
70
|
-
};
|
|
71
|
-
const mockFn = (...args) => {
|
|
72
|
-
const matchingMock = getMatchingMock(...args);
|
|
73
|
-
if (matchingMock) {
|
|
74
|
-
return matchingMock.response();
|
|
75
|
-
}
|
|
76
|
-
const operation = operationToString(...args);
|
|
77
|
-
const noMatchError = new Error(`No matching mock response found for request:
|
|
78
|
-
${operation}`);
|
|
79
|
-
if (configuration.hardFailOnUnmockedRequests) {
|
|
80
|
-
throw noMatchError;
|
|
81
|
-
}
|
|
82
|
-
return Promise.reject(noMatchError);
|
|
83
|
-
};
|
|
84
|
-
const addMockedOperation = (operation, response, onceOnly) => {
|
|
85
|
-
const mockResponse = () => response.toPromise();
|
|
86
|
-
mocks.push({
|
|
87
|
-
operation,
|
|
88
|
-
response: mockResponse,
|
|
89
|
-
onceOnly,
|
|
90
|
-
used: false
|
|
91
|
-
});
|
|
92
|
-
return mockFn;
|
|
93
|
-
};
|
|
94
|
-
mockFn.mockOperation = (operation, response) => addMockedOperation(operation, response, false);
|
|
95
|
-
mockFn.mockOperationOnce = (operation, response) => addMockedOperation(operation, response, true);
|
|
96
|
-
mockFn.configure = config => {
|
|
97
|
-
Object.assign(configuration, config);
|
|
98
|
-
return mockFn;
|
|
99
|
-
};
|
|
100
|
-
return mockFn;
|
|
101
|
-
};
|
|
12
|
+
const mockFetch=()=>mockRequester(fetchRequestMatchesMock,(input,init)=>`Input: ${typeof input==="string"?input:JSON.stringify(input,null,2)}
|
|
13
|
+
Options: ${init==null?"None":JSON.stringify(init,null,2)}`);
|
|
102
14
|
|
|
103
|
-
const
|
|
104
|
-
Options: ${init == null ? "None" : JSON.stringify(init, null, 2)}`);
|
|
15
|
+
const ResponseImpl=typeof Response==="undefined"?require("node-fetch").Response:Response;
|
|
105
16
|
|
|
106
|
-
const
|
|
17
|
+
const textResponse=(text,statusCode,signal)=>({toPromise:()=>makeMockResponse({type:"text",text,statusCode,signal})});const rejectResponse=(error,signal)=>({toPromise:()=>makeMockResponse({type:"reject",error,signal})});const RespondWith=Object.freeze({text:(text,statusCode=200,signal=null)=>textResponse(text,statusCode,signal),json:(json,signal=null)=>textResponse(()=>JSON.stringify(json),200,signal),graphQLData:(data,signal=null)=>textResponse(()=>JSON.stringify({data}),200,signal),unparseableBody:(signal=null)=>textResponse("INVALID JSON",200,signal),abortedRequest:(signal=null)=>rejectResponse(()=>{const abortError=new Error("Mock request aborted");abortError.name="AbortError";return abortError},signal),reject:(error,signal=null)=>rejectResponse(error,signal),errorStatusCode:(statusCode,signal=null)=>{if(statusCode<300){throw new Error(`${statusCode} is not a valid error status code`)}return textResponse("{}",statusCode,signal)},nonGraphQLBody:(signal=null)=>textResponse(()=>JSON.stringify({valid:"json",that:"is not a valid graphql response"}),200,signal),graphQLErrors:(errorMessages,signal=null)=>textResponse(()=>JSON.stringify({errors:errorMessages.map(e=>({message:e}))}),200,signal)});const callOnSettled=(signal,fn)=>{if(signal==null||signal.settled){fn();return}const onSettled=()=>{signal.removeEventListener("settled",onSettled);fn();};signal.addEventListener("settled",onSettled);};const makeMockResponse=response=>{const{signal}=response;switch(response.type){case"text":return new Promise((resolve,reject)=>{callOnSettled(signal,()=>{const text=typeof response.text==="function"?response.text():response.text;resolve(new ResponseImpl(text,{status:response.statusCode}));});});case"reject":return new Promise((resolve,reject)=>{callOnSettled(signal,()=>reject(response.error instanceof Error?response.error:response.error()));});default:if(process.env.NODE_ENV!=="production"){throw new Error(`Unknown response type: ${response.type}`)}return makeMockResponse({type:"reject",error:new Error("Unknown response type"),signal})}};
|
|
107
18
|
|
|
108
|
-
const
|
|
109
|
-
toPromise: () => makeMockResponse({
|
|
110
|
-
type: "text",
|
|
111
|
-
text,
|
|
112
|
-
statusCode,
|
|
113
|
-
signal
|
|
114
|
-
})
|
|
115
|
-
});
|
|
116
|
-
const rejectResponse = (error, signal) => ({
|
|
117
|
-
toPromise: () => makeMockResponse({
|
|
118
|
-
type: "reject",
|
|
119
|
-
error,
|
|
120
|
-
signal
|
|
121
|
-
})
|
|
122
|
-
});
|
|
123
|
-
const RespondWith = Object.freeze({
|
|
124
|
-
text: (text, statusCode = 200, signal = null) => textResponse(text, statusCode, signal),
|
|
125
|
-
json: (json, signal = null) => textResponse(() => JSON.stringify(json), 200, signal),
|
|
126
|
-
graphQLData: (data, signal = null) => textResponse(() => JSON.stringify({
|
|
127
|
-
data
|
|
128
|
-
}), 200, signal),
|
|
129
|
-
unparseableBody: (signal = null) => textResponse("INVALID JSON", 200, signal),
|
|
130
|
-
abortedRequest: (signal = null) => rejectResponse(() => {
|
|
131
|
-
const abortError = new Error("Mock request aborted");
|
|
132
|
-
abortError.name = "AbortError";
|
|
133
|
-
return abortError;
|
|
134
|
-
}, signal),
|
|
135
|
-
reject: (error, signal = null) => rejectResponse(error, signal),
|
|
136
|
-
errorStatusCode: (statusCode, signal = null) => {
|
|
137
|
-
if (statusCode < 300) {
|
|
138
|
-
throw new Error(`${statusCode} is not a valid error status code`);
|
|
139
|
-
}
|
|
140
|
-
return textResponse("{}", statusCode, signal);
|
|
141
|
-
},
|
|
142
|
-
nonGraphQLBody: (signal = null) => textResponse(() => JSON.stringify({
|
|
143
|
-
valid: "json",
|
|
144
|
-
that: "is not a valid graphql response"
|
|
145
|
-
}), 200, signal),
|
|
146
|
-
graphQLErrors: (errorMessages, signal = null) => textResponse(() => JSON.stringify({
|
|
147
|
-
errors: errorMessages.map(e => ({
|
|
148
|
-
message: e
|
|
149
|
-
}))
|
|
150
|
-
}), 200, signal)
|
|
151
|
-
});
|
|
152
|
-
const callOnSettled = (signal, fn) => {
|
|
153
|
-
if (signal == null || signal.settled) {
|
|
154
|
-
fn();
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
const onSettled = () => {
|
|
158
|
-
signal.removeEventListener("settled", onSettled);
|
|
159
|
-
fn();
|
|
160
|
-
};
|
|
161
|
-
signal.addEventListener("settled", onSettled);
|
|
162
|
-
};
|
|
163
|
-
const makeMockResponse = response => {
|
|
164
|
-
const {
|
|
165
|
-
signal
|
|
166
|
-
} = response;
|
|
167
|
-
switch (response.type) {
|
|
168
|
-
case "text":
|
|
169
|
-
return new Promise((resolve, reject) => {
|
|
170
|
-
callOnSettled(signal, () => {
|
|
171
|
-
const text = typeof response.text === "function" ? response.text() : response.text;
|
|
172
|
-
resolve(new ResponseImpl(text, {
|
|
173
|
-
status: response.statusCode
|
|
174
|
-
}));
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
case "reject":
|
|
178
|
-
return new Promise((resolve, reject) => {
|
|
179
|
-
callOnSettled(signal, () => reject(response.error instanceof Error ? response.error : response.error()));
|
|
180
|
-
});
|
|
181
|
-
default:
|
|
182
|
-
if (process.env.NODE_ENV !== "production") {
|
|
183
|
-
throw new Error(`Unknown response type: ${response.type}`);
|
|
184
|
-
}
|
|
185
|
-
return makeMockResponse({
|
|
186
|
-
type: "reject",
|
|
187
|
-
error: new Error("Unknown response type"),
|
|
188
|
-
signal
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
class SettleSignal extends EventTarget {
|
|
194
|
-
constructor(setSettleFn = null) {
|
|
195
|
-
super();
|
|
196
|
-
this._settled = false;
|
|
197
|
-
setSettleFn == null || setSettleFn(() => {
|
|
198
|
-
if (this._settled) {
|
|
199
|
-
throw new Error("SettleSignal already settled");
|
|
200
|
-
}
|
|
201
|
-
this._settled = true;
|
|
202
|
-
this.dispatchEvent(new Event("settled"));
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
static settle() {
|
|
206
|
-
const signal = new SettleSignal();
|
|
207
|
-
signal._settled = true;
|
|
208
|
-
return signal;
|
|
209
|
-
}
|
|
210
|
-
get settled() {
|
|
211
|
-
return this._settled;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
19
|
+
class SettleSignal extends EventTarget{static settle(){const signal=new SettleSignal;signal._settled=true;return signal}get settled(){return this._settled}constructor(setSettleFn=null){super(),this._settled=false;setSettleFn?.(()=>{if(this._settled){throw new Error("SettleSignal already settled")}this._settled=true;this.dispatchEvent(new Event("settled"));});}}
|
|
214
20
|
|
|
215
|
-
class SettleController {
|
|
216
|
-
constructor() {
|
|
217
|
-
this._settleFn = void 0;
|
|
218
|
-
this._signal = void 0;
|
|
219
|
-
this._signal = new SettleSignal(settleFn => this._settleFn = settleFn);
|
|
220
|
-
}
|
|
221
|
-
get signal() {
|
|
222
|
-
return this._signal;
|
|
223
|
-
}
|
|
224
|
-
settle() {
|
|
225
|
-
var _this$_settleFn;
|
|
226
|
-
(_this$_settleFn = this._settleFn) == null || _this$_settleFn.call(this);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
21
|
+
class SettleController{get signal(){return this._signal}settle(){this._settleFn?.();}constructor(){this._signal=new SettleSignal(settleFn=>this._settleFn=settleFn);}}
|
|
229
22
|
|
|
230
|
-
const defaultConfig$3 = null;
|
|
231
|
-
const normalizeConfig = config => {
|
|
232
|
-
if (typeof config === "string") {
|
|
233
|
-
return {
|
|
234
|
-
classes: [config],
|
|
235
|
-
style: {}
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
if (Array.isArray(config)) {
|
|
239
|
-
return {
|
|
240
|
-
classes: config,
|
|
241
|
-
style: {}
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
if (typeof config === "object") {
|
|
245
|
-
if ("classes" in config && config.classes != null && "style" in config && config.style != null) {
|
|
246
|
-
return config;
|
|
247
|
-
}
|
|
248
|
-
return {
|
|
249
|
-
classes: [],
|
|
250
|
-
style: config
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
throw new Error(`Invalid config: ${config}`);
|
|
254
|
-
};
|
|
255
|
-
const adapter$3 = (children, config) => {
|
|
256
|
-
const {
|
|
257
|
-
classes,
|
|
258
|
-
style
|
|
259
|
-
} = normalizeConfig(config);
|
|
260
|
-
return React.createElement("div", {
|
|
261
|
-
"data-testid": "css-adapter-container",
|
|
262
|
-
className: classes.join(" "),
|
|
263
|
-
style: style
|
|
264
|
-
}, children);
|
|
265
|
-
};
|
|
23
|
+
const defaultConfig$3=null;const normalizeConfig=config=>{if(typeof config==="string"){return {classes:[config],style:{}}}if(Array.isArray(config)){return {classes:config,style:{}}}if(typeof config==="object"){if("classes"in config&&config.classes!=null&&"style"in config&&config.style!=null){return config}return {classes:[],style:config}}throw new Error(`Invalid config: ${config}`)};const adapter$3=(children,config)=>{const{classes,style}=normalizeConfig(config);return jsx("div",{"data-testid":"css-adapter-container",className:classes.join(" "),style:style,children:children})};
|
|
266
24
|
|
|
267
|
-
const defaultConfig$2 =
|
|
268
|
-
class ErrorBoundary extends React.Component {
|
|
269
|
-
constructor(...args) {
|
|
270
|
-
super(...args);
|
|
271
|
-
this.state = {
|
|
272
|
-
renderError: false
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
static getDerivedStateFromError(error) {
|
|
276
|
-
return {
|
|
277
|
-
renderError: true
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
componentDidCatch(error, errorInfo) {
|
|
281
|
-
const lastErrorUx = this.props.onError(error, errorInfo);
|
|
282
|
-
this.setState({
|
|
283
|
-
lastErrorUx
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
render() {
|
|
287
|
-
var _this$state$lastError;
|
|
288
|
-
return this.state.renderError ? (_this$state$lastError = this.state.lastErrorUx) != null ? _this$state$lastError : "An error occurred" : this.props.children;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
const adapter$2 = (children, config) => React.createElement(ErrorBoundary, {
|
|
292
|
-
onError: config
|
|
293
|
-
}, children);
|
|
25
|
+
const defaultConfig$2=null;class ErrorBoundary extends React.Component{static getDerivedStateFromError(error){return {renderError:true}}componentDidCatch(error,errorInfo){const lastErrorUx=this.props.onError(error,errorInfo);this.setState({lastErrorUx});}render(){return this.state.renderError?this.state.lastErrorUx??"An error occurred":this.props.children}constructor(...args){super(...args),this.state={renderError:false};}}const adapter$2=(children,config)=>jsx(ErrorBoundary,{onError:config,children:children});
|
|
294
26
|
|
|
295
|
-
const defaultConfig$1
|
|
296
|
-
const adapter$1 = (children, config) => React.createElement(React.Fragment, null, React.createElement("div", {
|
|
297
|
-
id: config,
|
|
298
|
-
"data-testid": config
|
|
299
|
-
}), children);
|
|
27
|
+
const defaultConfig$1=null;const adapter$1=(children,config)=>jsxs(Fragment,{children:[jsx("div",{id:config,"data-testid":config}),children]});
|
|
300
28
|
|
|
301
|
-
const defaultConfig = {
|
|
302
|
-
location: "/"
|
|
303
|
-
};
|
|
304
|
-
const MaybeWithRoute = ({
|
|
305
|
-
children,
|
|
306
|
-
path,
|
|
307
|
-
configLocation
|
|
308
|
-
}) => {
|
|
309
|
-
if (path == null) {
|
|
310
|
-
return React.createElement(React.Fragment, null, children);
|
|
311
|
-
}
|
|
312
|
-
const ErrorElement = () => {
|
|
313
|
-
const actualLocation = useLocation();
|
|
314
|
-
const configuredLocation = typeof configLocation === "string" ? configLocation : configLocation.pathname;
|
|
315
|
-
const errorMessage = `The current location '${actualLocation.pathname}' ` + `does not match the configured path '${path}'. ` + `Did you provide the correct configured ` + `location, '${configuredLocation}', or did the ` + `routing lead to a different place than you ` + `expected?`;
|
|
316
|
-
throw new Error(errorMessage);
|
|
317
|
-
};
|
|
318
|
-
return React.createElement(Switch, null, React.createElement(Route, {
|
|
319
|
-
path: path,
|
|
320
|
-
render: () => React.createElement(React.Fragment, null, children)
|
|
321
|
-
}), React.createElement(Route, {
|
|
322
|
-
path: "*",
|
|
323
|
-
component: ErrorElement
|
|
324
|
-
}));
|
|
325
|
-
};
|
|
326
|
-
const adapter = (children, config) => {
|
|
327
|
-
var _config$initialIndex;
|
|
328
|
-
if (typeof config === "string") {
|
|
329
|
-
config = {
|
|
330
|
-
location: config
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
if ("forceStatic" in config && config.forceStatic) {
|
|
334
|
-
if (config.disableCompatRouter) {
|
|
335
|
-
return React.createElement(StaticRouter, {
|
|
336
|
-
location: config.location,
|
|
337
|
-
context: {}
|
|
338
|
-
}, React.createElement(MaybeWithRoute, {
|
|
339
|
-
path: config.path,
|
|
340
|
-
configLocation: config.location
|
|
341
|
-
}, children));
|
|
342
|
-
}
|
|
343
|
-
return React.createElement(StaticRouter, {
|
|
344
|
-
location: config.location,
|
|
345
|
-
context: {}
|
|
346
|
-
}, React.createElement(CompatRouter, null, React.createElement(MaybeWithRoute, {
|
|
347
|
-
path: config.path,
|
|
348
|
-
configLocation: config.location
|
|
349
|
-
}, children)));
|
|
350
|
-
}
|
|
351
|
-
if ("location" in config && config.location !== undefined) {
|
|
352
|
-
return React.createElement(MemoryRouter, {
|
|
353
|
-
initialEntries: [config.location]
|
|
354
|
-
}, React.createElement(CompatRouter, null, React.createElement(MaybeWithRoute, {
|
|
355
|
-
path: config.path,
|
|
356
|
-
configLocation: config.location
|
|
357
|
-
}, children)));
|
|
358
|
-
}
|
|
359
|
-
if (!("initialEntries" in config) || config.initialEntries === undefined) {
|
|
360
|
-
throw new Error("A location or initial history entries must be provided.");
|
|
361
|
-
}
|
|
362
|
-
const entries = config.initialEntries.length === 0 ? [defaultConfig.location] : config.initialEntries;
|
|
363
|
-
const routerProps = {
|
|
364
|
-
initialEntries: entries
|
|
365
|
-
};
|
|
366
|
-
if (config.initialIndex != null) {
|
|
367
|
-
routerProps.initialIndex = config.initialIndex;
|
|
368
|
-
}
|
|
369
|
-
return React.createElement(MemoryRouter, routerProps, React.createElement(CompatRouter, null, React.createElement(MaybeWithRoute, {
|
|
370
|
-
path: config.path,
|
|
371
|
-
configLocation: entries[(_config$initialIndex = config.initialIndex) != null ? _config$initialIndex : 0]
|
|
372
|
-
}, children)));
|
|
373
|
-
};
|
|
29
|
+
const defaultConfig={location:"/"};const MaybeWithRoute=({children,path,configLocation})=>{if(path==null){return jsx(Fragment,{children:children})}const ErrorElement=()=>{const actualLocation=useLocation();const configuredLocation=typeof configLocation==="string"?configLocation:configLocation.pathname;const errorMessage=`The current location '${actualLocation.pathname}' `+`does not match the configured path '${path}'. `+`Did you provide the correct configured `+`location, '${configuredLocation}', or did the `+`routing lead to a different place than you `+`expected?`;throw new Error(errorMessage)};return jsxs(Switch,{children:[jsx(Route,{path:path,render:()=>jsx(Fragment,{children:children})}),jsx(Route,{path:"*",component:ErrorElement})]})};const adapter=(children,config)=>{if(typeof config==="string"){config={location:config};}if("forceStatic"in config&&config.forceStatic){if(config.disableCompatRouter){return jsx(StaticRouter,{location:config.location,context:{},children:jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})}return jsx(StaticRouter,{location:config.location,context:{},children:jsx(CompatRouter,{children:jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})})}if("location"in config&&config.location!==undefined){return jsx(MemoryRouter,{initialEntries:[config.location],children:jsx(CompatRouter,{children:jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})})}if(!("initialEntries"in config)||config.initialEntries===undefined){throw new Error("A location or initial history entries must be provided.")}const entries=config.initialEntries.length===0?[defaultConfig.location]:config.initialEntries;const routerProps={initialEntries:entries};if(config.initialIndex!=null){routerProps.initialIndex=config.initialIndex;}return jsx(MemoryRouter,{...routerProps,children:jsx(CompatRouter,{children:jsx(MaybeWithRoute,{path:config.path,configLocation:entries[config.initialIndex??0],children:children})})})};
|
|
374
30
|
|
|
375
|
-
const DefaultAdapters =
|
|
376
|
-
boundary: adapter$2,
|
|
377
|
-
css: adapter$3,
|
|
378
|
-
portal: adapter$1,
|
|
379
|
-
router: adapter
|
|
380
|
-
};
|
|
381
|
-
const DefaultConfigs = {
|
|
382
|
-
boundary: defaultConfig$2,
|
|
383
|
-
css: defaultConfig$3,
|
|
384
|
-
portal: defaultConfig$1,
|
|
385
|
-
router: defaultConfig
|
|
386
|
-
};
|
|
31
|
+
const DefaultAdapters={boundary:adapter$2,css:adapter$3,portal:adapter$1,router:adapter};const DefaultConfigs={boundary:defaultConfig$2,css:defaultConfig$3,portal:defaultConfig$1,router:defaultConfig};
|
|
387
32
|
|
|
388
33
|
var adapters = /*#__PURE__*/Object.freeze({
|
|
389
34
|
__proto__: null,
|
|
@@ -391,88 +36,18 @@ var adapters = /*#__PURE__*/Object.freeze({
|
|
|
391
36
|
DefaultConfigs: DefaultConfigs
|
|
392
37
|
});
|
|
393
38
|
|
|
394
|
-
const componentCache
|
|
395
|
-
const getNamedAdapterComponent = name => {
|
|
396
|
-
const existing = componentCache.get(name);
|
|
397
|
-
if (existing != null) {
|
|
398
|
-
return existing;
|
|
399
|
-
}
|
|
400
|
-
const newComponent = ({
|
|
401
|
-
children,
|
|
402
|
-
config,
|
|
403
|
-
adapter
|
|
404
|
-
}) => adapter(children, config);
|
|
405
|
-
newComponent.displayName = `Adapter(${name})`;
|
|
406
|
-
componentCache.set(name, newComponent);
|
|
407
|
-
return newComponent;
|
|
408
|
-
};
|
|
39
|
+
const componentCache=new Map;const getNamedAdapterComponent=name=>{const existing=componentCache.get(name);if(existing!=null){return existing}const newComponent=({children,config,adapter})=>adapter(children,config);newComponent.displayName=`Adapter(${name})`;componentCache.set(name,newComponent);return newComponent};
|
|
409
40
|
|
|
410
|
-
const Adapt = ({
|
|
411
|
-
children,
|
|
412
|
-
adapters,
|
|
413
|
-
configs
|
|
414
|
-
}) => {
|
|
415
|
-
return Object.entries(adapters).reduce((newChildren, [name, adapter]) => {
|
|
416
|
-
const theConfig = configs[name];
|
|
417
|
-
if (theConfig == null) {
|
|
418
|
-
return newChildren;
|
|
419
|
-
}
|
|
420
|
-
const Adapter = getNamedAdapterComponent(name);
|
|
421
|
-
return React.createElement(Adapter, {
|
|
422
|
-
key: name,
|
|
423
|
-
adapter: adapter,
|
|
424
|
-
config: theConfig
|
|
425
|
-
}, newChildren);
|
|
426
|
-
}, React.createElement(React.Fragment, null, children));
|
|
427
|
-
};
|
|
41
|
+
const Adapt=({children,adapters,configs})=>{return Object.entries(adapters).reduce((newChildren,[name,adapter])=>{const theConfig=configs[name];if(theConfig==null){return newChildren}const Adapter=getNamedAdapterComponent(name);return jsx(Adapter,{adapter:adapter,config:theConfig,children:newChildren},name)},jsx(Fragment,{children:children}))};
|
|
428
42
|
|
|
429
|
-
const makeTestHarness
|
|
430
|
-
return (Component, configs) => {
|
|
431
|
-
const fullConfig = _extends({}, defaultConfigs, configs);
|
|
432
|
-
const harnessedComponent = React.forwardRef((props, ref) => React.createElement(Adapt, {
|
|
433
|
-
adapters: adapters,
|
|
434
|
-
configs: fullConfig
|
|
435
|
-
}, React.createElement(Component, _extends({}, props, {
|
|
436
|
-
ref: ref
|
|
437
|
-
}))));
|
|
438
|
-
harnessedComponent.displayName = `testHarness(${Component.displayName || Component.name || "Component"})`;
|
|
439
|
-
return harnessedComponent;
|
|
440
|
-
};
|
|
441
|
-
};
|
|
43
|
+
const makeTestHarness=(adapters,defaultConfigs)=>{return (Component,configs)=>{const fullConfig={...defaultConfigs,...configs};const harnessedComponent=React.forwardRef((props,ref)=>jsx(Adapt,{adapters:adapters,configs:fullConfig,children:jsx(Component,{...props,ref:ref})}));harnessedComponent.displayName=`testHarness(${Component.displayName||Component.name||"Component"})`;return harnessedComponent}};
|
|
442
44
|
|
|
443
|
-
const HookHarness = (
|
|
444
|
-
children
|
|
445
|
-
}) => React.createElement(React.Fragment, null, children);
|
|
446
|
-
const makeHookHarness = (adapters, defaultConfigs) => {
|
|
447
|
-
const testHarness = makeTestHarness(adapters, defaultConfigs);
|
|
448
|
-
return configs => testHarness(HookHarness, configs);
|
|
449
|
-
};
|
|
45
|
+
const HookHarness=({children})=>jsx(Fragment,{children:children});const makeHookHarness=(adapters,defaultConfigs)=>{const testHarness=makeTestHarness(adapters,defaultConfigs);return configs=>testHarness(HookHarness,configs)};
|
|
450
46
|
|
|
451
|
-
const hookHarness
|
|
47
|
+
const hookHarness=makeHookHarness(DefaultAdapters,DefaultConfigs);
|
|
452
48
|
|
|
453
|
-
const testHarness
|
|
49
|
+
const testHarness=makeTestHarness(DefaultAdapters,DefaultConfigs);
|
|
454
50
|
|
|
455
|
-
const renderHookStatic = (
|
|
456
|
-
wrapper,
|
|
457
|
-
initialProps
|
|
458
|
-
} = {}) => {
|
|
459
|
-
let result;
|
|
460
|
-
function TestComponent({
|
|
461
|
-
renderCallbackProps
|
|
462
|
-
}) {
|
|
463
|
-
result = render(renderCallbackProps);
|
|
464
|
-
return null;
|
|
465
|
-
}
|
|
466
|
-
const component = React.createElement(TestComponent, {
|
|
467
|
-
renderCallbackProps: initialProps
|
|
468
|
-
});
|
|
469
|
-
const componentWithWrapper = wrapper == null ? component : React.createElement(wrapper, null, component);
|
|
470
|
-
ReactDOMServer.renderToString(componentWithWrapper);
|
|
471
|
-
return {
|
|
472
|
-
result: {
|
|
473
|
-
current: result
|
|
474
|
-
}
|
|
475
|
-
};
|
|
476
|
-
};
|
|
51
|
+
const renderHookStatic=(render,{wrapper,initialProps}={})=>{let result;function TestComponent({renderCallbackProps}){result=render(renderCallbackProps);return null}const component=jsx(TestComponent,{renderCallbackProps:initialProps});const componentWithWrapper=wrapper==null?component:React.createElement(wrapper,null,component);ReactDOMServer.renderToString(componentWithWrapper);return {result:{current:result}}};
|
|
477
52
|
|
|
478
|
-
export { RespondWith, SettleController,
|
|
53
|
+
export { RespondWith, SettleController, adapters as harnessAdapters, hookHarness, makeHookHarness, makeTestHarness, mockFetch, mockRequester, renderHookStatic, testHarness };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export { fixtures } from "./fixtures/fixtures";
|
|
2
|
-
export type { FixtureFn, FixtureProps, GetPropsOptions } from "./fixtures/types";
|
|
3
1
|
export { mockFetch } from "./fetch/mock-fetch";
|
|
4
2
|
export { mockRequester } from "./mock-requester";
|
|
5
3
|
export { RespondWith } from "./respond-with";
|
package/dist/index.js
CHANGED
|
@@ -3,14 +3,11 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var React = require('react');
|
|
6
|
-
var
|
|
6
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
7
7
|
var reactRouterDom = require('react-router-dom');
|
|
8
8
|
var reactRouterDomV5Compat = require('react-router-dom-v5-compat');
|
|
9
|
-
var _extends = require('@babel/runtime/helpers/extends');
|
|
10
9
|
var ReactDOMServer = require('react-dom/server');
|
|
11
10
|
|
|
12
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
13
|
-
|
|
14
11
|
function _interopNamespace(e) {
|
|
15
12
|
if (e && e.__esModule) return e;
|
|
16
13
|
var n = Object.create(null);
|
|
@@ -30,388 +27,33 @@ function _interopNamespace(e) {
|
|
|
30
27
|
}
|
|
31
28
|
|
|
32
29
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
33
|
-
var _extends__default = /*#__PURE__*/_interopDefaultLegacy(_extends);
|
|
34
30
|
var ReactDOMServer__namespace = /*#__PURE__*/_interopNamespace(ReactDOMServer);
|
|
35
31
|
|
|
36
|
-
const
|
|
37
|
-
const templateMap = new WeakMap();
|
|
38
|
-
let storyNumber = 1;
|
|
39
|
-
const getPropsOptions = {
|
|
40
|
-
log: (message, ...args) => addonActions.action(message)(...args),
|
|
41
|
-
logHandler: addonActions.action
|
|
42
|
-
};
|
|
43
|
-
const makeStory = (description, props, wrapper = null) => {
|
|
44
|
-
const storyName = `${storyNumber++} ${description}`;
|
|
45
|
-
const getProps = options => typeof props === "function" ? props(options) : props;
|
|
46
|
-
const RealComponent = wrapper || Component;
|
|
47
|
-
let Template = templateMap.get(RealComponent);
|
|
48
|
-
if (Template == null) {
|
|
49
|
-
Template = args => React__namespace.createElement(RealComponent, args);
|
|
50
|
-
templateMap.set(RealComponent, Template);
|
|
51
|
-
}
|
|
52
|
-
const story = Template.bind({});
|
|
53
|
-
story.args = getProps(getPropsOptions);
|
|
54
|
-
story.storyName = storyName;
|
|
55
|
-
return story;
|
|
56
|
-
};
|
|
57
|
-
return makeStory;
|
|
58
|
-
};
|
|
32
|
+
const getHref=input=>{if(typeof input==="string"){return input}else if(typeof input.url==="string"){return input.url}else if(typeof input.href==="string"){return input.href}else {throw new Error(`Unsupported input type`)}};const fetchRequestMatchesMock=(mock,input,init)=>{const href=getHref(input);if(typeof mock==="string"){return href===mock}else if(mock instanceof RegExp){return mock.test(href)}else {throw new Error(`Unsupported mock operation: ${JSON.stringify(mock)}`)}};
|
|
59
33
|
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
return input;
|
|
63
|
-
} else if (typeof input.url === "string") {
|
|
64
|
-
return input.url;
|
|
65
|
-
} else if (typeof input.href === "string") {
|
|
66
|
-
return input.href;
|
|
67
|
-
} else {
|
|
68
|
-
throw new Error(`Unsupported input type`);
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
const fetchRequestMatchesMock = (mock, input, init) => {
|
|
72
|
-
const href = getHref(input);
|
|
73
|
-
if (typeof mock === "string") {
|
|
74
|
-
return href === mock;
|
|
75
|
-
} else if (mock instanceof RegExp) {
|
|
76
|
-
return mock.test(href);
|
|
77
|
-
} else {
|
|
78
|
-
throw new Error(`Unsupported mock operation: ${JSON.stringify(mock)}`);
|
|
79
|
-
}
|
|
80
|
-
};
|
|
34
|
+
const mockRequester=(operationMatcher,operationToString)=>{const mocks=[];const configuration={hardFailOnUnmockedRequests:false};const getMatchingMock=(...args)=>{for(const mock of mocks){if(mock.onceOnly&&mock.used){continue}if(operationMatcher(mock.operation,...args)){mock.used=true;return mock}}return null};const mockFn=(...args)=>{const matchingMock=getMatchingMock(...args);if(matchingMock){return matchingMock.response()}const operation=operationToString(...args);const noMatchError=new Error(`No matching mock response found for request:
|
|
35
|
+
${operation}`);if(configuration.hardFailOnUnmockedRequests){throw noMatchError}return Promise.reject(noMatchError)};const addMockedOperation=(operation,response,onceOnly)=>{const mockResponse=()=>response.toPromise();mocks.push({operation,response:mockResponse,onceOnly,used:false});return mockFn};mockFn.mockOperation=(operation,response)=>addMockedOperation(operation,response,false);mockFn.mockOperationOnce=(operation,response)=>addMockedOperation(operation,response,true);mockFn.configure=config=>{Object.assign(configuration,config);return mockFn};return mockFn};
|
|
81
36
|
|
|
82
|
-
const mockRequester
|
|
83
|
-
|
|
84
|
-
const configuration = {
|
|
85
|
-
hardFailOnUnmockedRequests: false
|
|
86
|
-
};
|
|
87
|
-
const getMatchingMock = (...args) => {
|
|
88
|
-
for (const mock of mocks) {
|
|
89
|
-
if (mock.onceOnly && mock.used) {
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
if (operationMatcher(mock.operation, ...args)) {
|
|
93
|
-
mock.used = true;
|
|
94
|
-
return mock;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return null;
|
|
98
|
-
};
|
|
99
|
-
const mockFn = (...args) => {
|
|
100
|
-
const matchingMock = getMatchingMock(...args);
|
|
101
|
-
if (matchingMock) {
|
|
102
|
-
return matchingMock.response();
|
|
103
|
-
}
|
|
104
|
-
const operation = operationToString(...args);
|
|
105
|
-
const noMatchError = new Error(`No matching mock response found for request:
|
|
106
|
-
${operation}`);
|
|
107
|
-
if (configuration.hardFailOnUnmockedRequests) {
|
|
108
|
-
throw noMatchError;
|
|
109
|
-
}
|
|
110
|
-
return Promise.reject(noMatchError);
|
|
111
|
-
};
|
|
112
|
-
const addMockedOperation = (operation, response, onceOnly) => {
|
|
113
|
-
const mockResponse = () => response.toPromise();
|
|
114
|
-
mocks.push({
|
|
115
|
-
operation,
|
|
116
|
-
response: mockResponse,
|
|
117
|
-
onceOnly,
|
|
118
|
-
used: false
|
|
119
|
-
});
|
|
120
|
-
return mockFn;
|
|
121
|
-
};
|
|
122
|
-
mockFn.mockOperation = (operation, response) => addMockedOperation(operation, response, false);
|
|
123
|
-
mockFn.mockOperationOnce = (operation, response) => addMockedOperation(operation, response, true);
|
|
124
|
-
mockFn.configure = config => {
|
|
125
|
-
Object.assign(configuration, config);
|
|
126
|
-
return mockFn;
|
|
127
|
-
};
|
|
128
|
-
return mockFn;
|
|
129
|
-
};
|
|
37
|
+
const mockFetch=()=>mockRequester(fetchRequestMatchesMock,(input,init)=>`Input: ${typeof input==="string"?input:JSON.stringify(input,null,2)}
|
|
38
|
+
Options: ${init==null?"None":JSON.stringify(init,null,2)}`);
|
|
130
39
|
|
|
131
|
-
const
|
|
132
|
-
Options: ${init == null ? "None" : JSON.stringify(init, null, 2)}`);
|
|
40
|
+
const ResponseImpl=typeof Response==="undefined"?require("node-fetch").Response:Response;
|
|
133
41
|
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
const textResponse = (text, statusCode, signal) => ({
|
|
137
|
-
toPromise: () => makeMockResponse({
|
|
138
|
-
type: "text",
|
|
139
|
-
text,
|
|
140
|
-
statusCode,
|
|
141
|
-
signal
|
|
142
|
-
})
|
|
143
|
-
});
|
|
144
|
-
const rejectResponse = (error, signal) => ({
|
|
145
|
-
toPromise: () => makeMockResponse({
|
|
146
|
-
type: "reject",
|
|
147
|
-
error,
|
|
148
|
-
signal
|
|
149
|
-
})
|
|
150
|
-
});
|
|
151
|
-
const RespondWith = Object.freeze({
|
|
152
|
-
text: (text, statusCode = 200, signal = null) => textResponse(text, statusCode, signal),
|
|
153
|
-
json: (json, signal = null) => textResponse(() => JSON.stringify(json), 200, signal),
|
|
154
|
-
graphQLData: (data, signal = null) => textResponse(() => JSON.stringify({
|
|
155
|
-
data
|
|
156
|
-
}), 200, signal),
|
|
157
|
-
unparseableBody: (signal = null) => textResponse("INVALID JSON", 200, signal),
|
|
158
|
-
abortedRequest: (signal = null) => rejectResponse(() => {
|
|
159
|
-
const abortError = new Error("Mock request aborted");
|
|
160
|
-
abortError.name = "AbortError";
|
|
161
|
-
return abortError;
|
|
162
|
-
}, signal),
|
|
163
|
-
reject: (error, signal = null) => rejectResponse(error, signal),
|
|
164
|
-
errorStatusCode: (statusCode, signal = null) => {
|
|
165
|
-
if (statusCode < 300) {
|
|
166
|
-
throw new Error(`${statusCode} is not a valid error status code`);
|
|
167
|
-
}
|
|
168
|
-
return textResponse("{}", statusCode, signal);
|
|
169
|
-
},
|
|
170
|
-
nonGraphQLBody: (signal = null) => textResponse(() => JSON.stringify({
|
|
171
|
-
valid: "json",
|
|
172
|
-
that: "is not a valid graphql response"
|
|
173
|
-
}), 200, signal),
|
|
174
|
-
graphQLErrors: (errorMessages, signal = null) => textResponse(() => JSON.stringify({
|
|
175
|
-
errors: errorMessages.map(e => ({
|
|
176
|
-
message: e
|
|
177
|
-
}))
|
|
178
|
-
}), 200, signal)
|
|
179
|
-
});
|
|
180
|
-
const callOnSettled = (signal, fn) => {
|
|
181
|
-
if (signal == null || signal.settled) {
|
|
182
|
-
fn();
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
const onSettled = () => {
|
|
186
|
-
signal.removeEventListener("settled", onSettled);
|
|
187
|
-
fn();
|
|
188
|
-
};
|
|
189
|
-
signal.addEventListener("settled", onSettled);
|
|
190
|
-
};
|
|
191
|
-
const makeMockResponse = response => {
|
|
192
|
-
const {
|
|
193
|
-
signal
|
|
194
|
-
} = response;
|
|
195
|
-
switch (response.type) {
|
|
196
|
-
case "text":
|
|
197
|
-
return new Promise((resolve, reject) => {
|
|
198
|
-
callOnSettled(signal, () => {
|
|
199
|
-
const text = typeof response.text === "function" ? response.text() : response.text;
|
|
200
|
-
resolve(new ResponseImpl(text, {
|
|
201
|
-
status: response.statusCode
|
|
202
|
-
}));
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
case "reject":
|
|
206
|
-
return new Promise((resolve, reject) => {
|
|
207
|
-
callOnSettled(signal, () => reject(response.error instanceof Error ? response.error : response.error()));
|
|
208
|
-
});
|
|
209
|
-
default:
|
|
210
|
-
if (process.env.NODE_ENV !== "production") {
|
|
211
|
-
throw new Error(`Unknown response type: ${response.type}`);
|
|
212
|
-
}
|
|
213
|
-
return makeMockResponse({
|
|
214
|
-
type: "reject",
|
|
215
|
-
error: new Error("Unknown response type"),
|
|
216
|
-
signal
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
};
|
|
42
|
+
const textResponse=(text,statusCode,signal)=>({toPromise:()=>makeMockResponse({type:"text",text,statusCode,signal})});const rejectResponse=(error,signal)=>({toPromise:()=>makeMockResponse({type:"reject",error,signal})});const RespondWith=Object.freeze({text:(text,statusCode=200,signal=null)=>textResponse(text,statusCode,signal),json:(json,signal=null)=>textResponse(()=>JSON.stringify(json),200,signal),graphQLData:(data,signal=null)=>textResponse(()=>JSON.stringify({data}),200,signal),unparseableBody:(signal=null)=>textResponse("INVALID JSON",200,signal),abortedRequest:(signal=null)=>rejectResponse(()=>{const abortError=new Error("Mock request aborted");abortError.name="AbortError";return abortError},signal),reject:(error,signal=null)=>rejectResponse(error,signal),errorStatusCode:(statusCode,signal=null)=>{if(statusCode<300){throw new Error(`${statusCode} is not a valid error status code`)}return textResponse("{}",statusCode,signal)},nonGraphQLBody:(signal=null)=>textResponse(()=>JSON.stringify({valid:"json",that:"is not a valid graphql response"}),200,signal),graphQLErrors:(errorMessages,signal=null)=>textResponse(()=>JSON.stringify({errors:errorMessages.map(e=>({message:e}))}),200,signal)});const callOnSettled=(signal,fn)=>{if(signal==null||signal.settled){fn();return}const onSettled=()=>{signal.removeEventListener("settled",onSettled);fn();};signal.addEventListener("settled",onSettled);};const makeMockResponse=response=>{const{signal}=response;switch(response.type){case"text":return new Promise((resolve,reject)=>{callOnSettled(signal,()=>{const text=typeof response.text==="function"?response.text():response.text;resolve(new ResponseImpl(text,{status:response.statusCode}));});});case"reject":return new Promise((resolve,reject)=>{callOnSettled(signal,()=>reject(response.error instanceof Error?response.error:response.error()));});default:if(process.env.NODE_ENV!=="production"){throw new Error(`Unknown response type: ${response.type}`)}return makeMockResponse({type:"reject",error:new Error("Unknown response type"),signal})}};
|
|
220
43
|
|
|
221
|
-
class SettleSignal extends EventTarget {
|
|
222
|
-
constructor(setSettleFn = null) {
|
|
223
|
-
super();
|
|
224
|
-
this._settled = false;
|
|
225
|
-
setSettleFn == null || setSettleFn(() => {
|
|
226
|
-
if (this._settled) {
|
|
227
|
-
throw new Error("SettleSignal already settled");
|
|
228
|
-
}
|
|
229
|
-
this._settled = true;
|
|
230
|
-
this.dispatchEvent(new Event("settled"));
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
static settle() {
|
|
234
|
-
const signal = new SettleSignal();
|
|
235
|
-
signal._settled = true;
|
|
236
|
-
return signal;
|
|
237
|
-
}
|
|
238
|
-
get settled() {
|
|
239
|
-
return this._settled;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
44
|
+
class SettleSignal extends EventTarget{static settle(){const signal=new SettleSignal;signal._settled=true;return signal}get settled(){return this._settled}constructor(setSettleFn=null){super(),this._settled=false;setSettleFn?.(()=>{if(this._settled){throw new Error("SettleSignal already settled")}this._settled=true;this.dispatchEvent(new Event("settled"));});}}
|
|
242
45
|
|
|
243
|
-
class SettleController {
|
|
244
|
-
constructor() {
|
|
245
|
-
this._settleFn = void 0;
|
|
246
|
-
this._signal = void 0;
|
|
247
|
-
this._signal = new SettleSignal(settleFn => this._settleFn = settleFn);
|
|
248
|
-
}
|
|
249
|
-
get signal() {
|
|
250
|
-
return this._signal;
|
|
251
|
-
}
|
|
252
|
-
settle() {
|
|
253
|
-
var _this$_settleFn;
|
|
254
|
-
(_this$_settleFn = this._settleFn) == null || _this$_settleFn.call(this);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
46
|
+
class SettleController{get signal(){return this._signal}settle(){this._settleFn?.();}constructor(){this._signal=new SettleSignal(settleFn=>this._settleFn=settleFn);}}
|
|
257
47
|
|
|
258
|
-
const defaultConfig$3 = null;
|
|
259
|
-
const normalizeConfig = config => {
|
|
260
|
-
if (typeof config === "string") {
|
|
261
|
-
return {
|
|
262
|
-
classes: [config],
|
|
263
|
-
style: {}
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
if (Array.isArray(config)) {
|
|
267
|
-
return {
|
|
268
|
-
classes: config,
|
|
269
|
-
style: {}
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
if (typeof config === "object") {
|
|
273
|
-
if ("classes" in config && config.classes != null && "style" in config && config.style != null) {
|
|
274
|
-
return config;
|
|
275
|
-
}
|
|
276
|
-
return {
|
|
277
|
-
classes: [],
|
|
278
|
-
style: config
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
throw new Error(`Invalid config: ${config}`);
|
|
282
|
-
};
|
|
283
|
-
const adapter$3 = (children, config) => {
|
|
284
|
-
const {
|
|
285
|
-
classes,
|
|
286
|
-
style
|
|
287
|
-
} = normalizeConfig(config);
|
|
288
|
-
return React__namespace.createElement("div", {
|
|
289
|
-
"data-testid": "css-adapter-container",
|
|
290
|
-
className: classes.join(" "),
|
|
291
|
-
style: style
|
|
292
|
-
}, children);
|
|
293
|
-
};
|
|
48
|
+
const defaultConfig$3=null;const normalizeConfig=config=>{if(typeof config==="string"){return {classes:[config],style:{}}}if(Array.isArray(config)){return {classes:config,style:{}}}if(typeof config==="object"){if("classes"in config&&config.classes!=null&&"style"in config&&config.style!=null){return config}return {classes:[],style:config}}throw new Error(`Invalid config: ${config}`)};const adapter$3=(children,config)=>{const{classes,style}=normalizeConfig(config);return jsxRuntime.jsx("div",{"data-testid":"css-adapter-container",className:classes.join(" "),style:style,children:children})};
|
|
294
49
|
|
|
295
|
-
const defaultConfig$2 =
|
|
296
|
-
class ErrorBoundary extends React__namespace.Component {
|
|
297
|
-
constructor(...args) {
|
|
298
|
-
super(...args);
|
|
299
|
-
this.state = {
|
|
300
|
-
renderError: false
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
static getDerivedStateFromError(error) {
|
|
304
|
-
return {
|
|
305
|
-
renderError: true
|
|
306
|
-
};
|
|
307
|
-
}
|
|
308
|
-
componentDidCatch(error, errorInfo) {
|
|
309
|
-
const lastErrorUx = this.props.onError(error, errorInfo);
|
|
310
|
-
this.setState({
|
|
311
|
-
lastErrorUx
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
render() {
|
|
315
|
-
var _this$state$lastError;
|
|
316
|
-
return this.state.renderError ? (_this$state$lastError = this.state.lastErrorUx) != null ? _this$state$lastError : "An error occurred" : this.props.children;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
const adapter$2 = (children, config) => React__namespace.createElement(ErrorBoundary, {
|
|
320
|
-
onError: config
|
|
321
|
-
}, children);
|
|
50
|
+
const defaultConfig$2=null;class ErrorBoundary extends React__namespace.Component{static getDerivedStateFromError(error){return {renderError:true}}componentDidCatch(error,errorInfo){const lastErrorUx=this.props.onError(error,errorInfo);this.setState({lastErrorUx});}render(){return this.state.renderError?this.state.lastErrorUx??"An error occurred":this.props.children}constructor(...args){super(...args),this.state={renderError:false};}}const adapter$2=(children,config)=>jsxRuntime.jsx(ErrorBoundary,{onError:config,children:children});
|
|
322
51
|
|
|
323
|
-
const defaultConfig$1
|
|
324
|
-
const adapter$1 = (children, config) => React__namespace.createElement(React__namespace.Fragment, null, React__namespace.createElement("div", {
|
|
325
|
-
id: config,
|
|
326
|
-
"data-testid": config
|
|
327
|
-
}), children);
|
|
52
|
+
const defaultConfig$1=null;const adapter$1=(children,config)=>jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("div",{id:config,"data-testid":config}),children]});
|
|
328
53
|
|
|
329
|
-
const defaultConfig = {
|
|
330
|
-
location: "/"
|
|
331
|
-
};
|
|
332
|
-
const MaybeWithRoute = ({
|
|
333
|
-
children,
|
|
334
|
-
path,
|
|
335
|
-
configLocation
|
|
336
|
-
}) => {
|
|
337
|
-
if (path == null) {
|
|
338
|
-
return React__namespace.createElement(React__namespace.Fragment, null, children);
|
|
339
|
-
}
|
|
340
|
-
const ErrorElement = () => {
|
|
341
|
-
const actualLocation = reactRouterDomV5Compat.useLocation();
|
|
342
|
-
const configuredLocation = typeof configLocation === "string" ? configLocation : configLocation.pathname;
|
|
343
|
-
const errorMessage = `The current location '${actualLocation.pathname}' ` + `does not match the configured path '${path}'. ` + `Did you provide the correct configured ` + `location, '${configuredLocation}', or did the ` + `routing lead to a different place than you ` + `expected?`;
|
|
344
|
-
throw new Error(errorMessage);
|
|
345
|
-
};
|
|
346
|
-
return React__namespace.createElement(reactRouterDom.Switch, null, React__namespace.createElement(reactRouterDom.Route, {
|
|
347
|
-
path: path,
|
|
348
|
-
render: () => React__namespace.createElement(React__namespace.Fragment, null, children)
|
|
349
|
-
}), React__namespace.createElement(reactRouterDom.Route, {
|
|
350
|
-
path: "*",
|
|
351
|
-
component: ErrorElement
|
|
352
|
-
}));
|
|
353
|
-
};
|
|
354
|
-
const adapter = (children, config) => {
|
|
355
|
-
var _config$initialIndex;
|
|
356
|
-
if (typeof config === "string") {
|
|
357
|
-
config = {
|
|
358
|
-
location: config
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
if ("forceStatic" in config && config.forceStatic) {
|
|
362
|
-
if (config.disableCompatRouter) {
|
|
363
|
-
return React__namespace.createElement(reactRouterDom.StaticRouter, {
|
|
364
|
-
location: config.location,
|
|
365
|
-
context: {}
|
|
366
|
-
}, React__namespace.createElement(MaybeWithRoute, {
|
|
367
|
-
path: config.path,
|
|
368
|
-
configLocation: config.location
|
|
369
|
-
}, children));
|
|
370
|
-
}
|
|
371
|
-
return React__namespace.createElement(reactRouterDom.StaticRouter, {
|
|
372
|
-
location: config.location,
|
|
373
|
-
context: {}
|
|
374
|
-
}, React__namespace.createElement(reactRouterDomV5Compat.CompatRouter, null, React__namespace.createElement(MaybeWithRoute, {
|
|
375
|
-
path: config.path,
|
|
376
|
-
configLocation: config.location
|
|
377
|
-
}, children)));
|
|
378
|
-
}
|
|
379
|
-
if ("location" in config && config.location !== undefined) {
|
|
380
|
-
return React__namespace.createElement(reactRouterDom.MemoryRouter, {
|
|
381
|
-
initialEntries: [config.location]
|
|
382
|
-
}, React__namespace.createElement(reactRouterDomV5Compat.CompatRouter, null, React__namespace.createElement(MaybeWithRoute, {
|
|
383
|
-
path: config.path,
|
|
384
|
-
configLocation: config.location
|
|
385
|
-
}, children)));
|
|
386
|
-
}
|
|
387
|
-
if (!("initialEntries" in config) || config.initialEntries === undefined) {
|
|
388
|
-
throw new Error("A location or initial history entries must be provided.");
|
|
389
|
-
}
|
|
390
|
-
const entries = config.initialEntries.length === 0 ? [defaultConfig.location] : config.initialEntries;
|
|
391
|
-
const routerProps = {
|
|
392
|
-
initialEntries: entries
|
|
393
|
-
};
|
|
394
|
-
if (config.initialIndex != null) {
|
|
395
|
-
routerProps.initialIndex = config.initialIndex;
|
|
396
|
-
}
|
|
397
|
-
return React__namespace.createElement(reactRouterDom.MemoryRouter, routerProps, React__namespace.createElement(reactRouterDomV5Compat.CompatRouter, null, React__namespace.createElement(MaybeWithRoute, {
|
|
398
|
-
path: config.path,
|
|
399
|
-
configLocation: entries[(_config$initialIndex = config.initialIndex) != null ? _config$initialIndex : 0]
|
|
400
|
-
}, children)));
|
|
401
|
-
};
|
|
54
|
+
const defaultConfig={location:"/"};const MaybeWithRoute=({children,path,configLocation})=>{if(path==null){return jsxRuntime.jsx(jsxRuntime.Fragment,{children:children})}const ErrorElement=()=>{const actualLocation=reactRouterDomV5Compat.useLocation();const configuredLocation=typeof configLocation==="string"?configLocation:configLocation.pathname;const errorMessage=`The current location '${actualLocation.pathname}' `+`does not match the configured path '${path}'. `+`Did you provide the correct configured `+`location, '${configuredLocation}', or did the `+`routing lead to a different place than you `+`expected?`;throw new Error(errorMessage)};return jsxRuntime.jsxs(reactRouterDom.Switch,{children:[jsxRuntime.jsx(reactRouterDom.Route,{path:path,render:()=>jsxRuntime.jsx(jsxRuntime.Fragment,{children:children})}),jsxRuntime.jsx(reactRouterDom.Route,{path:"*",component:ErrorElement})]})};const adapter=(children,config)=>{if(typeof config==="string"){config={location:config};}if("forceStatic"in config&&config.forceStatic){if(config.disableCompatRouter){return jsxRuntime.jsx(reactRouterDom.StaticRouter,{location:config.location,context:{},children:jsxRuntime.jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})}return jsxRuntime.jsx(reactRouterDom.StaticRouter,{location:config.location,context:{},children:jsxRuntime.jsx(reactRouterDomV5Compat.CompatRouter,{children:jsxRuntime.jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})})}if("location"in config&&config.location!==undefined){return jsxRuntime.jsx(reactRouterDom.MemoryRouter,{initialEntries:[config.location],children:jsxRuntime.jsx(reactRouterDomV5Compat.CompatRouter,{children:jsxRuntime.jsx(MaybeWithRoute,{path:config.path,configLocation:config.location,children:children})})})}if(!("initialEntries"in config)||config.initialEntries===undefined){throw new Error("A location or initial history entries must be provided.")}const entries=config.initialEntries.length===0?[defaultConfig.location]:config.initialEntries;const routerProps={initialEntries:entries};if(config.initialIndex!=null){routerProps.initialIndex=config.initialIndex;}return jsxRuntime.jsx(reactRouterDom.MemoryRouter,{...routerProps,children:jsxRuntime.jsx(reactRouterDomV5Compat.CompatRouter,{children:jsxRuntime.jsx(MaybeWithRoute,{path:config.path,configLocation:entries[config.initialIndex??0],children:children})})})};
|
|
402
55
|
|
|
403
|
-
const DefaultAdapters =
|
|
404
|
-
boundary: adapter$2,
|
|
405
|
-
css: adapter$3,
|
|
406
|
-
portal: adapter$1,
|
|
407
|
-
router: adapter
|
|
408
|
-
};
|
|
409
|
-
const DefaultConfigs = {
|
|
410
|
-
boundary: defaultConfig$2,
|
|
411
|
-
css: defaultConfig$3,
|
|
412
|
-
portal: defaultConfig$1,
|
|
413
|
-
router: defaultConfig
|
|
414
|
-
};
|
|
56
|
+
const DefaultAdapters={boundary:adapter$2,css:adapter$3,portal:adapter$1,router:adapter};const DefaultConfigs={boundary:defaultConfig$2,css:defaultConfig$3,portal:defaultConfig$1,router:defaultConfig};
|
|
415
57
|
|
|
416
58
|
var adapters = /*#__PURE__*/Object.freeze({
|
|
417
59
|
__proto__: null,
|
|
@@ -419,93 +61,22 @@ var adapters = /*#__PURE__*/Object.freeze({
|
|
|
419
61
|
DefaultConfigs: DefaultConfigs
|
|
420
62
|
});
|
|
421
63
|
|
|
422
|
-
const componentCache
|
|
423
|
-
const getNamedAdapterComponent = name => {
|
|
424
|
-
const existing = componentCache.get(name);
|
|
425
|
-
if (existing != null) {
|
|
426
|
-
return existing;
|
|
427
|
-
}
|
|
428
|
-
const newComponent = ({
|
|
429
|
-
children,
|
|
430
|
-
config,
|
|
431
|
-
adapter
|
|
432
|
-
}) => adapter(children, config);
|
|
433
|
-
newComponent.displayName = `Adapter(${name})`;
|
|
434
|
-
componentCache.set(name, newComponent);
|
|
435
|
-
return newComponent;
|
|
436
|
-
};
|
|
64
|
+
const componentCache=new Map;const getNamedAdapterComponent=name=>{const existing=componentCache.get(name);if(existing!=null){return existing}const newComponent=({children,config,adapter})=>adapter(children,config);newComponent.displayName=`Adapter(${name})`;componentCache.set(name,newComponent);return newComponent};
|
|
437
65
|
|
|
438
|
-
const Adapt = ({
|
|
439
|
-
children,
|
|
440
|
-
adapters,
|
|
441
|
-
configs
|
|
442
|
-
}) => {
|
|
443
|
-
return Object.entries(adapters).reduce((newChildren, [name, adapter]) => {
|
|
444
|
-
const theConfig = configs[name];
|
|
445
|
-
if (theConfig == null) {
|
|
446
|
-
return newChildren;
|
|
447
|
-
}
|
|
448
|
-
const Adapter = getNamedAdapterComponent(name);
|
|
449
|
-
return React__namespace.createElement(Adapter, {
|
|
450
|
-
key: name,
|
|
451
|
-
adapter: adapter,
|
|
452
|
-
config: theConfig
|
|
453
|
-
}, newChildren);
|
|
454
|
-
}, React__namespace.createElement(React__namespace.Fragment, null, children));
|
|
455
|
-
};
|
|
66
|
+
const Adapt=({children,adapters,configs})=>{return Object.entries(adapters).reduce((newChildren,[name,adapter])=>{const theConfig=configs[name];if(theConfig==null){return newChildren}const Adapter=getNamedAdapterComponent(name);return jsxRuntime.jsx(Adapter,{adapter:adapter,config:theConfig,children:newChildren},name)},jsxRuntime.jsx(jsxRuntime.Fragment,{children:children}))};
|
|
456
67
|
|
|
457
|
-
const makeTestHarness
|
|
458
|
-
return (Component, configs) => {
|
|
459
|
-
const fullConfig = _extends__default["default"]({}, defaultConfigs, configs);
|
|
460
|
-
const harnessedComponent = React__namespace.forwardRef((props, ref) => React__namespace.createElement(Adapt, {
|
|
461
|
-
adapters: adapters,
|
|
462
|
-
configs: fullConfig
|
|
463
|
-
}, React__namespace.createElement(Component, _extends__default["default"]({}, props, {
|
|
464
|
-
ref: ref
|
|
465
|
-
}))));
|
|
466
|
-
harnessedComponent.displayName = `testHarness(${Component.displayName || Component.name || "Component"})`;
|
|
467
|
-
return harnessedComponent;
|
|
468
|
-
};
|
|
469
|
-
};
|
|
68
|
+
const makeTestHarness=(adapters,defaultConfigs)=>{return (Component,configs)=>{const fullConfig={...defaultConfigs,...configs};const harnessedComponent=React__namespace.forwardRef((props,ref)=>jsxRuntime.jsx(Adapt,{adapters:adapters,configs:fullConfig,children:jsxRuntime.jsx(Component,{...props,ref:ref})}));harnessedComponent.displayName=`testHarness(${Component.displayName||Component.name||"Component"})`;return harnessedComponent}};
|
|
470
69
|
|
|
471
|
-
const HookHarness = (
|
|
472
|
-
children
|
|
473
|
-
}) => React__namespace.createElement(React__namespace.Fragment, null, children);
|
|
474
|
-
const makeHookHarness = (adapters, defaultConfigs) => {
|
|
475
|
-
const testHarness = makeTestHarness(adapters, defaultConfigs);
|
|
476
|
-
return configs => testHarness(HookHarness, configs);
|
|
477
|
-
};
|
|
70
|
+
const HookHarness=({children})=>jsxRuntime.jsx(jsxRuntime.Fragment,{children:children});const makeHookHarness=(adapters,defaultConfigs)=>{const testHarness=makeTestHarness(adapters,defaultConfigs);return configs=>testHarness(HookHarness,configs)};
|
|
478
71
|
|
|
479
|
-
const hookHarness
|
|
72
|
+
const hookHarness=makeHookHarness(DefaultAdapters,DefaultConfigs);
|
|
480
73
|
|
|
481
|
-
const testHarness
|
|
74
|
+
const testHarness=makeTestHarness(DefaultAdapters,DefaultConfigs);
|
|
482
75
|
|
|
483
|
-
const renderHookStatic = (
|
|
484
|
-
wrapper,
|
|
485
|
-
initialProps
|
|
486
|
-
} = {}) => {
|
|
487
|
-
let result;
|
|
488
|
-
function TestComponent({
|
|
489
|
-
renderCallbackProps
|
|
490
|
-
}) {
|
|
491
|
-
result = render(renderCallbackProps);
|
|
492
|
-
return null;
|
|
493
|
-
}
|
|
494
|
-
const component = React__namespace.createElement(TestComponent, {
|
|
495
|
-
renderCallbackProps: initialProps
|
|
496
|
-
});
|
|
497
|
-
const componentWithWrapper = wrapper == null ? component : React__namespace.createElement(wrapper, null, component);
|
|
498
|
-
ReactDOMServer__namespace.renderToString(componentWithWrapper);
|
|
499
|
-
return {
|
|
500
|
-
result: {
|
|
501
|
-
current: result
|
|
502
|
-
}
|
|
503
|
-
};
|
|
504
|
-
};
|
|
76
|
+
const renderHookStatic=(render,{wrapper,initialProps}={})=>{let result;function TestComponent({renderCallbackProps}){result=render(renderCallbackProps);return null}const component=jsxRuntime.jsx(TestComponent,{renderCallbackProps:initialProps});const componentWithWrapper=wrapper==null?component:React__namespace.createElement(wrapper,null,component);ReactDOMServer__namespace.renderToString(componentWithWrapper);return {result:{current:result}}};
|
|
505
77
|
|
|
506
78
|
exports.RespondWith = RespondWith;
|
|
507
79
|
exports.SettleController = SettleController;
|
|
508
|
-
exports.fixtures = fixtures;
|
|
509
80
|
exports.harnessAdapters = adapters;
|
|
510
81
|
exports.hookHarness = hookHarness;
|
|
511
82
|
exports.makeHookHarness = makeHookHarness;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanacademy/wonder-blocks-testing-core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"design": "v1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -9,12 +9,9 @@
|
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"module": "dist/es/index.js",
|
|
11
11
|
"types": "dist/index.d.ts",
|
|
12
|
-
"dependencies": {
|
|
13
|
-
"@babel/runtime": "^7.24.5"
|
|
14
|
-
},
|
|
12
|
+
"dependencies": {},
|
|
15
13
|
"peerDependencies": {
|
|
16
14
|
"@khanacademy/wonder-stuff-core": "^1.5.4",
|
|
17
|
-
"@storybook/addon-actions": "^8.5.2",
|
|
18
15
|
"aphrodite": "^1.2.5",
|
|
19
16
|
"node-fetch": "^2.6.7",
|
|
20
17
|
"react": "18.2.0",
|
|
@@ -23,8 +20,8 @@
|
|
|
23
20
|
"react-router-dom-v5-compat": "^6.30.0"
|
|
24
21
|
},
|
|
25
22
|
"devDependencies": {
|
|
26
|
-
"@khanacademy/wonder-stuff-testing": "^3.0.
|
|
27
|
-
"@khanacademy/wb-dev-build-settings": "2.
|
|
23
|
+
"@khanacademy/wonder-stuff-testing": "^3.0.5",
|
|
24
|
+
"@khanacademy/wb-dev-build-settings": "3.2.0"
|
|
28
25
|
},
|
|
29
26
|
"author": "",
|
|
30
27
|
"license": "MIT",
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
type Props = {
|
|
3
|
-
propA: string;
|
|
4
|
-
propB?: string;
|
|
5
|
-
};
|
|
6
|
-
export declare const F1: unknown;
|
|
7
|
-
export declare const F2: unknown;
|
|
8
|
-
export declare const F3: unknown;
|
|
9
|
-
declare const _default: {
|
|
10
|
-
title: string;
|
|
11
|
-
component: (props: Props) => React.ReactElement;
|
|
12
|
-
};
|
|
13
|
-
export default _default;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import type { FixtureFn } from "./types";
|
|
3
|
-
/**
|
|
4
|
-
* Describe a group of fixtures for a given component.
|
|
5
|
-
*
|
|
6
|
-
* Only one `fixtures` call should be used per fixture file as it returns
|
|
7
|
-
* the exports for that file.
|
|
8
|
-
*
|
|
9
|
-
* @param {React.ComponentType<any>} Component The component we want to create
|
|
10
|
-
* stories for.
|
|
11
|
-
* @returns {FixtureFn<TProps>} A function to create a CSF compatible story.
|
|
12
|
-
*
|
|
13
|
-
* @deprecated Use CSFv3 style stories instead. This API was for migration
|
|
14
|
-
* from our old fixtures framework and will be removed in a future release.
|
|
15
|
-
*/
|
|
16
|
-
export declare const fixtures: <TComponent extends React.ComponentType<any>, TProps extends JSX.LibraryManagedAttributes<TComponent, React.ComponentProps<TComponent>>>(Component: TComponent) => FixtureFn<TProps>;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
type Props = Record<any, any>;
|
|
3
|
-
export declare const F1: unknown;
|
|
4
|
-
export declare const F2: unknown;
|
|
5
|
-
declare const _default: {
|
|
6
|
-
title: string;
|
|
7
|
-
component: (props: Props) => React.ReactElement;
|
|
8
|
-
};
|
|
9
|
-
export default _default;
|
package/dist/fixtures/types.d.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
/**
|
|
3
|
-
* Options injected to the function that returns the fixture props.
|
|
4
|
-
* @deprecated Use CSFv3 style stories instead. This API was for migration
|
|
5
|
-
* from our old fixtures framework and will be removed in a future release.
|
|
6
|
-
*/
|
|
7
|
-
export type GetPropsOptions = {
|
|
8
|
-
/**
|
|
9
|
-
* A function to call that will log output.
|
|
10
|
-
*/
|
|
11
|
-
log: (message: string, ...args: Array<any>) => void;
|
|
12
|
-
/**
|
|
13
|
-
* A function to make a handler that will log all arguments with the given
|
|
14
|
-
* name or message. Useful for logging events as it avoids the boilerplate
|
|
15
|
-
* of the `log` function.
|
|
16
|
-
*/
|
|
17
|
-
logHandler: (name: string) => (...args: Array<any>) => void;
|
|
18
|
-
};
|
|
19
|
-
/**
|
|
20
|
-
* The props for a fixture.
|
|
21
|
-
*
|
|
22
|
-
* This can be either a static object or a function that returns an object.
|
|
23
|
-
*
|
|
24
|
-
* @deprecated Use CSFv3 style stories instead. This API was for migration
|
|
25
|
-
* from our old fixtures framework and will be removed in a future release.
|
|
26
|
-
*/
|
|
27
|
-
export type FixtureProps<TProps extends object> = Readonly<TProps> | ((options: Readonly<GetPropsOptions>) => Readonly<TProps>);
|
|
28
|
-
/**
|
|
29
|
-
* A function for defining a fixture.
|
|
30
|
-
* @deprecated Use CSFv3 style stories instead. This API was for migration
|
|
31
|
-
* from our old fixtures framework and will be removed in a future release.
|
|
32
|
-
*/
|
|
33
|
-
export type FixtureFn<TProps extends object> = (
|
|
34
|
-
/**
|
|
35
|
-
* The name of the fixture.
|
|
36
|
-
*/
|
|
37
|
-
description: string,
|
|
38
|
-
/**
|
|
39
|
-
* The props for the fixture or a function that returns the props.
|
|
40
|
-
* The function is injected with an API to facilitate logging.
|
|
41
|
-
*/
|
|
42
|
-
props: FixtureProps<TProps>,
|
|
43
|
-
/**
|
|
44
|
-
* An alternative component to render for the fixture.
|
|
45
|
-
* Useful if the fixture requires some additional setup for testing the
|
|
46
|
-
* component.
|
|
47
|
-
*/
|
|
48
|
-
wrapper?: React.ComponentType<TProps>) => unknown;
|