@khanacademy/wonder-blocks-data 3.2.0 → 4.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 +23 -0
- package/dist/es/index.js +356 -332
- package/dist/index.js +507 -456
- package/docs.md +17 -35
- package/package.json +1 -1
- package/src/__tests__/__snapshots__/generated-snapshot.test.js.snap +7 -46
- package/src/__tests__/generated-snapshot.test.js +56 -122
- package/src/components/__tests__/data.test.js +372 -297
- package/src/components/__tests__/intercept-data.test.js +6 -30
- package/src/components/data.js +153 -21
- package/src/components/data.md +38 -69
- package/src/components/intercept-context.js +6 -2
- package/src/components/intercept-data.js +40 -51
- package/src/components/intercept-data.md +13 -27
- package/src/components/track-data.md +9 -23
- package/src/hooks/__tests__/__snapshots__/use-shared-cache.test.js.snap +17 -0
- package/src/hooks/__tests__/use-server-effect.test.js +217 -0
- package/src/hooks/__tests__/use-shared-cache.test.js +307 -0
- package/src/hooks/use-server-effect.js +45 -0
- package/src/hooks/use-shared-cache.js +106 -0
- package/src/index.js +15 -19
- package/src/util/__tests__/__snapshots__/scoped-in-memory-cache.test.js.snap +19 -0
- package/src/util/__tests__/request-fulfillment.test.js +42 -85
- package/src/util/__tests__/request-tracking.test.js +72 -191
- package/src/util/__tests__/{result-from-cache-entry.test.js → result-from-cache-response.test.js} +9 -10
- package/src/util/__tests__/scoped-in-memory-cache.test.js +396 -0
- package/src/util/__tests__/ssr-cache.test.js +639 -0
- package/src/util/request-fulfillment.js +36 -44
- package/src/util/request-tracking.js +62 -75
- package/src/util/{result-from-cache-entry.js → result-from-cache-response.js} +10 -13
- package/src/util/scoped-in-memory-cache.js +149 -0
- package/src/util/ssr-cache.js +206 -0
- package/src/util/types.js +43 -108
- package/src/hooks/__tests__/use-data.test.js +0 -826
- package/src/hooks/use-data.js +0 -143
- package/src/util/__tests__/memory-cache.test.js +0 -446
- package/src/util/__tests__/request-handler.test.js +0 -121
- package/src/util/__tests__/response-cache.test.js +0 -879
- package/src/util/memory-cache.js +0 -187
- package/src/util/request-handler.js +0 -42
- package/src/util/request-handler.md +0 -51
- package/src/util/response-cache.js +0 -213
|
@@ -9,19 +9,15 @@ import {Server, View} from "@khanacademy/wonder-blocks-core";
|
|
|
9
9
|
|
|
10
10
|
import TrackData from "../track-data.js";
|
|
11
11
|
import {RequestFulfillment} from "../../util/request-fulfillment.js";
|
|
12
|
-
import {
|
|
12
|
+
import {SsrCache} from "../../util/ssr-cache.js";
|
|
13
13
|
import {RequestTracker} from "../../util/request-tracking.js";
|
|
14
14
|
import InterceptData from "../intercept-data.js";
|
|
15
15
|
import Data from "../data.js";
|
|
16
16
|
|
|
17
|
-
import type {IRequestHandler} from "../../util/types.js";
|
|
18
|
-
|
|
19
17
|
describe("Data", () => {
|
|
20
18
|
beforeEach(() => {
|
|
21
|
-
const responseCache = new
|
|
22
|
-
jest.spyOn(
|
|
23
|
-
responseCache,
|
|
24
|
-
);
|
|
19
|
+
const responseCache = new SsrCache();
|
|
20
|
+
jest.spyOn(SsrCache, "Default", "get").mockReturnValue(responseCache);
|
|
25
21
|
jest.spyOn(RequestFulfillment, "Default", "get").mockReturnValue(
|
|
26
22
|
new RequestFulfillment(responseCache),
|
|
27
23
|
);
|
|
@@ -45,53 +41,42 @@ describe("Data", () => {
|
|
|
45
41
|
* Each of these test cases will not have cached data to be
|
|
46
42
|
* retrieved in the beginning.
|
|
47
43
|
*/
|
|
48
|
-
jest.spyOn(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
).mockReturnValueOnce(null);
|
|
44
|
+
jest.spyOn(SsrCache.Default, "getEntry").mockReturnValueOnce(
|
|
45
|
+
null,
|
|
46
|
+
);
|
|
52
47
|
});
|
|
53
48
|
|
|
54
|
-
it("should make request for data on construction", () => {
|
|
49
|
+
it("should make request for data on construction", async () => {
|
|
55
50
|
// Arrange
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
);
|
|
59
|
-
const fakeHandler: IRequestHandler<string, string> = {
|
|
60
|
-
fulfillRequest: fulfillRequestSpy,
|
|
61
|
-
getKey: (o) => o,
|
|
62
|
-
type: "MY_HANDLER",
|
|
63
|
-
hydrate: true,
|
|
64
|
-
};
|
|
51
|
+
const response = Promise.resolve("data");
|
|
52
|
+
const fakeHandler = jest.fn().mockReturnValue(response);
|
|
65
53
|
const fakeChildrenFn = jest.fn(() => null);
|
|
66
54
|
|
|
67
55
|
// Act
|
|
68
56
|
render(
|
|
69
|
-
<Data handler={fakeHandler}
|
|
57
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
70
58
|
{fakeChildrenFn}
|
|
71
59
|
</Data>,
|
|
72
60
|
);
|
|
61
|
+
await act(() => response);
|
|
73
62
|
|
|
74
63
|
// Assert
|
|
75
|
-
expect(
|
|
76
|
-
expect(fulfillRequestSpy).toHaveBeenCalledTimes(1);
|
|
64
|
+
expect(fakeHandler).toHaveBeenCalledTimes(1);
|
|
77
65
|
});
|
|
78
66
|
|
|
79
|
-
it("should initially render children with loading", () => {
|
|
67
|
+
it("should initially render children with loading", async () => {
|
|
80
68
|
// Arrange
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
getKey: (o) => o,
|
|
84
|
-
type: "MY_HANDLER",
|
|
85
|
-
hydrate: true,
|
|
86
|
-
};
|
|
69
|
+
const response = Promise.resolve("data");
|
|
70
|
+
const fakeHandler = jest.fn().mockReturnValue(response);
|
|
87
71
|
const fakeChildrenFn = jest.fn(() => null);
|
|
88
72
|
|
|
89
73
|
// Act
|
|
90
74
|
render(
|
|
91
|
-
<Data handler={fakeHandler}
|
|
75
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
92
76
|
{fakeChildrenFn}
|
|
93
77
|
</Data>,
|
|
94
78
|
);
|
|
79
|
+
await act(() => response);
|
|
95
80
|
|
|
96
81
|
// Assert
|
|
97
82
|
expect(fakeChildrenFn).toHaveBeenCalledWith({
|
|
@@ -101,32 +86,25 @@ describe("Data", () => {
|
|
|
101
86
|
|
|
102
87
|
it("should share single request across all uses", () => {
|
|
103
88
|
// Arrange
|
|
104
|
-
const
|
|
89
|
+
const fakeHandler = jest.fn(
|
|
105
90
|
() => new Promise((resolve, reject) => {}),
|
|
106
91
|
);
|
|
107
|
-
const fakeHandler: IRequestHandler<string, string> = {
|
|
108
|
-
fulfillRequest: fulfillRequestSpy,
|
|
109
|
-
getKey: (o) => o,
|
|
110
|
-
type: "MY_HANDLER",
|
|
111
|
-
hydrate: true,
|
|
112
|
-
};
|
|
113
92
|
const fakeChildrenFn = jest.fn(() => null);
|
|
114
93
|
|
|
115
94
|
// Act
|
|
116
95
|
render(
|
|
117
96
|
<View>
|
|
118
|
-
<Data handler={fakeHandler}
|
|
97
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
119
98
|
{fakeChildrenFn}
|
|
120
99
|
</Data>
|
|
121
|
-
<Data handler={fakeHandler}
|
|
100
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
122
101
|
{fakeChildrenFn}
|
|
123
102
|
</Data>
|
|
124
103
|
</View>,
|
|
125
104
|
);
|
|
126
105
|
|
|
127
106
|
// Assert
|
|
128
|
-
expect(
|
|
129
|
-
expect(fulfillRequestSpy).toHaveBeenCalledTimes(1);
|
|
107
|
+
expect(fakeHandler).toHaveBeenCalledTimes(1);
|
|
130
108
|
});
|
|
131
109
|
|
|
132
110
|
it("should render with an error if the request rejects to an error", async () => {
|
|
@@ -135,18 +113,12 @@ describe("Data", () => {
|
|
|
135
113
|
RequestFulfillment.Default,
|
|
136
114
|
"fulfill",
|
|
137
115
|
);
|
|
138
|
-
|
|
139
|
-
const fakeHandler: IRequestHandler<string, string> = {
|
|
140
|
-
fulfillRequest: () => Promise.reject(new Error("OH NOES!")),
|
|
141
|
-
getKey: (o) => o,
|
|
142
|
-
type: "MY_HANDLER",
|
|
143
|
-
hydrate: true,
|
|
144
|
-
};
|
|
116
|
+
const fakeHandler = () => Promise.reject(new Error("OH NOES!"));
|
|
145
117
|
const fakeChildrenFn = jest.fn(() => null);
|
|
146
118
|
|
|
147
119
|
// Act
|
|
148
120
|
render(
|
|
149
|
-
<Data handler={fakeHandler}
|
|
121
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
150
122
|
{fakeChildrenFn}
|
|
151
123
|
</Data>,
|
|
152
124
|
);
|
|
@@ -170,17 +142,12 @@ describe("Data", () => {
|
|
|
170
142
|
"fulfill",
|
|
171
143
|
);
|
|
172
144
|
|
|
173
|
-
const fakeHandler
|
|
174
|
-
fulfillRequest: () => Promise.resolve("YAY! DATA!"),
|
|
175
|
-
getKey: (o) => o,
|
|
176
|
-
type: "MY_HANDLER",
|
|
177
|
-
hydrate: true,
|
|
178
|
-
};
|
|
145
|
+
const fakeHandler = () => Promise.resolve("YAY! DATA!");
|
|
179
146
|
const fakeChildrenFn = jest.fn(() => null);
|
|
180
147
|
|
|
181
148
|
// Act
|
|
182
149
|
render(
|
|
183
|
-
<Data handler={fakeHandler}
|
|
150
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
184
151
|
{fakeChildrenFn}
|
|
185
152
|
</Data>,
|
|
186
153
|
);
|
|
@@ -197,86 +164,76 @@ describe("Data", () => {
|
|
|
197
164
|
});
|
|
198
165
|
});
|
|
199
166
|
|
|
200
|
-
it
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
};
|
|
212
|
-
const fakeChildrenFn = jest.fn(() => null);
|
|
213
|
-
const consoleSpy = jest
|
|
214
|
-
.spyOn(console, "error")
|
|
215
|
-
.mockImplementation(() => {
|
|
216
|
-
/* Just to shut it up */
|
|
217
|
-
});
|
|
167
|
+
it.each`
|
|
168
|
+
error
|
|
169
|
+
${"CATASTROPHE!"}
|
|
170
|
+
${new Error("CATASTROPHE!")}
|
|
171
|
+
`(
|
|
172
|
+
"should render with an error if the request rejects with $error",
|
|
173
|
+
async ({error}) => {
|
|
174
|
+
// Arrange
|
|
175
|
+
const fulfillSpy = jest
|
|
176
|
+
.spyOn(RequestFulfillment.Default, "fulfill")
|
|
177
|
+
.mockReturnValue(Promise.reject(error));
|
|
218
178
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
* We wait for the fulfillment to reject.
|
|
227
|
-
*/
|
|
228
|
-
await act(() =>
|
|
229
|
-
fulfillSpy.mock.results[0].value.catch(() => {}),
|
|
230
|
-
);
|
|
179
|
+
const fakeHandler = () => Promise.resolve("YAY!");
|
|
180
|
+
const fakeChildrenFn = jest.fn(() => null);
|
|
181
|
+
const consoleSpy = jest
|
|
182
|
+
.spyOn(console, "error")
|
|
183
|
+
.mockImplementation(() => {
|
|
184
|
+
/* Just to shut it up */
|
|
185
|
+
});
|
|
231
186
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
187
|
+
// Act
|
|
188
|
+
render(
|
|
189
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
190
|
+
{fakeChildrenFn}
|
|
191
|
+
</Data>,
|
|
192
|
+
);
|
|
193
|
+
/**
|
|
194
|
+
* We wait for the fulfillment to reject.
|
|
195
|
+
*/
|
|
196
|
+
await act(() =>
|
|
197
|
+
fulfillSpy.mock.results[0].value.catch(() => {}),
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
// Assert
|
|
201
|
+
expect(fakeChildrenFn).toHaveBeenCalledTimes(2);
|
|
202
|
+
expect(fakeChildrenFn).toHaveBeenLastCalledWith({
|
|
203
|
+
status: "error",
|
|
204
|
+
error: "CATASTROPHE!",
|
|
205
|
+
});
|
|
206
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
207
|
+
expect.stringMatching(
|
|
208
|
+
"Unexpected error occurred during data fulfillment:(?: Error:)? CATASTROPHE!",
|
|
209
|
+
),
|
|
210
|
+
);
|
|
211
|
+
},
|
|
212
|
+
);
|
|
242
213
|
|
|
243
|
-
it("should
|
|
214
|
+
it("should start loading if the id changes and request not cached", async () => {
|
|
244
215
|
// Arrange
|
|
245
216
|
const fulfillSpy = jest.spyOn(
|
|
246
217
|
RequestFulfillment.Default,
|
|
247
218
|
"fulfill",
|
|
248
219
|
);
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
getKey: (o) => o,
|
|
252
|
-
type: "TYPE1",
|
|
253
|
-
hydrate: true,
|
|
254
|
-
};
|
|
255
|
-
const fakeHandler2: IRequestHandler<string, string> = {
|
|
256
|
-
fulfillRequest: () =>
|
|
257
|
-
new Promise(() => {
|
|
258
|
-
/*pending*/
|
|
259
|
-
}),
|
|
260
|
-
getKey: (o) => o,
|
|
261
|
-
type: "TYPE2",
|
|
262
|
-
hydrate: true,
|
|
263
|
-
};
|
|
220
|
+
|
|
221
|
+
const fakeHandler = () => Promise.resolve("HELLO!");
|
|
264
222
|
const fakeChildrenFn = jest.fn(() => null);
|
|
265
223
|
const wrapper = render(
|
|
266
|
-
<Data handler={fakeHandler}
|
|
224
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
267
225
|
{fakeChildrenFn}
|
|
268
226
|
</Data>,
|
|
269
227
|
);
|
|
270
|
-
// We want to make sure we render the
|
|
228
|
+
// We want to make sure we render the data state so we can
|
|
271
229
|
// see our switch back to loading.
|
|
272
230
|
await act(() => fulfillSpy.mock.results[0].value);
|
|
273
|
-
// Clear out calls so everything is from the props change.
|
|
274
231
|
fulfillSpy.mockClear();
|
|
275
232
|
fakeChildrenFn.mockClear();
|
|
276
233
|
|
|
277
234
|
// Act
|
|
278
235
|
wrapper.rerender(
|
|
279
|
-
<Data handler={
|
|
236
|
+
<Data handler={fakeHandler} requestId="NEW_ID">
|
|
280
237
|
{fakeChildrenFn}
|
|
281
238
|
</Data>,
|
|
282
239
|
);
|
|
@@ -290,112 +247,157 @@ describe("Data", () => {
|
|
|
290
247
|
});
|
|
291
248
|
});
|
|
292
249
|
|
|
293
|
-
it("should
|
|
250
|
+
it("should ignore resolution of pending handler fulfillment when id changes", async () => {
|
|
294
251
|
// Arrange
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
252
|
+
const oldRequest = Promise.resolve("OLD DATA");
|
|
253
|
+
const oldHandler = jest
|
|
254
|
+
.fn()
|
|
255
|
+
.mockReturnValueOnce(oldRequest)
|
|
256
|
+
.mockReturnValue(
|
|
257
|
+
new Promise(() => {
|
|
258
|
+
/*let's have the new request remain pending*/
|
|
259
|
+
}),
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
// Act
|
|
263
|
+
const fakeChildrenFn = jest.fn(() => null);
|
|
264
|
+
const wrapper = render(
|
|
265
|
+
<Data handler={oldHandler} requestId="ID">
|
|
266
|
+
{fakeChildrenFn}
|
|
267
|
+
</Data>,
|
|
298
268
|
);
|
|
269
|
+
wrapper.rerender(
|
|
270
|
+
<Data handler={oldHandler} requestId="NEW_ID">
|
|
271
|
+
{fakeChildrenFn}
|
|
272
|
+
</Data>,
|
|
273
|
+
);
|
|
274
|
+
await act(() => oldRequest);
|
|
275
|
+
|
|
276
|
+
// Assert
|
|
277
|
+
expect(fakeChildrenFn).not.toHaveBeenCalledWith({
|
|
278
|
+
status: "success",
|
|
279
|
+
data: "OLD DATA",
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it("should ignore rejection of pending handler fulfillment when id changes", async () => {
|
|
284
|
+
// Arrange
|
|
285
|
+
const oldRequest = Promise.reject(new Error("BOOM!"));
|
|
286
|
+
const oldHandler = jest
|
|
287
|
+
.fn()
|
|
288
|
+
.mockReturnValueOnce(oldRequest)
|
|
289
|
+
.mockReturnValue(
|
|
290
|
+
new Promise(() => {
|
|
291
|
+
/*let's have the new request remain pending*/
|
|
292
|
+
}),
|
|
293
|
+
);
|
|
299
294
|
|
|
300
|
-
|
|
301
|
-
fulfillRequest: () => Promise.resolve("HELLO!"),
|
|
302
|
-
getKey: (o) => o,
|
|
303
|
-
type: "MY_HANDLER",
|
|
304
|
-
hydrate: true,
|
|
305
|
-
};
|
|
295
|
+
// Act
|
|
306
296
|
const fakeChildrenFn = jest.fn(() => null);
|
|
307
297
|
const wrapper = render(
|
|
308
|
-
<Data handler={
|
|
298
|
+
<Data handler={oldHandler} requestId="ID">
|
|
309
299
|
{fakeChildrenFn}
|
|
310
300
|
</Data>,
|
|
311
301
|
);
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
302
|
+
wrapper.rerender(
|
|
303
|
+
<Data handler={oldHandler} requestId="NEW_ID">
|
|
304
|
+
{fakeChildrenFn}
|
|
305
|
+
</Data>,
|
|
306
|
+
);
|
|
307
|
+
await act(() =>
|
|
308
|
+
oldRequest.catch(() => {
|
|
309
|
+
/*ignore*/
|
|
310
|
+
}),
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
// Assert
|
|
314
|
+
expect(fakeChildrenFn).not.toHaveBeenCalledWith({
|
|
315
|
+
status: "error",
|
|
316
|
+
error: "BOOM!",
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
it("should ignore catastrophic request fulfillment when id changes", async () => {
|
|
321
|
+
// Arrange
|
|
322
|
+
const catastrophe = Promise.reject("CATASTROPHE!");
|
|
323
|
+
jest.spyOn(
|
|
324
|
+
RequestFulfillment.Default,
|
|
325
|
+
"fulfill",
|
|
326
|
+
).mockReturnValueOnce(catastrophe);
|
|
327
|
+
const oldHandler = jest.fn().mockResolvedValue("OLD DATA");
|
|
317
328
|
|
|
318
329
|
// Act
|
|
330
|
+
const fakeChildrenFn = jest.fn(() => null);
|
|
331
|
+
const wrapper = render(
|
|
332
|
+
<Data handler={oldHandler} requestId="ID">
|
|
333
|
+
{fakeChildrenFn}
|
|
334
|
+
</Data>,
|
|
335
|
+
);
|
|
319
336
|
wrapper.rerender(
|
|
320
|
-
<Data handler={
|
|
337
|
+
<Data handler={oldHandler} requestId="NEW_ID">
|
|
321
338
|
{fakeChildrenFn}
|
|
322
339
|
</Data>,
|
|
323
340
|
);
|
|
341
|
+
await act(() =>
|
|
342
|
+
catastrophe.catch(() => {
|
|
343
|
+
/* ignore */
|
|
344
|
+
}),
|
|
345
|
+
);
|
|
324
346
|
|
|
325
347
|
// Assert
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
expect(fakeChildrenFn).toHaveBeenLastCalledWith({
|
|
330
|
-
status: "loading",
|
|
348
|
+
expect(fakeChildrenFn).not.toHaveBeenCalledWith({
|
|
349
|
+
status: "error",
|
|
350
|
+
error: "CATASTROPHE!",
|
|
331
351
|
});
|
|
332
352
|
});
|
|
333
353
|
|
|
334
354
|
describe("with data interceptor", () => {
|
|
335
355
|
it("should request data from interceptor", () => {
|
|
336
356
|
// Arrange
|
|
337
|
-
const
|
|
338
|
-
.fn()
|
|
339
|
-
.mockResolvedValue("data");
|
|
340
|
-
const fakeHandler: IRequestHandler<string, string> = {
|
|
341
|
-
fulfillRequest: fulfillRequestSpy,
|
|
342
|
-
getKey: (o) => o,
|
|
343
|
-
type: "MY_HANDLER",
|
|
344
|
-
hydrate: true,
|
|
345
|
-
};
|
|
357
|
+
const fakeHandler = jest.fn().mockResolvedValue("data");
|
|
346
358
|
const fakeChildrenFn = jest.fn(() => null);
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
|
|
359
|
+
const interceptHandler = jest
|
|
360
|
+
.fn()
|
|
361
|
+
.mockResolvedValue("INTERCEPTED DATA");
|
|
350
362
|
|
|
351
363
|
// Act
|
|
352
364
|
render(
|
|
353
365
|
<InterceptData
|
|
354
|
-
|
|
355
|
-
|
|
366
|
+
requestId="ID"
|
|
367
|
+
handler={interceptHandler}
|
|
356
368
|
>
|
|
357
|
-
<Data handler={fakeHandler}
|
|
369
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
358
370
|
{fakeChildrenFn}
|
|
359
371
|
</Data>
|
|
360
372
|
</InterceptData>,
|
|
361
373
|
);
|
|
362
374
|
|
|
363
375
|
// Assert
|
|
364
|
-
expect(
|
|
365
|
-
expect(
|
|
366
|
-
expect(fulfillRequestSpy).not.toHaveBeenCalled();
|
|
376
|
+
expect(interceptHandler).toHaveBeenCalledTimes(1);
|
|
377
|
+
expect(fakeHandler).not.toHaveBeenCalled();
|
|
367
378
|
});
|
|
368
379
|
|
|
369
380
|
it("should invoke handler method if interceptor method returns null", () => {
|
|
370
381
|
// Arrange
|
|
371
|
-
const
|
|
372
|
-
.fn()
|
|
373
|
-
.mockResolvedValue("data");
|
|
374
|
-
const fakeHandler: IRequestHandler<string, string> = {
|
|
375
|
-
fulfillRequest: fulfillRequestSpy,
|
|
376
|
-
getKey: (o) => o,
|
|
377
|
-
type: "MY_HANDLER",
|
|
378
|
-
hydrate: true,
|
|
379
|
-
};
|
|
382
|
+
const fakeHandler = jest.fn().mockResolvedValue("data");
|
|
380
383
|
const fakeChildrenFn = jest.fn(() => null);
|
|
381
|
-
const
|
|
384
|
+
const interceptHandler = jest.fn(() => null);
|
|
382
385
|
|
|
383
386
|
// Act
|
|
384
387
|
render(
|
|
385
388
|
<InterceptData
|
|
386
|
-
handler={
|
|
387
|
-
|
|
389
|
+
handler={interceptHandler}
|
|
390
|
+
requestId="ID"
|
|
388
391
|
>
|
|
389
|
-
<Data handler={fakeHandler}
|
|
392
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
390
393
|
{fakeChildrenFn}
|
|
391
394
|
</Data>
|
|
392
395
|
</InterceptData>,
|
|
393
396
|
);
|
|
394
397
|
|
|
395
398
|
// Assert
|
|
396
|
-
expect(
|
|
397
|
-
expect(
|
|
398
|
-
expect(fulfillRequestSpy).toHaveBeenCalled();
|
|
399
|
+
expect(interceptHandler).toHaveBeenCalledTimes(1);
|
|
400
|
+
expect(fakeHandler).toHaveBeenCalledTimes(1);
|
|
399
401
|
});
|
|
400
402
|
});
|
|
401
403
|
});
|
|
@@ -406,24 +408,24 @@ describe("Data", () => {
|
|
|
406
408
|
* Each of these test cases will start out with some cached data
|
|
407
409
|
* retrieved.
|
|
408
410
|
*/
|
|
409
|
-
jest.spyOn(
|
|
411
|
+
jest.spyOn(
|
|
412
|
+
SsrCache.Default,
|
|
413
|
+
"getEntry",
|
|
414
|
+
// Fake once because that's how the cache would work,
|
|
415
|
+
// deleting the hydrated value as soon as it was used.
|
|
416
|
+
).mockReturnValueOnce({
|
|
410
417
|
data: "YAY! DATA!",
|
|
411
418
|
});
|
|
412
419
|
});
|
|
413
420
|
|
|
414
421
|
it("should render first time with the cached data", () => {
|
|
415
422
|
// Arrange
|
|
416
|
-
const fakeHandler
|
|
417
|
-
fulfillRequest: () => Promise.resolve("data"),
|
|
418
|
-
getKey: (o) => o,
|
|
419
|
-
type: "MY_HANDLER",
|
|
420
|
-
hydrate: true,
|
|
421
|
-
};
|
|
423
|
+
const fakeHandler = () => Promise.resolve("data");
|
|
422
424
|
const fakeChildrenFn = jest.fn(() => null);
|
|
423
425
|
|
|
424
426
|
// Act
|
|
425
427
|
render(
|
|
426
|
-
<Data handler={fakeHandler}
|
|
428
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
427
429
|
{fakeChildrenFn}
|
|
428
430
|
</Data>,
|
|
429
431
|
);
|
|
@@ -434,6 +436,144 @@ describe("Data", () => {
|
|
|
434
436
|
data: "YAY! DATA!",
|
|
435
437
|
});
|
|
436
438
|
});
|
|
439
|
+
|
|
440
|
+
it("should retain old data while reloading if showOldDataWhileLoading is true", async () => {
|
|
441
|
+
// Arrange
|
|
442
|
+
const response1 = Promise.resolve("data1");
|
|
443
|
+
const response2 = Promise.resolve("data2");
|
|
444
|
+
const fakeHandler1 = () => response1;
|
|
445
|
+
const fakeHandler2 = () => response2;
|
|
446
|
+
const fakeChildrenFn = jest.fn(() => null);
|
|
447
|
+
|
|
448
|
+
// Act
|
|
449
|
+
const wrapper = render(
|
|
450
|
+
<Data
|
|
451
|
+
handler={fakeHandler1}
|
|
452
|
+
requestId="ID"
|
|
453
|
+
showOldDataWhileLoading={false}
|
|
454
|
+
>
|
|
455
|
+
{fakeChildrenFn}
|
|
456
|
+
</Data>,
|
|
457
|
+
);
|
|
458
|
+
wrapper.rerender(
|
|
459
|
+
<Data
|
|
460
|
+
handler={fakeHandler2}
|
|
461
|
+
requestId="ID"
|
|
462
|
+
showOldDataWhileLoading={true}
|
|
463
|
+
>
|
|
464
|
+
{fakeChildrenFn}
|
|
465
|
+
</Data>,
|
|
466
|
+
);
|
|
467
|
+
|
|
468
|
+
// Assert
|
|
469
|
+
expect(fakeChildrenFn).not.toHaveBeenCalledWith({
|
|
470
|
+
status: "loading",
|
|
471
|
+
});
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
it("should not request data when alwaysRequestOnHydration is false and cache has a valid data result", () => {
|
|
475
|
+
// Arrange
|
|
476
|
+
const fakeHandler = jest.fn().mockResolvedValue("data");
|
|
477
|
+
const fakeChildrenFn = jest.fn(() => null);
|
|
478
|
+
|
|
479
|
+
// Act
|
|
480
|
+
render(
|
|
481
|
+
<Data
|
|
482
|
+
handler={fakeHandler}
|
|
483
|
+
requestId="ID"
|
|
484
|
+
alwaysRequestOnHydration={false}
|
|
485
|
+
>
|
|
486
|
+
{fakeChildrenFn}
|
|
487
|
+
</Data>,
|
|
488
|
+
);
|
|
489
|
+
|
|
490
|
+
// Assert
|
|
491
|
+
expect(fakeHandler).not.toHaveBeenCalled();
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
it("should request data if cached data value is valid but alwaysRequestOnHydration is true", () => {
|
|
495
|
+
// Arrange
|
|
496
|
+
const fakeHandler = jest.fn().mockResolvedValue("data");
|
|
497
|
+
const fakeChildrenFn = jest.fn(() => null);
|
|
498
|
+
|
|
499
|
+
// Act
|
|
500
|
+
render(
|
|
501
|
+
<Data
|
|
502
|
+
handler={fakeHandler}
|
|
503
|
+
requestId="ID"
|
|
504
|
+
alwaysRequestOnHydration={true}
|
|
505
|
+
>
|
|
506
|
+
{fakeChildrenFn}
|
|
507
|
+
</Data>,
|
|
508
|
+
);
|
|
509
|
+
|
|
510
|
+
// Assert
|
|
511
|
+
expect(fakeHandler).toHaveBeenCalledTimes(1);
|
|
512
|
+
});
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
describe("with cached abort", () => {
|
|
516
|
+
beforeEach(() => {
|
|
517
|
+
/**
|
|
518
|
+
* Each of these test cases will start out with a cached abort.
|
|
519
|
+
*/
|
|
520
|
+
jest.spyOn(
|
|
521
|
+
SsrCache.Default,
|
|
522
|
+
"getEntry",
|
|
523
|
+
// Fake once because that's how the cache would work,
|
|
524
|
+
// deleting the hydrated value as soon as it was used.
|
|
525
|
+
).mockReturnValueOnce({
|
|
526
|
+
data: null,
|
|
527
|
+
});
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
it("should request data if cached data value is null (i.e. represents an aborted request)", () => {
|
|
531
|
+
// Arrange
|
|
532
|
+
const fakeHandler = jest.fn().mockResolvedValue("data");
|
|
533
|
+
const fakeChildrenFn = jest.fn(() => null);
|
|
534
|
+
|
|
535
|
+
// Act
|
|
536
|
+
render(
|
|
537
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
538
|
+
{fakeChildrenFn}
|
|
539
|
+
</Data>,
|
|
540
|
+
);
|
|
541
|
+
|
|
542
|
+
// Assert
|
|
543
|
+
expect(fakeHandler).toHaveBeenCalledTimes(1);
|
|
544
|
+
});
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
describe("with cached error", () => {
|
|
548
|
+
beforeEach(() => {
|
|
549
|
+
/**
|
|
550
|
+
* Each of these test cases will start out with a cached error.
|
|
551
|
+
*/
|
|
552
|
+
jest.spyOn(
|
|
553
|
+
SsrCache.Default,
|
|
554
|
+
"getEntry",
|
|
555
|
+
// Fake once because that's how the cache would work,
|
|
556
|
+
// deleting the hydrated value as soon as it was used.
|
|
557
|
+
).mockReturnValueOnce({
|
|
558
|
+
error: "BOO! ERROR!",
|
|
559
|
+
});
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
it("should always request data if there's a cached error", () => {
|
|
563
|
+
// Arrange
|
|
564
|
+
const fakeHandler = jest.fn().mockResolvedValue("data");
|
|
565
|
+
const fakeChildrenFn = jest.fn(() => null);
|
|
566
|
+
|
|
567
|
+
// Act
|
|
568
|
+
render(
|
|
569
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
570
|
+
{fakeChildrenFn}
|
|
571
|
+
</Data>,
|
|
572
|
+
);
|
|
573
|
+
|
|
574
|
+
// Assert
|
|
575
|
+
expect(fakeHandler).toHaveBeenCalledTimes(1);
|
|
576
|
+
});
|
|
437
577
|
});
|
|
438
578
|
});
|
|
439
579
|
|
|
@@ -448,46 +588,33 @@ describe("Data", () => {
|
|
|
448
588
|
* Each of these test cases will never have cached data
|
|
449
589
|
* retrieved.
|
|
450
590
|
*/
|
|
451
|
-
jest.spyOn(
|
|
452
|
-
null,
|
|
453
|
-
);
|
|
591
|
+
jest.spyOn(SsrCache.Default, "getEntry").mockReturnValue(null);
|
|
454
592
|
});
|
|
455
593
|
|
|
456
594
|
it("should not request data", () => {
|
|
457
595
|
// Arrange
|
|
458
|
-
const
|
|
459
|
-
const fakeHandler: IRequestHandler<string, string> = {
|
|
460
|
-
fulfillRequest: fulfillRequestSpy,
|
|
461
|
-
getKey: (o) => o,
|
|
462
|
-
type: "MY_HANDLER",
|
|
463
|
-
hydrate: true,
|
|
464
|
-
};
|
|
596
|
+
const fakeHandler = jest.fn().mockResolvedValue("data");
|
|
465
597
|
const fakeChildrenFn = jest.fn(() => null);
|
|
466
598
|
|
|
467
599
|
// Act
|
|
468
600
|
ReactDOMServer.renderToString(
|
|
469
|
-
<Data handler={fakeHandler}
|
|
601
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
470
602
|
{fakeChildrenFn}
|
|
471
603
|
</Data>,
|
|
472
604
|
);
|
|
473
605
|
|
|
474
606
|
// Assert
|
|
475
|
-
expect(
|
|
607
|
+
expect(fakeHandler).not.toHaveBeenCalled();
|
|
476
608
|
});
|
|
477
609
|
|
|
478
610
|
it("should render children with loading", () => {
|
|
479
611
|
// Arrange
|
|
480
|
-
const fakeHandler
|
|
481
|
-
fulfillRequest: () => Promise.resolve("data"),
|
|
482
|
-
getKey: (o) => o,
|
|
483
|
-
type: "MY_HANDLER",
|
|
484
|
-
hydrate: true,
|
|
485
|
-
};
|
|
612
|
+
const fakeHandler = jest.fn().mockResolvedValue("data");
|
|
486
613
|
const fakeChildrenFn = jest.fn(() => null);
|
|
487
614
|
|
|
488
615
|
// Act
|
|
489
616
|
ReactDOMServer.renderToString(
|
|
490
|
-
<Data handler={fakeHandler}
|
|
617
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
491
618
|
{fakeChildrenFn}
|
|
492
619
|
</Data>,
|
|
493
620
|
);
|
|
@@ -504,59 +631,50 @@ describe("Data", () => {
|
|
|
504
631
|
RequestTracker.Default,
|
|
505
632
|
"trackDataRequest",
|
|
506
633
|
);
|
|
507
|
-
const fakeHandler
|
|
508
|
-
fulfillRequest: () => Promise.resolve("data"),
|
|
509
|
-
getKey: (o) => o,
|
|
510
|
-
type: "MY_HANDLER",
|
|
511
|
-
hydrate: true,
|
|
512
|
-
};
|
|
634
|
+
const fakeHandler = jest.fn().mockResolvedValue("data");
|
|
513
635
|
const fakeChildrenFn = jest.fn(() => null);
|
|
514
636
|
|
|
515
637
|
// Act
|
|
516
638
|
ReactDOMServer.renderToString(
|
|
517
639
|
<TrackData>
|
|
518
|
-
<Data handler={fakeHandler}
|
|
640
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
519
641
|
{fakeChildrenFn}
|
|
520
642
|
</Data>
|
|
521
643
|
</TrackData>,
|
|
522
644
|
);
|
|
523
645
|
|
|
524
646
|
// Assert
|
|
525
|
-
expect(trackSpy).toHaveBeenCalledWith(
|
|
647
|
+
expect(trackSpy).toHaveBeenCalledWith(
|
|
648
|
+
"ID",
|
|
649
|
+
expect.any(Function),
|
|
650
|
+
true,
|
|
651
|
+
);
|
|
526
652
|
});
|
|
527
653
|
|
|
528
654
|
describe("with data interceptor", () => {
|
|
529
655
|
it("should not request data from the interceptor", () => {
|
|
530
656
|
// Arrange
|
|
531
|
-
const
|
|
532
|
-
.fn()
|
|
533
|
-
.mockResolvedValue("data");
|
|
534
|
-
const fakeHandler: IRequestHandler<string, string> = {
|
|
535
|
-
fulfillRequest: fulfillRequestSpy,
|
|
536
|
-
getKey: (o) => o,
|
|
537
|
-
type: "MY_HANDLER",
|
|
538
|
-
hydrate: true,
|
|
539
|
-
};
|
|
657
|
+
const fakeHandler = jest.fn().mockResolvedValue("data");
|
|
540
658
|
const fakeChildrenFn = jest.fn(() => null);
|
|
541
|
-
const
|
|
659
|
+
const interceptedHandler = jest.fn(() =>
|
|
542
660
|
Promise.resolve("DATA!"),
|
|
543
661
|
);
|
|
544
662
|
|
|
545
663
|
// Act
|
|
546
664
|
ReactDOMServer.renderToString(
|
|
547
665
|
<InterceptData
|
|
548
|
-
handler={
|
|
549
|
-
|
|
666
|
+
handler={interceptedHandler}
|
|
667
|
+
requestId="ID"
|
|
550
668
|
>
|
|
551
|
-
<Data handler={fakeHandler}
|
|
669
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
552
670
|
{fakeChildrenFn}
|
|
553
671
|
</Data>
|
|
554
672
|
</InterceptData>,
|
|
555
673
|
);
|
|
556
674
|
|
|
557
675
|
// Assert
|
|
558
|
-
expect(
|
|
559
|
-
expect(
|
|
676
|
+
expect(fakeHandler).not.toHaveBeenCalled();
|
|
677
|
+
expect(interceptedHandler).not.toHaveBeenCalled();
|
|
560
678
|
});
|
|
561
679
|
|
|
562
680
|
it("should invoke the tracking call", () => {
|
|
@@ -565,30 +683,20 @@ describe("Data", () => {
|
|
|
565
683
|
RequestTracker.Default,
|
|
566
684
|
"trackDataRequest",
|
|
567
685
|
);
|
|
568
|
-
const fakeHandler =
|
|
569
|
-
fulfillRequest: () => Promise.resolve("data"),
|
|
570
|
-
getKey: (o) => o,
|
|
571
|
-
type: "MY_HANDLER",
|
|
572
|
-
hydrate: true,
|
|
573
|
-
};
|
|
686
|
+
const fakeHandler = jest.fn().mockResolvedValue("data");
|
|
574
687
|
const fakeChildrenFn = jest.fn(() => null);
|
|
575
|
-
const
|
|
576
|
-
|
|
577
|
-
|
|
688
|
+
const interceptedHandler = jest
|
|
689
|
+
.fn()
|
|
690
|
+
.mockResolvedValue("INTERCEPTED");
|
|
578
691
|
|
|
579
692
|
// Act
|
|
580
693
|
ReactDOMServer.renderToString(
|
|
581
694
|
<TrackData>
|
|
582
695
|
<InterceptData
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
string,
|
|
586
|
-
string,
|
|
587
|
-
>)
|
|
588
|
-
}
|
|
589
|
-
fulfillRequest={fulfillRequestFn}
|
|
696
|
+
requestId="ID"
|
|
697
|
+
handler={interceptedHandler}
|
|
590
698
|
>
|
|
591
|
-
<Data handler={fakeHandler}
|
|
699
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
592
700
|
{fakeChildrenFn}
|
|
593
701
|
</Data>
|
|
594
702
|
</InterceptData>
|
|
@@ -597,13 +705,9 @@ describe("Data", () => {
|
|
|
597
705
|
|
|
598
706
|
// Assert
|
|
599
707
|
expect(trackSpy).toHaveBeenCalledWith(
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
type: "MY_HANDLER",
|
|
604
|
-
hydrate: true,
|
|
605
|
-
},
|
|
606
|
-
"options",
|
|
708
|
+
"ID",
|
|
709
|
+
expect.any(Function),
|
|
710
|
+
true,
|
|
607
711
|
);
|
|
608
712
|
});
|
|
609
713
|
});
|
|
@@ -615,46 +719,35 @@ describe("Data", () => {
|
|
|
615
719
|
* Each of these test cases will start out with some cached data
|
|
616
720
|
* retrieved.
|
|
617
721
|
*/
|
|
618
|
-
jest.spyOn(
|
|
722
|
+
jest.spyOn(SsrCache.Default, "getEntry").mockReturnValue({
|
|
619
723
|
data: "YAY! DATA!",
|
|
620
724
|
});
|
|
621
725
|
});
|
|
622
726
|
|
|
623
727
|
it("should not request data", () => {
|
|
624
728
|
// Arrange
|
|
625
|
-
const
|
|
626
|
-
const fakeHandler: IRequestHandler<string, string> = {
|
|
627
|
-
fulfillRequest: fulfillRequestSpy,
|
|
628
|
-
getKey: (o) => o,
|
|
629
|
-
type: "MY_HANDLER",
|
|
630
|
-
hydrate: true,
|
|
631
|
-
};
|
|
729
|
+
const fakeHandler = jest.fn().mockResolvedValue("data");
|
|
632
730
|
const fakeChildrenFn = jest.fn(() => null);
|
|
633
731
|
|
|
634
732
|
// Act
|
|
635
733
|
ReactDOMServer.renderToString(
|
|
636
|
-
<Data handler={fakeHandler}
|
|
734
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
637
735
|
{fakeChildrenFn}
|
|
638
736
|
</Data>,
|
|
639
737
|
);
|
|
640
738
|
|
|
641
739
|
// Assert
|
|
642
|
-
expect(
|
|
740
|
+
expect(fakeHandler).not.toHaveBeenCalled();
|
|
643
741
|
});
|
|
644
742
|
|
|
645
743
|
it("should render children with data", () => {
|
|
646
744
|
// Arrange
|
|
647
|
-
const fakeHandler
|
|
648
|
-
fulfillRequest: () => Promise.resolve("data"),
|
|
649
|
-
getKey: (o) => o,
|
|
650
|
-
type: "MY_HANDLER",
|
|
651
|
-
hydrate: true,
|
|
652
|
-
};
|
|
745
|
+
const fakeHandler = jest.fn().mockResolvedValue("data");
|
|
653
746
|
const fakeChildrenFn = jest.fn(() => null);
|
|
654
747
|
|
|
655
748
|
// Act
|
|
656
749
|
ReactDOMServer.renderToString(
|
|
657
|
-
<Data handler={fakeHandler}
|
|
750
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
658
751
|
{fakeChildrenFn}
|
|
659
752
|
</Data>,
|
|
660
753
|
);
|
|
@@ -668,20 +761,15 @@ describe("Data", () => {
|
|
|
668
761
|
|
|
669
762
|
it("should render children with error", () => {
|
|
670
763
|
// Arrange
|
|
671
|
-
jest.spyOn(
|
|
764
|
+
jest.spyOn(SsrCache.Default, "getEntry").mockReturnValue({
|
|
672
765
|
error: "OH NO! IT GO BOOM",
|
|
673
766
|
});
|
|
674
|
-
const fakeHandler
|
|
675
|
-
fulfillRequest: () => Promise.resolve("data"),
|
|
676
|
-
getKey: (o) => o,
|
|
677
|
-
type: "MY_HANDLER",
|
|
678
|
-
hydrate: true,
|
|
679
|
-
};
|
|
767
|
+
const fakeHandler = jest.fn().mockResolvedValue("data");
|
|
680
768
|
const fakeChildrenFn = jest.fn(() => null);
|
|
681
769
|
|
|
682
770
|
// Act
|
|
683
771
|
ReactDOMServer.renderToString(
|
|
684
|
-
<Data handler={fakeHandler}
|
|
772
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
685
773
|
{fakeChildrenFn}
|
|
686
774
|
</Data>,
|
|
687
775
|
);
|
|
@@ -699,18 +787,13 @@ describe("Data", () => {
|
|
|
699
787
|
RequestTracker.Default,
|
|
700
788
|
"trackDataRequest",
|
|
701
789
|
);
|
|
702
|
-
const fakeHandler
|
|
703
|
-
fulfillRequest: () => Promise.resolve("data"),
|
|
704
|
-
getKey: (o) => o,
|
|
705
|
-
type: "MY_HANDLER",
|
|
706
|
-
hydrate: true,
|
|
707
|
-
};
|
|
790
|
+
const fakeHandler = jest.fn().mockResolvedValue("data");
|
|
708
791
|
const fakeChildrenFn = jest.fn(() => null);
|
|
709
792
|
|
|
710
793
|
// Act
|
|
711
794
|
ReactDOMServer.renderToString(
|
|
712
795
|
<TrackData>
|
|
713
|
-
<Data handler={fakeHandler}
|
|
796
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
714
797
|
{fakeChildrenFn}
|
|
715
798
|
</Data>
|
|
716
799
|
</TrackData>,
|
|
@@ -726,35 +809,27 @@ describe("Data", () => {
|
|
|
726
809
|
describe("with data interceptor", () => {
|
|
727
810
|
it("should not request data from interceptor", () => {
|
|
728
811
|
// Arrange
|
|
729
|
-
const
|
|
730
|
-
.fn()
|
|
731
|
-
.mockResolvedValue("data");
|
|
732
|
-
const fakeHandler: IRequestHandler<string, string> = {
|
|
733
|
-
fulfillRequest: fulfillRequestSpy,
|
|
734
|
-
getKey: (o) => o,
|
|
735
|
-
type: "MY_HANDLER",
|
|
736
|
-
hydrate: true,
|
|
737
|
-
};
|
|
812
|
+
const fakeHandler = jest.fn().mockResolvedValue("data");
|
|
738
813
|
const fakeChildrenFn = jest.fn(() => null);
|
|
739
|
-
const
|
|
740
|
-
|
|
741
|
-
|
|
814
|
+
const interceptHandler = jest
|
|
815
|
+
.fn()
|
|
816
|
+
.mockResolvedValue("INTERCEPTED");
|
|
742
817
|
|
|
743
818
|
// Act
|
|
744
819
|
ReactDOMServer.renderToString(
|
|
745
820
|
<InterceptData
|
|
746
|
-
handler={
|
|
747
|
-
|
|
821
|
+
handler={interceptHandler}
|
|
822
|
+
requestId="ID"
|
|
748
823
|
>
|
|
749
|
-
<Data handler={fakeHandler}
|
|
824
|
+
<Data handler={fakeHandler} requestId="ID">
|
|
750
825
|
{fakeChildrenFn}
|
|
751
826
|
</Data>
|
|
752
827
|
</InterceptData>,
|
|
753
828
|
);
|
|
754
829
|
|
|
755
830
|
// Assert
|
|
756
|
-
expect(
|
|
757
|
-
expect(
|
|
831
|
+
expect(fakeHandler).not.toHaveBeenCalled();
|
|
832
|
+
expect(interceptHandler).not.toHaveBeenCalled();
|
|
758
833
|
});
|
|
759
834
|
});
|
|
760
835
|
});
|