@khanacademy/wonder-blocks-data 8.0.1 → 8.0.4
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 +22 -0
- package/dist/es/index.js +8 -15
- package/dist/index.js +28 -167
- package/package.json +4 -3
- package/src/hooks/use-cached-effect.js +3 -14
- package/src/hooks/use-hydratable-effect.js +0 -4
- package/src/util/__tests__/ssr-cache.test.js +28 -38
- package/src/util/ssr-cache.js +12 -17
- package/src/util/types.js +0 -4
- package/src/__tests__/__snapshots__/generated-snapshot.test.js.snap +0 -337
- package/src/__tests__/generated-snapshot.test.js +0 -350
|
@@ -1,350 +0,0 @@
|
|
|
1
|
-
// This file is auto-generated by gen-snapshot-tests.js
|
|
2
|
-
// Do not edit this file. To make changes to these snapshot tests:
|
|
3
|
-
// 1. edit the markdown documentation files in the package,
|
|
4
|
-
// packages/wonder-blocks-data
|
|
5
|
-
// 2. Run `yarn run gen-snapshot-tests`.
|
|
6
|
-
import React from "react";
|
|
7
|
-
import renderer from "react-test-renderer";
|
|
8
|
-
|
|
9
|
-
// Mock react-dom as jest doesn't like findDOMNode.
|
|
10
|
-
jest.mock("react-dom");
|
|
11
|
-
import {Body, BodyMonospace} from "@khanacademy/wonder-blocks-typography";
|
|
12
|
-
import {View, Server} from "@khanacademy/wonder-blocks-core";
|
|
13
|
-
import {
|
|
14
|
-
Data,
|
|
15
|
-
initializeHydrationCache,
|
|
16
|
-
InterceptRequests,
|
|
17
|
-
TrackData,
|
|
18
|
-
fetchTrackedRequests,
|
|
19
|
-
} from "@khanacademy/wonder-blocks-data";
|
|
20
|
-
import {Strut} from "@khanacademy/wonder-blocks-layout";
|
|
21
|
-
import Color from "@khanacademy/wonder-blocks-color";
|
|
22
|
-
import Spacing from "@khanacademy/wonder-blocks-spacing";
|
|
23
|
-
import Button from "@khanacademy/wonder-blocks-button";
|
|
24
|
-
|
|
25
|
-
describe("wonder-blocks-data", () => {
|
|
26
|
-
it("example 1", () => {
|
|
27
|
-
const myValidHandler = () =>
|
|
28
|
-
new Promise((resolve, reject) =>
|
|
29
|
-
setTimeout(() => resolve("I'm DATA from a request"), 3000),
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
const myInvalidHandler = () =>
|
|
33
|
-
new Promise((resolve, reject) =>
|
|
34
|
-
setTimeout(() => reject("I'm an ERROR from a request"), 3000),
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
const example = (
|
|
38
|
-
<View>
|
|
39
|
-
<View>
|
|
40
|
-
<Body>This request will succeed and give us data!</Body>
|
|
41
|
-
<Data handler={myValidHandler} requestId="VALID">
|
|
42
|
-
{(result) => {
|
|
43
|
-
if (result.status === "loading") {
|
|
44
|
-
return "Loading...";
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return <BodyMonospace>{result.data}</BodyMonospace>;
|
|
48
|
-
}}
|
|
49
|
-
</Data>
|
|
50
|
-
</View>
|
|
51
|
-
<Strut size={Spacing.small_12} />
|
|
52
|
-
<View>
|
|
53
|
-
<Body>This request will go boom and give us an error!</Body>
|
|
54
|
-
<Data handler={myInvalidHandler} requestId="INVALID">
|
|
55
|
-
{(result) => {
|
|
56
|
-
if (result.status === "loading") {
|
|
57
|
-
return "Loading...";
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return (
|
|
61
|
-
<BodyMonospace
|
|
62
|
-
style={{
|
|
63
|
-
color: Color.red,
|
|
64
|
-
}}
|
|
65
|
-
>
|
|
66
|
-
ERROR: {result.error}
|
|
67
|
-
</BodyMonospace>
|
|
68
|
-
);
|
|
69
|
-
}}
|
|
70
|
-
</Data>
|
|
71
|
-
</View>
|
|
72
|
-
</View>
|
|
73
|
-
);
|
|
74
|
-
const tree = renderer.create(example).toJSON();
|
|
75
|
-
expect(tree).toMatchSnapshot();
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it("example 2", () => {
|
|
79
|
-
const myHandler = () => {
|
|
80
|
-
throw new Error(
|
|
81
|
-
"If you're seeing this error, the examples are broken and data isn't in the cache that should be.",
|
|
82
|
-
);
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
initializeHydrationCache({
|
|
86
|
-
DATA: {
|
|
87
|
-
data: "I'm DATA from the hydration cache",
|
|
88
|
-
},
|
|
89
|
-
});
|
|
90
|
-
const example = (
|
|
91
|
-
<View>
|
|
92
|
-
<View>
|
|
93
|
-
<Body>This cache has data!</Body>
|
|
94
|
-
<Data handler={myHandler} requestId="DATA">
|
|
95
|
-
{(result) => {
|
|
96
|
-
if (result.status !== "success") {
|
|
97
|
-
return "If you see this, the example is broken!";
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return <BodyMonospace>{result.data}</BodyMonospace>;
|
|
101
|
-
}}
|
|
102
|
-
</Data>
|
|
103
|
-
</View>
|
|
104
|
-
</View>
|
|
105
|
-
);
|
|
106
|
-
const tree = renderer.create(example).toJSON();
|
|
107
|
-
expect(tree).toMatchSnapshot();
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it("example 3", () => {
|
|
111
|
-
const myHandler = () =>
|
|
112
|
-
Promise.reject(new Error("You should not see this!"));
|
|
113
|
-
|
|
114
|
-
const interceptor = (requestId) =>
|
|
115
|
-
requestId === "INTERCEPT_EXAMPLE"
|
|
116
|
-
? Promise.resolve("INTERCEPTED DATA!")
|
|
117
|
-
: null;
|
|
118
|
-
|
|
119
|
-
const example = (
|
|
120
|
-
<InterceptRequests interceptor={interceptor}>
|
|
121
|
-
<View>
|
|
122
|
-
<Body>This received intercepted data!</Body>
|
|
123
|
-
<Data handler={myHandler} requestId="INTERCEPT_EXAMPLE">
|
|
124
|
-
{(result) => {
|
|
125
|
-
if (result.status !== "success") {
|
|
126
|
-
return "If you see this, the example is broken!";
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return <BodyMonospace>{result.data}</BodyMonospace>;
|
|
130
|
-
}}
|
|
131
|
-
</Data>
|
|
132
|
-
</View>
|
|
133
|
-
</InterceptRequests>
|
|
134
|
-
);
|
|
135
|
-
const tree = renderer.create(example).toJSON();
|
|
136
|
-
expect(tree).toMatchSnapshot();
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
it("example 4", () => {
|
|
140
|
-
class ErrorBoundary extends React.Component {
|
|
141
|
-
constructor(props) {
|
|
142
|
-
super(props);
|
|
143
|
-
this.state = {};
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
static getDerivedStateFromError(error) {
|
|
147
|
-
return {
|
|
148
|
-
error: error.message,
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
render() {
|
|
153
|
-
if (typeof jest !== "undefined") {
|
|
154
|
-
/**
|
|
155
|
-
* The snapshot test just sees the error getting thrown, not the
|
|
156
|
-
* awesome error boundary, so we have to hack around it to keep
|
|
157
|
-
* this live example, but not get test failures.
|
|
158
|
-
*/
|
|
159
|
-
return "Sorry, no snapshot for you";
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (this.state.error) {
|
|
163
|
-
return <View>{this.state.error}</View>;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return this.props.children;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const example = (
|
|
171
|
-
<ErrorBoundary>
|
|
172
|
-
<View>
|
|
173
|
-
<TrackData>
|
|
174
|
-
<Body>
|
|
175
|
-
This only renders if we're in server-side mode and
|
|
176
|
-
the page hot reloaded
|
|
177
|
-
</Body>
|
|
178
|
-
</TrackData>
|
|
179
|
-
</View>
|
|
180
|
-
</ErrorBoundary>
|
|
181
|
-
);
|
|
182
|
-
const tree = renderer.create(example).toJSON();
|
|
183
|
-
expect(tree).toMatchSnapshot();
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
it("example 5", () => {
|
|
187
|
-
const myPretendHandler = () =>
|
|
188
|
-
new Promise((resolve, reject) =>
|
|
189
|
-
setTimeout(() => resolve("DATA!"), 3000),
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
class Example extends React.Component {
|
|
193
|
-
constructor() {
|
|
194
|
-
super();
|
|
195
|
-
/**
|
|
196
|
-
* For this demonstration, we need to hack the return of isServerSide solely
|
|
197
|
-
* for the scope of this component.
|
|
198
|
-
*/
|
|
199
|
-
|
|
200
|
-
this.state = {};
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
static getDerivedStateFromError(error) {
|
|
204
|
-
return {
|
|
205
|
-
error,
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
componentDidMount() {
|
|
210
|
-
this._mounted = true;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
componentWillUnmount() {
|
|
214
|
-
this._mounted = false;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
setClientMode() {
|
|
218
|
-
window.location.reload();
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
setServerMode() {
|
|
222
|
-
Server.setServerSide();
|
|
223
|
-
this.setState({
|
|
224
|
-
refresh: Date.now(),
|
|
225
|
-
error: null,
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
_renderErrorOrContent() {
|
|
230
|
-
if (typeof jest !== "undefined") {
|
|
231
|
-
/**
|
|
232
|
-
* The snapshot test just sees the error getting thrown, not the
|
|
233
|
-
* awesome error boundary, so we have to hack around it to keep
|
|
234
|
-
* this live example, but not get test failures.
|
|
235
|
-
*/
|
|
236
|
-
return "Sorry, no snapshot for you";
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
if (this.state.error) {
|
|
240
|
-
return (
|
|
241
|
-
<React.Fragment>
|
|
242
|
-
<Strut size={Spacing.small_12} />
|
|
243
|
-
<Body>
|
|
244
|
-
We can't show you anything useful in client-side
|
|
245
|
-
mode
|
|
246
|
-
</Body>
|
|
247
|
-
</React.Fragment>
|
|
248
|
-
);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const data = this.state.data
|
|
252
|
-
? JSON.stringify(this.state.data, undefined, " ")
|
|
253
|
-
: "Data requested...";
|
|
254
|
-
return (
|
|
255
|
-
<React.Fragment>
|
|
256
|
-
<Strut size={Spacing.small_12} />
|
|
257
|
-
<TrackData>
|
|
258
|
-
<Data
|
|
259
|
-
handler={myPretendHandler}
|
|
260
|
-
requestId="TRACK_DATA_EXAMPLE"
|
|
261
|
-
>
|
|
262
|
-
{(result) => (
|
|
263
|
-
<View>
|
|
264
|
-
<BodyMonospace>{`Loading: ${
|
|
265
|
-
result.status === "loading"
|
|
266
|
-
}`}</BodyMonospace>
|
|
267
|
-
<BodyMonospace>{`Data: ${JSON.stringify(
|
|
268
|
-
result.data,
|
|
269
|
-
)}`}</BodyMonospace>
|
|
270
|
-
</View>
|
|
271
|
-
)}
|
|
272
|
-
</Data>
|
|
273
|
-
</TrackData>
|
|
274
|
-
<Strut size={Spacing.small_12} />
|
|
275
|
-
<View>
|
|
276
|
-
<Body>
|
|
277
|
-
The above components requested data, but we're
|
|
278
|
-
server-side, so all that happened is we tracked
|
|
279
|
-
the request. In this example, we've also called
|
|
280
|
-
`fetchTrackedRequests` to fetch that tracked
|
|
281
|
-
data.
|
|
282
|
-
</Body>
|
|
283
|
-
<Strut size={Spacing.small_12} />
|
|
284
|
-
<Body>
|
|
285
|
-
In about 3 seconds, it will appear below. Notice
|
|
286
|
-
that when it does, the above still doesn't
|
|
287
|
-
update. That's because during SSR, the data is
|
|
288
|
-
not updated in the rendered tree.
|
|
289
|
-
</Body>
|
|
290
|
-
<Strut size={Spacing.small_12} />
|
|
291
|
-
<BodyMonospace>{data}</BodyMonospace>
|
|
292
|
-
</View>
|
|
293
|
-
</React.Fragment>
|
|
294
|
-
);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
render() {
|
|
298
|
-
try {
|
|
299
|
-
return (
|
|
300
|
-
<View key={this.state.refresh}>
|
|
301
|
-
{Server.isServerSide() ? (
|
|
302
|
-
<React.Fragment>
|
|
303
|
-
<Button
|
|
304
|
-
kind={"secondary"}
|
|
305
|
-
onClick={() => this.setClientMode()}
|
|
306
|
-
>
|
|
307
|
-
Back to Client-side Mode (reloads page)
|
|
308
|
-
</Button>
|
|
309
|
-
<Strut size={Spacing.small_12} />
|
|
310
|
-
<Button
|
|
311
|
-
kind={"secondary"}
|
|
312
|
-
onClick={() => this.setServerMode()}
|
|
313
|
-
>
|
|
314
|
-
Re-mount
|
|
315
|
-
</Button>
|
|
316
|
-
</React.Fragment>
|
|
317
|
-
) : (
|
|
318
|
-
<Button
|
|
319
|
-
kind={"primary"}
|
|
320
|
-
onClick={() => this.setServerMode()}
|
|
321
|
-
>
|
|
322
|
-
Enable Server-side Mode
|
|
323
|
-
</Button>
|
|
324
|
-
)}
|
|
325
|
-
{this._renderErrorOrContent()}
|
|
326
|
-
</View>
|
|
327
|
-
);
|
|
328
|
-
} finally {
|
|
329
|
-
if (!this.state.data && Server.isServerSide()) {
|
|
330
|
-
setTimeout(
|
|
331
|
-
() =>
|
|
332
|
-
fetchTrackedRequests().then((data) => {
|
|
333
|
-
if (this._mounted) {
|
|
334
|
-
this.setState({
|
|
335
|
-
data,
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
}),
|
|
339
|
-
0,
|
|
340
|
-
);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
const example = <Example />;
|
|
347
|
-
const tree = renderer.create(example).toJSON();
|
|
348
|
-
expect(tree).toMatchSnapshot();
|
|
349
|
-
});
|
|
350
|
-
});
|