@khanacademy/wonder-blocks-data 2.3.3 → 3.1.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.
Files changed (50) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/es/index.js +365 -429
  3. package/dist/index.js +455 -461
  4. package/docs.md +19 -13
  5. package/package.json +6 -6
  6. package/src/__tests__/__snapshots__/generated-snapshot.test.js.snap +40 -160
  7. package/src/__tests__/generated-snapshot.test.js +15 -195
  8. package/src/components/__tests__/data.test.js +159 -965
  9. package/src/components/__tests__/gql-router.test.js +64 -0
  10. package/src/components/__tests__/intercept-data.test.js +9 -66
  11. package/src/components/__tests__/track-data.test.js +6 -5
  12. package/src/components/data.js +9 -119
  13. package/src/components/data.md +38 -60
  14. package/src/components/gql-router.js +66 -0
  15. package/src/components/intercept-context.js +2 -3
  16. package/src/components/intercept-data.js +2 -34
  17. package/src/components/intercept-data.md +7 -105
  18. package/src/hooks/__tests__/use-data.test.js +826 -0
  19. package/src/hooks/__tests__/use-gql.test.js +233 -0
  20. package/src/hooks/use-data.js +143 -0
  21. package/src/hooks/use-gql.js +75 -0
  22. package/src/index.js +7 -9
  23. package/src/util/__tests__/get-gql-data-from-response.test.js +187 -0
  24. package/src/util/__tests__/memory-cache.test.js +134 -35
  25. package/src/util/__tests__/request-fulfillment.test.js +21 -36
  26. package/src/util/__tests__/request-handler.test.js +30 -30
  27. package/src/util/__tests__/request-tracking.test.js +29 -30
  28. package/src/util/__tests__/response-cache.test.js +521 -561
  29. package/src/util/__tests__/result-from-cache-entry.test.js +68 -0
  30. package/src/util/get-gql-data-from-response.js +69 -0
  31. package/src/util/gql-error.js +36 -0
  32. package/src/util/gql-router-context.js +6 -0
  33. package/src/util/gql-types.js +60 -0
  34. package/src/util/memory-cache.js +20 -15
  35. package/src/util/request-fulfillment.js +4 -0
  36. package/src/util/request-handler.js +4 -28
  37. package/src/util/request-handler.md +0 -32
  38. package/src/util/request-tracking.js +2 -3
  39. package/src/util/response-cache.js +50 -110
  40. package/src/util/result-from-cache-entry.js +38 -0
  41. package/src/util/types.js +14 -35
  42. package/LICENSE +0 -21
  43. package/src/components/__tests__/intercept-cache.test.js +0 -124
  44. package/src/components/__tests__/internal-data.test.js +0 -1030
  45. package/src/components/intercept-cache.js +0 -79
  46. package/src/components/intercept-cache.md +0 -103
  47. package/src/components/internal-data.js +0 -219
  48. package/src/util/__tests__/no-cache.test.js +0 -112
  49. package/src/util/no-cache.js +0 -66
  50. package/src/util/no-cache.md +0 -66
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable max-lines */
2
2
  // @flow
3
3
  import * as React from "react";
4
- import {mount, shallow} from "enzyme";
4
+ import {render, act} from "@testing-library/react";
5
5
 
6
6
  // eslint-disable-next-line import/extensions
7
7
  import * as ReactDOMServer from "react-dom/server";
@@ -11,7 +11,6 @@ import TrackData from "../track-data.js";
11
11
  import {RequestFulfillment} from "../../util/request-fulfillment.js";
12
12
  import {ResponseCache} from "../../util/response-cache.js";
13
13
  import {RequestTracker} from "../../util/request-tracking.js";
14
- import InterceptCache from "../intercept-cache.js";
15
14
  import InterceptData from "../intercept-data.js";
16
15
  import Data from "../data.js";
17
16
 
@@ -43,12 +42,13 @@ describe("Data", () => {
43
42
  describe("without cached data", () => {
44
43
  beforeEach(() => {
45
44
  /**
46
- * Each of these test cases will never have cached data
47
- * retrieved.
45
+ * Each of these test cases will not have cached data to be
46
+ * retrieved in the beginning.
48
47
  */
49
- jest.spyOn(ResponseCache.Default, "getEntry").mockReturnValue(
50
- null,
51
- );
48
+ jest.spyOn(
49
+ ResponseCache.Default,
50
+ "getEntry",
51
+ ).mockReturnValueOnce(null);
52
52
  });
53
53
 
54
54
  it("should make request for data on construction", () => {
@@ -59,15 +59,13 @@ describe("Data", () => {
59
59
  const fakeHandler: IRequestHandler<string, string> = {
60
60
  fulfillRequest: fulfillRequestSpy,
61
61
  getKey: (o) => o,
62
- shouldRefreshCache: () => false,
63
62
  type: "MY_HANDLER",
64
- cache: null,
65
63
  hydrate: true,
66
64
  };
67
65
  const fakeChildrenFn = jest.fn(() => null);
68
66
 
69
67
  // Act
70
- mount(
68
+ render(
71
69
  <Data handler={fakeHandler} options={"options"}>
72
70
  {fakeChildrenFn}
73
71
  </Data>,
@@ -83,26 +81,22 @@ describe("Data", () => {
83
81
  const fakeHandler: IRequestHandler<string, string> = {
84
82
  fulfillRequest: () => Promise.resolve("data"),
85
83
  getKey: (o) => o,
86
- shouldRefreshCache: () => false,
87
84
  type: "MY_HANDLER",
88
- cache: null,
89
85
  hydrate: true,
90
86
  };
91
87
  const fakeChildrenFn = jest.fn(() => null);
92
88
 
93
89
  // Act
94
- mount(
90
+ render(
95
91
  <Data handler={fakeHandler} options={"options"}>
96
92
  {fakeChildrenFn}
97
93
  </Data>,
98
94
  );
99
95
 
100
96
  // Assert
101
- expect(fakeChildrenFn).toHaveBeenCalledWith(
102
- expect.objectContaining({
103
- loading: true,
104
- }),
105
- );
97
+ expect(fakeChildrenFn).toHaveBeenCalledWith({
98
+ status: "loading",
99
+ });
106
100
  });
107
101
 
108
102
  it("should share single request across all uses", () => {
@@ -113,15 +107,13 @@ describe("Data", () => {
113
107
  const fakeHandler: IRequestHandler<string, string> = {
114
108
  fulfillRequest: fulfillRequestSpy,
115
109
  getKey: (o) => o,
116
- shouldRefreshCache: () => false,
117
110
  type: "MY_HANDLER",
118
- cache: null,
119
111
  hydrate: true,
120
112
  };
121
113
  const fakeChildrenFn = jest.fn(() => null);
122
114
 
123
115
  // Act
124
- mount(
116
+ render(
125
117
  <View>
126
118
  <Data handler={fakeHandler} options={"options"}>
127
119
  {fakeChildrenFn}
@@ -137,7 +129,7 @@ describe("Data", () => {
137
129
  expect(fulfillRequestSpy).toHaveBeenCalledTimes(1);
138
130
  });
139
131
 
140
- it("should render with an error if the request resolves to an error", async () => {
132
+ it("should render with an error if the request rejects to an error", async () => {
141
133
  // Arrange
142
134
  const fulfillSpy = jest.spyOn(
143
135
  RequestFulfillment.Default,
@@ -147,15 +139,13 @@ describe("Data", () => {
147
139
  const fakeHandler: IRequestHandler<string, string> = {
148
140
  fulfillRequest: () => Promise.reject(new Error("OH NOES!")),
149
141
  getKey: (o) => o,
150
- shouldRefreshCache: () => false,
151
142
  type: "MY_HANDLER",
152
- cache: null,
153
143
  hydrate: true,
154
144
  };
155
145
  const fakeChildrenFn = jest.fn(() => null);
156
146
 
157
147
  // Act
158
- mount(
148
+ render(
159
149
  <Data handler={fakeHandler} options={"options"}>
160
150
  {fakeChildrenFn}
161
151
  </Data>,
@@ -163,12 +153,12 @@ describe("Data", () => {
163
153
  /**
164
154
  * We wait for the fulfillment to resolve.
165
155
  */
166
- await fulfillSpy.mock.results[0].value;
156
+ await act(() => fulfillSpy.mock.results[0].value);
167
157
 
168
158
  // Assert
169
159
  expect(fakeChildrenFn).toHaveBeenCalledTimes(2);
170
160
  expect(fakeChildrenFn).toHaveBeenLastCalledWith({
171
- loading: false,
161
+ status: "error",
172
162
  error: "OH NOES!",
173
163
  });
174
164
  });
@@ -183,15 +173,13 @@ describe("Data", () => {
183
173
  const fakeHandler: IRequestHandler<string, string> = {
184
174
  fulfillRequest: () => Promise.resolve("YAY! DATA!"),
185
175
  getKey: (o) => o,
186
- shouldRefreshCache: () => false,
187
176
  type: "MY_HANDLER",
188
- cache: null,
189
177
  hydrate: true,
190
178
  };
191
179
  const fakeChildrenFn = jest.fn(() => null);
192
180
 
193
181
  // Act
194
- mount(
182
+ render(
195
183
  <Data handler={fakeHandler} options={"options"}>
196
184
  {fakeChildrenFn}
197
185
  </Data>,
@@ -199,12 +187,12 @@ describe("Data", () => {
199
187
  /**
200
188
  * We wait for the fulfillment to resolve.
201
189
  */
202
- await fulfillSpy.mock.results[0].value;
190
+ await act(() => fulfillSpy.mock.results[0].value);
203
191
 
204
192
  // Assert
205
193
  expect(fakeChildrenFn).toHaveBeenCalledTimes(2);
206
194
  expect(fakeChildrenFn).toHaveBeenLastCalledWith({
207
- loading: false,
195
+ status: "success",
208
196
  data: "YAY! DATA!",
209
197
  });
210
198
  });
@@ -218,9 +206,7 @@ describe("Data", () => {
218
206
  const fakeHandler: IRequestHandler<string, string> = {
219
207
  fulfillRequest: () => Promise.resolve("YAY!"),
220
208
  getKey: (o) => o,
221
- shouldRefreshCache: () => false,
222
209
  type: "MY_HANDLER",
223
- cache: null,
224
210
  hydrate: true,
225
211
  };
226
212
  const fakeChildrenFn = jest.fn(() => null);
@@ -231,7 +217,7 @@ describe("Data", () => {
231
217
  });
232
218
 
233
219
  // Act
234
- mount(
220
+ render(
235
221
  <Data handler={fakeHandler} options={"options"}>
236
222
  {fakeChildrenFn}
237
223
  </Data>,
@@ -239,12 +225,14 @@ describe("Data", () => {
239
225
  /**
240
226
  * We wait for the fulfillment to reject.
241
227
  */
242
- await fulfillSpy.mock.results[0].value.catch(() => {});
228
+ await act(() =>
229
+ fulfillSpy.mock.results[0].value.catch(() => {}),
230
+ );
243
231
 
244
232
  // Assert
245
233
  expect(fakeChildrenFn).toHaveBeenCalledTimes(2);
246
234
  expect(fakeChildrenFn).toHaveBeenLastCalledWith({
247
- loading: false,
235
+ status: "error",
248
236
  error: "CATASTROPHE!",
249
237
  });
250
238
  expect(consoleSpy).toHaveBeenCalledWith(
@@ -252,50 +240,53 @@ describe("Data", () => {
252
240
  );
253
241
  });
254
242
 
255
- it("should start loading if the handler changes and request not cached", async () => {
243
+ it("should render loading if the handler changes and request not cached", async () => {
256
244
  // Arrange
257
245
  const fulfillSpy = jest.spyOn(
258
246
  RequestFulfillment.Default,
259
247
  "fulfill",
260
248
  );
261
-
262
249
  const fakeHandler: IRequestHandler<string, string> = {
263
250
  fulfillRequest: () => Promise.reject(new Error("OH NOES!")),
264
251
  getKey: (o) => o,
265
- shouldRefreshCache: () => false,
266
252
  type: "TYPE1",
267
- cache: null,
268
253
  hydrate: true,
269
254
  };
270
255
  const fakeHandler2: IRequestHandler<string, string> = {
271
- fulfillRequest: () => new Promise(() => {}),
256
+ fulfillRequest: () =>
257
+ new Promise(() => {
258
+ /*pending*/
259
+ }),
272
260
  getKey: (o) => o,
273
- shouldRefreshCache: () => false,
274
261
  type: "TYPE2",
275
- cache: null,
276
262
  hydrate: true,
277
263
  };
278
264
  const fakeChildrenFn = jest.fn(() => null);
279
- const wrapper = mount(
265
+ const wrapper = render(
280
266
  <Data handler={fakeHandler} options={"options"}>
281
267
  {fakeChildrenFn}
282
268
  </Data>,
283
269
  );
284
- // Make sure we render as laoded.
285
- await fulfillSpy.mock.results[0].value;
270
+ // We want to make sure we render the error state so we can
271
+ // see our switch back to loading.
272
+ await act(() => fulfillSpy.mock.results[0].value);
286
273
  // Clear out calls so everything is from the props change.
287
274
  fulfillSpy.mockClear();
288
275
  fakeChildrenFn.mockClear();
289
276
 
290
277
  // Act
291
- wrapper.setProps({
292
- handler: fakeHandler2,
293
- });
278
+ wrapper.rerender(
279
+ <Data handler={fakeHandler2} options={"options"}>
280
+ {fakeChildrenFn}
281
+ </Data>,
282
+ );
294
283
 
295
284
  // Assert
296
- expect(fakeChildrenFn).toHaveBeenCalledTimes(1);
285
+ // Render 1: Caused by handler changed
286
+ // Render 2: Caused by result state changing to null
287
+ expect(fakeChildrenFn).toHaveBeenCalledTimes(2);
297
288
  expect(fakeChildrenFn).toHaveBeenLastCalledWith({
298
- loading: true,
289
+ status: "loading",
299
290
  });
300
291
  });
301
292
 
@@ -309,134 +300,34 @@ describe("Data", () => {
309
300
  const fakeHandler: IRequestHandler<string, string> = {
310
301
  fulfillRequest: () => Promise.resolve("HELLO!"),
311
302
  getKey: (o) => o,
312
- shouldRefreshCache: () => false,
313
303
  type: "MY_HANDLER",
314
- cache: null,
315
304
  hydrate: true,
316
305
  };
317
306
  const fakeChildrenFn = jest.fn(() => null);
318
- const wrapper = mount(
307
+ const wrapper = render(
319
308
  <Data handler={fakeHandler} options={"options"}>
320
309
  {fakeChildrenFn}
321
310
  </Data>,
322
311
  );
323
- await fulfillSpy.mock.results[0].value;
312
+ // We want to make sure we render the data state so we can
313
+ // see our switch back to loading.
314
+ await act(() => fulfillSpy.mock.results[0].value);
324
315
  fulfillSpy.mockClear();
325
316
  fakeChildrenFn.mockClear();
326
317
 
327
318
  // Act
328
- wrapper.setProps({
329
- options: "new-options",
330
- });
319
+ wrapper.rerender(
320
+ <Data handler={fakeHandler} options={"new-options"}>
321
+ {fakeChildrenFn}
322
+ </Data>,
323
+ );
331
324
 
332
325
  // Assert
333
- expect(fakeChildrenFn).toHaveBeenCalledTimes(1);
326
+ // Render 1: Caused by handler changed
327
+ // Render 2: Caused by result state changing to null
328
+ expect(fakeChildrenFn).toHaveBeenCalledTimes(2);
334
329
  expect(fakeChildrenFn).toHaveBeenLastCalledWith({
335
- loading: true,
336
- });
337
- });
338
-
339
- describe("with cache interceptor", () => {
340
- it("should call the interceptor with null", () => {
341
- // Arrange
342
- const fakeHandler: IRequestHandler<string, string> = {
343
- fulfillRequest: () => Promise.resolve("data"),
344
- getKey: (o) => o,
345
- shouldRefreshCache: () => false,
346
- type: "MY_HANDLER",
347
- cache: null,
348
- hydrate: true,
349
- };
350
- const fakeChildrenFn = jest.fn(() => null);
351
- const fakeGetEntryFn = jest.fn(() => null);
352
-
353
- // Act
354
- mount(
355
- <InterceptCache
356
- handler={fakeHandler}
357
- getEntry={fakeGetEntryFn}
358
- >
359
- <Data handler={fakeHandler} options={"options"}>
360
- {fakeChildrenFn}
361
- </Data>
362
- </InterceptCache>,
363
- );
364
-
365
- // Assert
366
- expect(fakeGetEntryFn).toHaveBeenCalledWith(
367
- "options",
368
- null,
369
- );
370
- });
371
-
372
- it("should defer to the handler if interceptor returns null", () => {
373
- // Arrange
374
- const fulfillRequestSpy = jest
375
- .fn()
376
- .mockResolvedValue("data");
377
- const fakeHandler: IRequestHandler<string, string> = {
378
- fulfillRequest: fulfillRequestSpy,
379
- getKey: (o) => o,
380
- shouldRefreshCache: () => false,
381
- type: "MY_HANDLER",
382
- cache: null,
383
- hydrate: true,
384
- };
385
- const fakeChildrenFn = jest.fn(() => null);
386
- const fakeGetEntryFn = jest.fn(() => null);
387
-
388
- // Act
389
- mount(
390
- <InterceptCache
391
- handler={fakeHandler}
392
- getEntry={fakeGetEntryFn}
393
- >
394
- <Data handler={fakeHandler} options={"options"}>
395
- {fakeChildrenFn}
396
- </Data>
397
- </InterceptCache>,
398
- );
399
-
400
- // Assert
401
- expect(fulfillRequestSpy).toHaveBeenCalledWith("options");
402
- });
403
-
404
- it("should render with the intercepted cache entry", () => {
405
- // Arrange
406
- const fulfillRequestSpy = jest
407
- .fn()
408
- .mockResolvedValue("data");
409
- const fakeHandler: IRequestHandler<string, string> = {
410
- fulfillRequest: fulfillRequestSpy,
411
- getKey: (o) => o,
412
- shouldRefreshCache: () => false,
413
- type: "MY_HANDLER",
414
- cache: null,
415
- hydrate: true,
416
- };
417
- const fakeChildrenFn = jest.fn(() => null);
418
- const fakeGetEntryFn = jest.fn(() => ({
419
- error: "BOOMY BOOM!",
420
- }));
421
-
422
- // Act
423
- mount(
424
- <InterceptCache
425
- handler={fakeHandler}
426
- getEntry={fakeGetEntryFn}
427
- >
428
- <Data handler={fakeHandler} options={"options"}>
429
- {fakeChildrenFn}
430
- </Data>
431
- </InterceptCache>,
432
- );
433
-
434
- // Assert
435
- expect(fakeChildrenFn).toHaveBeenCalledWith({
436
- loading: false,
437
- error: "BOOMY BOOM!",
438
- });
439
- expect(fulfillRequestSpy).not.toHaveBeenCalled();
330
+ status: "loading",
440
331
  });
441
332
  });
442
333
 
@@ -449,9 +340,7 @@ describe("Data", () => {
449
340
  const fakeHandler: IRequestHandler<string, string> = {
450
341
  fulfillRequest: fulfillRequestSpy,
451
342
  getKey: (o) => o,
452
- shouldRefreshCache: () => false,
453
343
  type: "MY_HANDLER",
454
- cache: null,
455
344
  hydrate: true,
456
345
  };
457
346
  const fakeChildrenFn = jest.fn(() => null);
@@ -460,7 +349,7 @@ describe("Data", () => {
460
349
  );
461
350
 
462
351
  // Act
463
- mount(
352
+ render(
464
353
  <InterceptData
465
354
  handler={fakeHandler}
466
355
  fulfillRequest={fulfillRequestFn}
@@ -485,16 +374,14 @@ describe("Data", () => {
485
374
  const fakeHandler: IRequestHandler<string, string> = {
486
375
  fulfillRequest: fulfillRequestSpy,
487
376
  getKey: (o) => o,
488
- shouldRefreshCache: () => false,
489
377
  type: "MY_HANDLER",
490
- cache: null,
491
378
  hydrate: true,
492
379
  };
493
380
  const fakeChildrenFn = jest.fn(() => null);
494
381
  const fulfillRequestFn = jest.fn(() => null);
495
382
 
496
383
  // Act
497
- mount(
384
+ render(
498
385
  <InterceptData
499
386
  handler={fakeHandler}
500
387
  fulfillRequest={fulfillRequestFn}
@@ -524,69 +411,82 @@ describe("Data", () => {
524
411
  });
525
412
  });
526
413
 
527
- it("should not request data on construction", () => {
414
+ it("should render first time with the cached data", () => {
528
415
  // Arrange
529
- const fulfillRequestSpy = jest.fn();
530
416
  const fakeHandler: IRequestHandler<string, string> = {
531
- fulfillRequest: fulfillRequestSpy,
417
+ fulfillRequest: () => Promise.resolve("data"),
532
418
  getKey: (o) => o,
533
- shouldRefreshCache: () => false,
534
419
  type: "MY_HANDLER",
535
- cache: null,
536
420
  hydrate: true,
537
421
  };
538
422
  const fakeChildrenFn = jest.fn(() => null);
539
423
 
540
424
  // Act
541
- shallow(
425
+ render(
542
426
  <Data handler={fakeHandler} options={"options"}>
543
427
  {fakeChildrenFn}
544
428
  </Data>,
545
429
  );
546
430
 
547
431
  // Assert
548
- expect(fulfillRequestSpy).not.toHaveBeenCalled();
432
+ expect(fakeChildrenFn).toHaveBeenCalledWith({
433
+ status: "success",
434
+ data: "YAY! DATA!",
435
+ });
436
+ });
437
+ });
438
+ });
439
+
440
+ describe("SSR: isServerSide true", () => {
441
+ beforeEach(() => {
442
+ jest.spyOn(Server, "isServerSide").mockReturnValue(true);
443
+ });
444
+
445
+ describe("without cached data", () => {
446
+ beforeEach(() => {
447
+ /**
448
+ * Each of these test cases will never have cached data
449
+ * retrieved.
450
+ */
451
+ jest.spyOn(ResponseCache.Default, "getEntry").mockReturnValue(
452
+ null,
453
+ );
549
454
  });
550
455
 
551
- it("should request data if shouldRefreshCache returns true", () => {
456
+ it("should not request data", () => {
552
457
  // Arrange
553
458
  const fulfillRequestSpy = jest.fn().mockResolvedValue("data");
554
459
  const fakeHandler: IRequestHandler<string, string> = {
555
460
  fulfillRequest: fulfillRequestSpy,
556
461
  getKey: (o) => o,
557
- shouldRefreshCache: () => true,
558
462
  type: "MY_HANDLER",
559
- cache: null,
560
463
  hydrate: true,
561
464
  };
562
465
  const fakeChildrenFn = jest.fn(() => null);
563
466
 
564
467
  // Act
565
- mount(
468
+ ReactDOMServer.renderToString(
566
469
  <Data handler={fakeHandler} options={"options"}>
567
470
  {fakeChildrenFn}
568
471
  </Data>,
569
472
  );
570
473
 
571
474
  // Assert
572
- expect(fulfillRequestSpy).toHaveBeenCalledWith("options");
573
- expect(fulfillRequestSpy).toHaveBeenCalledTimes(1);
475
+ expect(fulfillRequestSpy).not.toHaveBeenCalled();
574
476
  });
575
477
 
576
- it("should render first time with the cached data", () => {
478
+ it("should render children with loading", () => {
577
479
  // Arrange
578
480
  const fakeHandler: IRequestHandler<string, string> = {
579
481
  fulfillRequest: () => Promise.resolve("data"),
580
482
  getKey: (o) => o,
581
- shouldRefreshCache: () => false,
582
483
  type: "MY_HANDLER",
583
- cache: null,
584
484
  hydrate: true,
585
485
  };
586
486
  const fakeChildrenFn = jest.fn(() => null);
587
487
 
588
488
  // Act
589
- mount(
489
+ ReactDOMServer.renderToString(
590
490
  <Data handler={fakeHandler} options={"options"}>
591
491
  {fakeChildrenFn}
592
492
  </Data>,
@@ -594,676 +494,120 @@ describe("Data", () => {
594
494
 
595
495
  // Assert
596
496
  expect(fakeChildrenFn).toHaveBeenCalledWith({
597
- loading: false,
598
- data: "YAY! DATA!",
497
+ status: "loading",
599
498
  });
600
499
  });
601
500
 
602
- it("should render with new data if the handler changes and request cached", () => {
501
+ it("should invoke the tracking call", () => {
603
502
  // Arrange
604
- const fakeHandler: IRequestHandler<string, string> = {
605
- fulfillRequest: () => Promise.reject(new Error("OH NOES!")),
606
- getKey: (o) => o,
607
- shouldRefreshCache: () => false,
608
- type: "TYPE1",
609
- cache: null,
610
- hydrate: true,
611
- };
612
- const fakeHandler2: IRequestHandler<string, string> = {
613
- fulfillRequest: () => new Promise(() => {}),
614
- getKey: (o) => o,
615
- shouldRefreshCache: () => false,
616
- type: "TYPE2",
617
- cache: null,
618
- hydrate: true,
619
- };
620
- const fakeChildrenFn = jest.fn(() => null);
621
- const wrapper = mount(
622
- <Data handler={fakeHandler} options={"options"}>
623
- {fakeChildrenFn}
624
- </Data>,
503
+ const trackSpy = jest.spyOn(
504
+ RequestTracker.Default,
505
+ "trackDataRequest",
625
506
  );
626
- // Clear out calls so everything is from the props change.
627
- fakeChildrenFn.mockClear();
628
- jest.spyOn(ResponseCache.Default, "getEntry").mockReturnValue({
629
- data: "NEW DATA!",
630
- });
631
-
632
- // Act
633
- wrapper.setProps({
634
- handler: fakeHandler2,
635
- });
636
-
637
- // Assert
638
- expect(fakeChildrenFn).toHaveBeenCalledTimes(1);
639
- expect(fakeChildrenFn).toHaveBeenLastCalledWith({
640
- loading: false,
641
- data: "NEW DATA!",
642
- });
643
- });
644
-
645
- it("should render with new data if the options key changes and is cached", () => {
646
- // Arrange
647
507
  const fakeHandler: IRequestHandler<string, string> = {
648
- fulfillRequest: () => Promise.resolve("Not called!"),
508
+ fulfillRequest: () => Promise.resolve("data"),
649
509
  getKey: (o) => o,
650
- shouldRefreshCache: () => false,
651
510
  type: "MY_HANDLER",
652
- cache: null,
653
511
  hydrate: true,
654
512
  };
655
513
  const fakeChildrenFn = jest.fn(() => null);
656
- const wrapper = mount(
657
- <Data handler={fakeHandler} options={"options"}>
658
- {fakeChildrenFn}
659
- </Data>,
660
- );
661
- fakeChildrenFn.mockClear();
662
- jest.spyOn(ResponseCache.Default, "getEntry").mockReturnValue({
663
- data: "NEW DATA!",
664
- });
665
514
 
666
515
  // Act
667
- wrapper.setProps({
668
- options: "new-options",
669
- });
516
+ ReactDOMServer.renderToString(
517
+ <TrackData>
518
+ <Data handler={fakeHandler} options={"options"}>
519
+ {fakeChildrenFn}
520
+ </Data>
521
+ </TrackData>,
522
+ );
670
523
 
671
524
  // Assert
672
- expect(fakeChildrenFn).toHaveBeenCalledTimes(1);
673
- expect(fakeChildrenFn).toHaveBeenLastCalledWith({
674
- loading: false,
675
- data: "NEW DATA!",
676
- });
525
+ expect(trackSpy).toHaveBeenCalledWith(fakeHandler, "options");
677
526
  });
678
527
 
679
- describe("with cache interceptor", () => {
680
- it("should call the interceptor with current cache entry", () => {
528
+ describe("with data interceptor", () => {
529
+ it("should not request data from the interceptor", () => {
681
530
  // Arrange
531
+ const fulfillRequestSpy = jest
532
+ .fn()
533
+ .mockResolvedValue("data");
682
534
  const fakeHandler: IRequestHandler<string, string> = {
683
- fulfillRequest: () => Promise.resolve("data"),
535
+ fulfillRequest: fulfillRequestSpy,
684
536
  getKey: (o) => o,
685
- shouldRefreshCache: () => false,
686
537
  type: "MY_HANDLER",
687
- cache: null,
688
538
  hydrate: true,
689
539
  };
690
540
  const fakeChildrenFn = jest.fn(() => null);
691
- const fakeGetEntryFn = jest.fn(() => null);
692
-
693
- // Act
694
- mount(
695
- <InterceptCache
696
- handler={fakeHandler}
697
- getEntry={fakeGetEntryFn}
698
- >
699
- <Data handler={fakeHandler} options={"options"}>
700
- {fakeChildrenFn}
701
- </Data>
702
- </InterceptCache>,
541
+ const fulfillRequestFn = jest.fn(() =>
542
+ Promise.resolve("DATA!"),
703
543
  );
704
544
 
705
- // Assert
706
- expect(fakeGetEntryFn).toHaveBeenCalledWith("options", {
707
- data: "YAY! DATA!",
708
- });
709
- });
710
-
711
- it("should defer to the main cache if interceptor returns null", () => {
712
- // Arrange
713
- const fakeHandler: IRequestHandler<string, string> = {
714
- fulfillRequest: () => Promise.resolve("data"),
715
- getKey: (o) => o,
716
- shouldRefreshCache: () => false,
717
- type: "MY_HANDLER",
718
- cache: null,
719
- hydrate: true,
720
- };
721
- const fakeChildrenFn = jest.fn(() => null);
722
- const fakeGetEntryFn = jest.fn(() => null);
723
-
724
545
  // Act
725
- mount(
726
- <InterceptCache
546
+ ReactDOMServer.renderToString(
547
+ <InterceptData
727
548
  handler={fakeHandler}
728
- getEntry={fakeGetEntryFn}
549
+ fulfillRequest={fulfillRequestFn}
729
550
  >
730
551
  <Data handler={fakeHandler} options={"options"}>
731
552
  {fakeChildrenFn}
732
553
  </Data>
733
- </InterceptCache>,
554
+ </InterceptData>,
734
555
  );
735
556
 
736
557
  // Assert
737
- expect(fakeChildrenFn).toHaveBeenCalledWith({
738
- loading: false,
739
- data: "YAY! DATA!",
740
- });
558
+ expect(fulfillRequestFn).not.toHaveBeenCalled();
559
+ expect(fulfillRequestSpy).not.toHaveBeenCalled();
741
560
  });
742
561
 
743
- it("should render with the intercepted cache entry", () => {
562
+ it("should invoke the tracking call", () => {
744
563
  // Arrange
745
- const fakeHandler: IRequestHandler<string, string> = {
564
+ const trackSpy = jest.spyOn(
565
+ RequestTracker.Default,
566
+ "trackDataRequest",
567
+ );
568
+ const fakeHandler = {
746
569
  fulfillRequest: () => Promise.resolve("data"),
747
570
  getKey: (o) => o,
748
- shouldRefreshCache: () => false,
749
571
  type: "MY_HANDLER",
750
- cache: null,
751
572
  hydrate: true,
752
573
  };
753
574
  const fakeChildrenFn = jest.fn(() => null);
754
- const fakeGetEntryFn = jest.fn(() => ({
755
- error: "BOOMY BOOM!",
756
- }));
575
+ const fulfillRequestFn = jest.fn(() =>
576
+ Promise.resolve("DATA!"),
577
+ );
757
578
 
758
579
  // Act
759
- mount(
760
- <InterceptCache
761
- handler={fakeHandler}
762
- getEntry={fakeGetEntryFn}
763
- >
764
- <Data handler={fakeHandler} options={"options"}>
765
- {fakeChildrenFn}
766
- </Data>
767
- </InterceptCache>,
580
+ ReactDOMServer.renderToString(
581
+ <TrackData>
582
+ <InterceptData
583
+ handler={
584
+ (fakeHandler: IRequestHandler<
585
+ string,
586
+ string,
587
+ >)
588
+ }
589
+ fulfillRequest={fulfillRequestFn}
590
+ >
591
+ <Data handler={fakeHandler} options={"options"}>
592
+ {fakeChildrenFn}
593
+ </Data>
594
+ </InterceptData>
595
+ </TrackData>,
768
596
  );
769
597
 
770
598
  // Assert
771
- expect(fakeChildrenFn).toHaveBeenCalledWith({
772
- loading: false,
773
- error: "BOOMY BOOM!",
774
- });
599
+ expect(trackSpy).toHaveBeenCalledWith(
600
+ {
601
+ fulfillRequest: expect.any(Function),
602
+ getKey: expect.any(Function),
603
+ type: "MY_HANDLER",
604
+ hydrate: true,
605
+ },
606
+ "options",
607
+ );
775
608
  });
776
609
  });
777
-
778
- describe("with data interceptor", () => {
779
- it("should request data from handler if interceptor shouldRefreshCache returns true", () => {
780
- // Arrange
781
- const fulfillRequestSpy = jest
782
- .fn()
783
- .mockResolvedValue("data");
784
- const shouldRefreshCacheSpy = jest.fn(() => false);
785
- const fakeHandler: IRequestHandler<string, string> = {
786
- fulfillRequest: fulfillRequestSpy,
787
- getKey: (o) => o,
788
- shouldRefreshCache: shouldRefreshCacheSpy,
789
- type: "MY_HANDLER",
790
- cache: null,
791
- hydrate: true,
792
- };
793
- const fakeChildrenFn = jest.fn(() => null);
794
- const shouldRefreshCacheFn = jest.fn(() => true);
795
-
796
- // Act
797
- mount(
798
- <InterceptData
799
- handler={fakeHandler}
800
- shouldRefreshCache={shouldRefreshCacheFn}
801
- >
802
- <Data handler={fakeHandler} options={"options"}>
803
- {fakeChildrenFn}
804
- </Data>
805
- </InterceptData>,
806
- );
807
-
808
- // Assert
809
- expect(fulfillRequestSpy).toHaveBeenCalledWith("options");
810
- expect(fulfillRequestSpy).toHaveBeenCalledTimes(1);
811
- expect(shouldRefreshCacheSpy).not.toHaveBeenCalled();
812
- });
813
-
814
- it("should defer to handler if interceptor shouldRefreshCache returns null", () => {
815
- // Arrange
816
- const fulfillRequestSpy = jest
817
- .fn()
818
- .mockResolvedValue("data");
819
- const shouldRefreshCacheSpy = jest.fn(() => false);
820
- const fakeHandler: IRequestHandler<string, string> = {
821
- fulfillRequest: fulfillRequestSpy,
822
- getKey: (o) => o,
823
- shouldRefreshCache: shouldRefreshCacheSpy,
824
- type: "MY_HANDLER",
825
- cache: null,
826
- hydrate: true,
827
- };
828
- const fakeChildrenFn = jest.fn(() => null);
829
- const shouldRefreshCacheFn = jest.fn(() => null);
830
-
831
- // Act
832
- mount(
833
- <InterceptData
834
- handler={fakeHandler}
835
- shouldRefreshCache={shouldRefreshCacheFn}
836
- >
837
- <Data handler={fakeHandler} options={"options"}>
838
- {fakeChildrenFn}
839
- </Data>
840
- </InterceptData>,
841
- );
842
-
843
- // Assert
844
- expect(shouldRefreshCacheSpy).toHaveBeenCalledWith(
845
- "options",
846
- expect.any(Object),
847
- );
848
- });
849
-
850
- it("should request data from interceptor if handler shouldRefreshCache returns true", () => {
851
- // Arrange
852
- const fulfillRequestSpy = jest
853
- .fn()
854
- .mockResolvedValue("data");
855
- const fakeHandler: IRequestHandler<string, string> = {
856
- fulfillRequest: fulfillRequestSpy,
857
- getKey: (o) => o,
858
- shouldRefreshCache: () => true,
859
- type: "MY_HANDLER",
860
- cache: null,
861
- hydrate: true,
862
- };
863
- const fakeChildrenFn = jest.fn(() => null);
864
- const fulfillRequestFn = jest.fn(() =>
865
- Promise.resolve("DATA!"),
866
- );
867
-
868
- // Act
869
- mount(
870
- <InterceptData
871
- handler={fakeHandler}
872
- fulfillRequest={fulfillRequestFn}
873
- >
874
- <Data handler={fakeHandler} options={"options"}>
875
- {fakeChildrenFn}
876
- </Data>
877
- </InterceptData>,
878
- );
879
-
880
- // Assert
881
- expect(fulfillRequestFn).toHaveBeenCalledWith("options");
882
- expect(fulfillRequestFn).toHaveBeenCalledTimes(1);
883
- expect(fulfillRequestSpy).not.toHaveBeenCalled();
884
- });
885
-
886
- it("should request data from interceptor if interceptor shouldRefreshCache returns true", () => {
887
- // Arrange
888
- const fulfillRequestSpy = jest
889
- .fn()
890
- .mockResolvedValue("data");
891
- const fakeHandler: IRequestHandler<string, string> = {
892
- fulfillRequest: fulfillRequestSpy,
893
- getKey: (o) => o,
894
- shouldRefreshCache: () => false,
895
- type: "MY_HANDLER",
896
- cache: null,
897
- hydrate: true,
898
- };
899
- const fakeChildrenFn = jest.fn(() => null);
900
- const shouldRefreshCacheFn = jest.fn(() => true);
901
- const fulfillRequestFn = jest.fn(() =>
902
- Promise.resolve("DATA!"),
903
- );
904
-
905
- // Act
906
- mount(
907
- <InterceptData
908
- handler={fakeHandler}
909
- fulfillRequest={fulfillRequestFn}
910
- shouldRefreshCache={shouldRefreshCacheFn}
911
- >
912
- <Data handler={fakeHandler} options={"options"}>
913
- {fakeChildrenFn}
914
- </Data>
915
- </InterceptData>,
916
- );
917
-
918
- // Assert
919
- expect(fulfillRequestFn).toHaveBeenCalledWith("options");
920
- expect(fulfillRequestFn).toHaveBeenCalledTimes(1);
921
- expect(fulfillRequestSpy).not.toHaveBeenCalled();
922
- });
923
- });
924
- });
925
- });
926
-
927
- describe("SSR: isServerSide true", () => {
928
- beforeEach(() => {
929
- jest.spyOn(Server, "isServerSide").mockReturnValue(true);
930
- });
931
-
932
- describe("without cached data", () => {
933
- beforeEach(() => {
934
- /**
935
- * Each of these test cases will never have cached data
936
- * retrieved.
937
- */
938
- jest.spyOn(ResponseCache.Default, "getEntry").mockReturnValue(
939
- null,
940
- );
941
- });
942
-
943
- it("should not request data", () => {
944
- // Arrange
945
- const fulfillRequestSpy = jest.fn().mockResolvedValue("data");
946
- const fakeHandler: IRequestHandler<string, string> = {
947
- fulfillRequest: fulfillRequestSpy,
948
- getKey: (o) => o,
949
- shouldRefreshCache: () => false,
950
- type: "MY_HANDLER",
951
- cache: null,
952
- hydrate: true,
953
- };
954
- const fakeChildrenFn = jest.fn(() => null);
955
-
956
- // Act
957
- ReactDOMServer.renderToString(
958
- <Data handler={fakeHandler} options={"options"}>
959
- {fakeChildrenFn}
960
- </Data>,
961
- );
962
-
963
- // Assert
964
- expect(fulfillRequestSpy).not.toHaveBeenCalled();
965
- });
966
-
967
- it("should render children with loading", () => {
968
- // Arrange
969
- const fakeHandler: IRequestHandler<string, string> = {
970
- fulfillRequest: () => Promise.resolve("data"),
971
- getKey: (o) => o,
972
- shouldRefreshCache: () => false,
973
- type: "MY_HANDLER",
974
- cache: null,
975
- hydrate: true,
976
- };
977
- const fakeChildrenFn = jest.fn(() => null);
978
-
979
- // Act
980
- ReactDOMServer.renderToString(
981
- <Data handler={fakeHandler} options={"options"}>
982
- {fakeChildrenFn}
983
- </Data>,
984
- );
985
-
986
- // Assert
987
- expect(fakeChildrenFn).toHaveBeenCalledWith(
988
- expect.objectContaining({
989
- loading: true,
990
- }),
991
- );
992
- });
993
-
994
- it("should invoke the tracking call", () => {
995
- // Arrange
996
- const trackSpy = jest.spyOn(
997
- RequestTracker.Default,
998
- "trackDataRequest",
999
- );
1000
- const fakeHandler: IRequestHandler<string, string> = {
1001
- fulfillRequest: () => Promise.resolve("data"),
1002
- getKey: (o) => o,
1003
- shouldRefreshCache: () => false,
1004
- type: "MY_HANDLER",
1005
- cache: null,
1006
- hydrate: true,
1007
- };
1008
- const fakeChildrenFn = jest.fn(() => null);
1009
-
1010
- // Act
1011
- ReactDOMServer.renderToString(
1012
- <TrackData>
1013
- <Data handler={fakeHandler} options={"options"}>
1014
- {fakeChildrenFn}
1015
- </Data>
1016
- </TrackData>,
1017
- );
1018
-
1019
- // Assert
1020
- expect(trackSpy).toHaveBeenCalledWith(fakeHandler, "options");
1021
- });
1022
-
1023
- describe("with cache interceptor", () => {
1024
- it("should call the interceptor with null", () => {
1025
- // Arrange
1026
- const fakeHandler: IRequestHandler<string, string> = {
1027
- fulfillRequest: () => Promise.resolve("data"),
1028
- getKey: (o) => o,
1029
- shouldRefreshCache: () => false,
1030
- type: "MY_HANDLER",
1031
- cache: null,
1032
- hydrate: true,
1033
- };
1034
- const fakeChildrenFn = jest.fn(() => null);
1035
- const fakeGetEntryFn = jest.fn(() => null);
1036
-
1037
- // Act
1038
- ReactDOMServer.renderToString(
1039
- <InterceptCache
1040
- handler={fakeHandler}
1041
- getEntry={fakeGetEntryFn}
1042
- >
1043
- <Data handler={fakeHandler} options={"options"}>
1044
- {fakeChildrenFn}
1045
- </Data>
1046
- </InterceptCache>,
1047
- );
1048
-
1049
- // Assert
1050
- expect(fakeGetEntryFn).toHaveBeenCalledWith(
1051
- "options",
1052
- null,
1053
- );
1054
- });
1055
-
1056
- it("should render with the intercepted cache entry", () => {
1057
- // Arrange
1058
- const fulfillRequestSpy = jest
1059
- .fn()
1060
- .mockResolvedValue("data");
1061
- const fakeHandler: IRequestHandler<string, string> = {
1062
- fulfillRequest: fulfillRequestSpy,
1063
- getKey: (o) => o,
1064
- shouldRefreshCache: () => false,
1065
- type: "MY_HANDLER",
1066
- cache: null,
1067
- hydrate: true,
1068
- };
1069
- const fakeChildrenFn = jest.fn(() => null);
1070
- const fakeGetEntryFn = jest.fn(() => ({
1071
- error: "BOOMY BOOM!",
1072
- }));
1073
-
1074
- // Act
1075
- ReactDOMServer.renderToString(
1076
- <InterceptCache
1077
- handler={fakeHandler}
1078
- getEntry={fakeGetEntryFn}
1079
- >
1080
- <Data handler={fakeHandler} options={"options"}>
1081
- {fakeChildrenFn}
1082
- </Data>
1083
- </InterceptCache>,
1084
- );
1085
-
1086
- // Assert
1087
- expect(fakeChildrenFn).toHaveBeenCalledWith({
1088
- loading: false,
1089
- error: "BOOMY BOOM!",
1090
- });
1091
- expect(fulfillRequestSpy).not.toHaveBeenCalled();
1092
- });
1093
-
1094
- it("should not invoke the tracking call", () => {
1095
- // Arrange
1096
- const trackSpy = jest.spyOn(
1097
- RequestTracker.Default,
1098
- "trackDataRequest",
1099
- );
1100
- const fakeHandler = {
1101
- fulfillRequest: () => Promise.resolve("data"),
1102
- getKey: (o) => o,
1103
- shouldRefreshCache: () => false,
1104
- type: "MY_HANDLER",
1105
- cache: null,
1106
- hydrate: true,
1107
- };
1108
- const fakeChildrenFn = jest.fn(() => null);
1109
- const fakeGetEntryFn = jest.fn(() => ({
1110
- data: "BOOMY BOOM!",
1111
- }));
1112
-
1113
- // Act
1114
- ReactDOMServer.renderToString(
1115
- <TrackData>
1116
- <InterceptCache
1117
- handler={fakeHandler}
1118
- getEntry={fakeGetEntryFn}
1119
- >
1120
- <Data handler={fakeHandler} options={"options"}>
1121
- {fakeChildrenFn}
1122
- </Data>
1123
- </InterceptCache>
1124
- </TrackData>,
1125
- );
1126
-
1127
- // Assert
1128
- expect(trackSpy).not.toHaveBeenCalled();
1129
- });
1130
- });
1131
-
1132
- describe("with data interceptor", () => {
1133
- it("should not request data from the interceptor", () => {
1134
- // Arrange
1135
- const fulfillRequestSpy = jest
1136
- .fn()
1137
- .mockResolvedValue("data");
1138
- const fakeHandler: IRequestHandler<string, string> = {
1139
- fulfillRequest: fulfillRequestSpy,
1140
- getKey: (o) => o,
1141
- shouldRefreshCache: () => false,
1142
- type: "MY_HANDLER",
1143
- cache: null,
1144
- hydrate: true,
1145
- };
1146
- const fakeChildrenFn = jest.fn(() => null);
1147
- const fulfillRequestFn = jest.fn(() =>
1148
- Promise.resolve("DATA!"),
1149
- );
1150
-
1151
- // Act
1152
- ReactDOMServer.renderToString(
1153
- <InterceptData
1154
- handler={fakeHandler}
1155
- fulfillRequest={fulfillRequestFn}
1156
- >
1157
- <Data handler={fakeHandler} options={"options"}>
1158
- {fakeChildrenFn}
1159
- </Data>
1160
- </InterceptData>,
1161
- );
1162
-
1163
- // Assert
1164
- expect(fulfillRequestFn).not.toHaveBeenCalled();
1165
- expect(fulfillRequestSpy).not.toHaveBeenCalled();
1166
- });
1167
-
1168
- it("should invoke the tracking call", () => {
1169
- // Arrange
1170
- const trackSpy = jest.spyOn(
1171
- RequestTracker.Default,
1172
- "trackDataRequest",
1173
- );
1174
- const fakeHandler = {
1175
- fulfillRequest: () => Promise.resolve("data"),
1176
- getKey: (o) => o,
1177
- shouldRefreshCache: () => false,
1178
- type: "MY_HANDLER",
1179
- cache: null,
1180
- hydrate: true,
1181
- };
1182
- const fakeChildrenFn = jest.fn(() => null);
1183
- const shouldRefreshCacheFn = jest.fn(() => true);
1184
-
1185
- // Act
1186
- ReactDOMServer.renderToString(
1187
- <TrackData>
1188
- <InterceptData
1189
- handler={
1190
- (fakeHandler: IRequestHandler<
1191
- string,
1192
- string,
1193
- >)
1194
- }
1195
- shouldRefreshCache={shouldRefreshCacheFn}
1196
- >
1197
- <Data handler={fakeHandler} options={"options"}>
1198
- {fakeChildrenFn}
1199
- </Data>
1200
- </InterceptData>
1201
- </TrackData>,
1202
- );
1203
-
1204
- // Assert
1205
- expect(trackSpy).toHaveBeenCalledWith(
1206
- {
1207
- fulfillRequest: expect.any(Function),
1208
- getKey: expect.any(Function),
1209
- type: "MY_HANDLER",
1210
- cache: null,
1211
- hydrate: true,
1212
- shouldRefreshCache: expect.any(Function),
1213
- },
1214
- "options",
1215
- );
1216
- });
1217
-
1218
- it("should invoke tracking call with handler that defers to interceptor", () => {
1219
- // Arrange
1220
- const trackSpy = jest.spyOn(
1221
- RequestTracker.Default,
1222
- "trackDataRequest",
1223
- );
1224
- const fakeHandler = {
1225
- fulfillRequest: () => Promise.resolve("data"),
1226
- getKey: (o) => o,
1227
- shouldRefreshCache: () => false,
1228
- type: "MY_HANDLER",
1229
- cache: null,
1230
- hydrate: true,
1231
- };
1232
- const fakeChildrenFn = jest.fn(() => null);
1233
- const shouldRefreshCacheFn = jest.fn(() => true);
1234
-
1235
- // Act
1236
- ReactDOMServer.renderToString(
1237
- <TrackData>
1238
- <InterceptData
1239
- handler={
1240
- (fakeHandler: IRequestHandler<
1241
- string,
1242
- string,
1243
- >)
1244
- }
1245
- shouldRefreshCache={shouldRefreshCacheFn}
1246
- >
1247
- <Data handler={fakeHandler} options={"options"}>
1248
- {fakeChildrenFn}
1249
- </Data>
1250
- </InterceptData>
1251
- </TrackData>,
1252
- );
1253
- trackSpy.mock.calls[0][0].shouldRefreshCache(
1254
- "options",
1255
- null,
1256
- );
1257
-
1258
- // Assert
1259
- expect(shouldRefreshCacheFn).toHaveBeenCalledWith(
1260
- "options",
1261
- null,
1262
- );
1263
- expect(shouldRefreshCacheFn).toHaveBeenCalledTimes(1);
1264
- });
1265
- });
1266
- });
610
+ });
1267
611
 
1268
612
  describe("with cached data", () => {
1269
613
  beforeEach(() => {
@@ -1282,9 +626,7 @@ describe("Data", () => {
1282
626
  const fakeHandler: IRequestHandler<string, string> = {
1283
627
  fulfillRequest: fulfillRequestSpy,
1284
628
  getKey: (o) => o,
1285
- shouldRefreshCache: () => false,
1286
629
  type: "MY_HANDLER",
1287
- cache: null,
1288
630
  hydrate: true,
1289
631
  };
1290
632
  const fakeChildrenFn = jest.fn(() => null);
@@ -1305,9 +647,7 @@ describe("Data", () => {
1305
647
  const fakeHandler: IRequestHandler<string, string> = {
1306
648
  fulfillRequest: () => Promise.resolve("data"),
1307
649
  getKey: (o) => o,
1308
- shouldRefreshCache: () => false,
1309
650
  type: "MY_HANDLER",
1310
- cache: null,
1311
651
  hydrate: true,
1312
652
  };
1313
653
  const fakeChildrenFn = jest.fn(() => null);
@@ -1320,12 +660,10 @@ describe("Data", () => {
1320
660
  );
1321
661
 
1322
662
  // Assert
1323
- expect(fakeChildrenFn).toHaveBeenCalledWith(
1324
- expect.objectContaining({
1325
- loading: false,
1326
- data: "YAY! DATA!",
1327
- }),
1328
- );
663
+ expect(fakeChildrenFn).toHaveBeenCalledWith({
664
+ status: "success",
665
+ data: "YAY! DATA!",
666
+ });
1329
667
  });
1330
668
 
1331
669
  it("should render children with error", () => {
@@ -1336,9 +674,7 @@ describe("Data", () => {
1336
674
  const fakeHandler: IRequestHandler<string, string> = {
1337
675
  fulfillRequest: () => Promise.resolve("data"),
1338
676
  getKey: (o) => o,
1339
- shouldRefreshCache: () => false,
1340
677
  type: "MY_HANDLER",
1341
- cache: null,
1342
678
  hydrate: true,
1343
679
  };
1344
680
  const fakeChildrenFn = jest.fn(() => null);
@@ -1351,12 +687,10 @@ describe("Data", () => {
1351
687
  );
1352
688
 
1353
689
  // Assert
1354
- expect(fakeChildrenFn).toHaveBeenCalledWith(
1355
- expect.objectContaining({
1356
- loading: false,
1357
- error: "OH NO! IT GO BOOM",
1358
- }),
1359
- );
690
+ expect(fakeChildrenFn).toHaveBeenCalledWith({
691
+ status: "error",
692
+ error: "OH NO! IT GO BOOM",
693
+ });
1360
694
  });
1361
695
 
1362
696
  it("should not invoke the tracking call", () => {
@@ -1368,9 +702,7 @@ describe("Data", () => {
1368
702
  const fakeHandler: IRequestHandler<string, string> = {
1369
703
  fulfillRequest: () => Promise.resolve("data"),
1370
704
  getKey: (o) => o,
1371
- shouldRefreshCache: () => false,
1372
705
  type: "MY_HANDLER",
1373
- cache: null,
1374
706
  hydrate: true,
1375
707
  };
1376
708
  const fakeChildrenFn = jest.fn(() => null);
@@ -1391,142 +723,6 @@ describe("Data", () => {
1391
723
  );
1392
724
  });
1393
725
 
1394
- describe("with cache interceptor", () => {
1395
- it("should call the interceptor with current cache entry", () => {
1396
- // Arrange
1397
- const fakeHandler: IRequestHandler<string, string> = {
1398
- fulfillRequest: () => Promise.resolve("data"),
1399
- getKey: (o) => o,
1400
- shouldRefreshCache: () => false,
1401
- type: "MY_HANDLER",
1402
- cache: null,
1403
- hydrate: true,
1404
- };
1405
- const fakeChildrenFn = jest.fn(() => null);
1406
- const fakeGetEntryFn = jest.fn(() => null);
1407
-
1408
- // Act
1409
- ReactDOMServer.renderToString(
1410
- <InterceptCache
1411
- handler={fakeHandler}
1412
- getEntry={fakeGetEntryFn}
1413
- >
1414
- <Data handler={fakeHandler} options={"options"}>
1415
- {fakeChildrenFn}
1416
- </Data>
1417
- </InterceptCache>,
1418
- );
1419
-
1420
- // Assert
1421
- expect(fakeGetEntryFn).toHaveBeenCalledWith("options", {
1422
- data: "YAY! DATA!",
1423
- });
1424
- });
1425
-
1426
- it("should defer to the main cache if interceptor returns null", () => {
1427
- // Arrange
1428
- const fakeHandler: IRequestHandler<string, string> = {
1429
- fulfillRequest: () => Promise.resolve("data"),
1430
- getKey: (o) => o,
1431
- shouldRefreshCache: () => false,
1432
- type: "MY_HANDLER",
1433
- cache: null,
1434
- hydrate: true,
1435
- };
1436
- const fakeChildrenFn = jest.fn(() => null);
1437
- const fakeGetEntryFn = jest.fn(() => null);
1438
-
1439
- // Act
1440
- ReactDOMServer.renderToString(
1441
- <InterceptCache
1442
- handler={fakeHandler}
1443
- getEntry={fakeGetEntryFn}
1444
- >
1445
- <Data handler={fakeHandler} options={"options"}>
1446
- {fakeChildrenFn}
1447
- </Data>
1448
- </InterceptCache>,
1449
- );
1450
-
1451
- // Assert
1452
- expect(fakeChildrenFn).toHaveBeenCalledWith({
1453
- loading: false,
1454
- data: "YAY! DATA!",
1455
- });
1456
- });
1457
-
1458
- it("should render with the intercepted cache entry", () => {
1459
- // Arrange
1460
- const fakeHandler: IRequestHandler<string, string> = {
1461
- fulfillRequest: () => Promise.resolve("data"),
1462
- getKey: (o) => o,
1463
- shouldRefreshCache: () => false,
1464
- type: "MY_HANDLER",
1465
- cache: null,
1466
- hydrate: true,
1467
- };
1468
- const fakeChildrenFn = jest.fn(() => null);
1469
- const fakeGetEntryFn = jest.fn(() => ({
1470
- error: "BOOMY BOOM!",
1471
- }));
1472
-
1473
- // Act
1474
- ReactDOMServer.renderToString(
1475
- <InterceptCache
1476
- handler={fakeHandler}
1477
- getEntry={fakeGetEntryFn}
1478
- >
1479
- <Data handler={fakeHandler} options={"options"}>
1480
- {fakeChildrenFn}
1481
- </Data>
1482
- </InterceptCache>,
1483
- );
1484
-
1485
- // Assert
1486
- expect(fakeChildrenFn).toHaveBeenCalledWith({
1487
- loading: false,
1488
- error: "BOOMY BOOM!",
1489
- });
1490
- });
1491
-
1492
- it("should not invoke the tracking call", () => {
1493
- // Arrange
1494
- const trackSpy = jest.spyOn(
1495
- RequestTracker.Default,
1496
- "trackDataRequest",
1497
- );
1498
- const fakeHandler: IRequestHandler<string, string> = {
1499
- fulfillRequest: () => Promise.resolve("data"),
1500
- getKey: (o) => o,
1501
- shouldRefreshCache: () => false,
1502
- type: "MY_HANDLER",
1503
- cache: null,
1504
- hydrate: true,
1505
- };
1506
- const fakeChildrenFn = jest.fn(() => null);
1507
- const fakeGetEntryFn = jest.fn(() => ({
1508
- data: "DATA!",
1509
- }));
1510
-
1511
- // Act
1512
- ReactDOMServer.renderToString(
1513
- <TrackData>
1514
- <InterceptCache
1515
- handler={fakeHandler}
1516
- getEntry={fakeGetEntryFn}
1517
- >
1518
- <Data handler={fakeHandler} options={"options"}>
1519
- {fakeChildrenFn}
1520
- </Data>
1521
- </InterceptCache>
1522
- </TrackData>,
1523
- );
1524
-
1525
- // Assert
1526
- expect(trackSpy).not.toHaveBeenCalled();
1527
- });
1528
- });
1529
-
1530
726
  describe("with data interceptor", () => {
1531
727
  it("should not request data from interceptor", () => {
1532
728
  // Arrange
@@ -1536,9 +732,7 @@ describe("Data", () => {
1536
732
  const fakeHandler: IRequestHandler<string, string> = {
1537
733
  fulfillRequest: fulfillRequestSpy,
1538
734
  getKey: (o) => o,
1539
- shouldRefreshCache: jest.fn(() => true),
1540
735
  type: "MY_HANDLER",
1541
- cache: null,
1542
736
  hydrate: true,
1543
737
  };
1544
738
  const fakeChildrenFn = jest.fn(() => null);