@khanacademy/wonder-blocks-data 13.0.11 → 14.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.
Files changed (66) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/package.json +5 -5
  3. package/src/components/__tests__/data.test.tsx +0 -832
  4. package/src/components/__tests__/gql-router.test.tsx +0 -63
  5. package/src/components/__tests__/intercept-requests.test.tsx +0 -57
  6. package/src/components/__tests__/track-data.test.tsx +0 -56
  7. package/src/components/data.ts +0 -73
  8. package/src/components/gql-router.tsx +0 -63
  9. package/src/components/intercept-context.ts +0 -19
  10. package/src/components/intercept-requests.tsx +0 -67
  11. package/src/components/track-data.tsx +0 -28
  12. package/src/hooks/__tests__/__snapshots__/use-shared-cache.test.ts.snap +0 -17
  13. package/src/hooks/__tests__/use-cached-effect.test.tsx +0 -789
  14. package/src/hooks/__tests__/use-gql-router-context.test.tsx +0 -132
  15. package/src/hooks/__tests__/use-gql.test.tsx +0 -204
  16. package/src/hooks/__tests__/use-hydratable-effect.test.ts +0 -708
  17. package/src/hooks/__tests__/use-request-interception.test.tsx +0 -254
  18. package/src/hooks/__tests__/use-server-effect.test.ts +0 -293
  19. package/src/hooks/__tests__/use-shared-cache.test.ts +0 -263
  20. package/src/hooks/use-cached-effect.ts +0 -297
  21. package/src/hooks/use-gql-router-context.ts +0 -49
  22. package/src/hooks/use-gql.ts +0 -58
  23. package/src/hooks/use-hydratable-effect.ts +0 -201
  24. package/src/hooks/use-request-interception.ts +0 -53
  25. package/src/hooks/use-server-effect.ts +0 -75
  26. package/src/hooks/use-shared-cache.ts +0 -107
  27. package/src/index.ts +0 -46
  28. package/src/util/__tests__/__snapshots__/scoped-in-memory-cache.test.ts.snap +0 -19
  29. package/src/util/__tests__/__snapshots__/serializable-in-memory-cache.test.ts.snap +0 -19
  30. package/src/util/__tests__/get-gql-data-from-response.test.ts +0 -186
  31. package/src/util/__tests__/get-gql-request-id.test.ts +0 -132
  32. package/src/util/__tests__/graphql-document-node-parser.test.ts +0 -535
  33. package/src/util/__tests__/hydration-cache-api.test.ts +0 -34
  34. package/src/util/__tests__/merge-gql-context.test.ts +0 -73
  35. package/src/util/__tests__/purge-caches.test.ts +0 -28
  36. package/src/util/__tests__/request-api.test.ts +0 -176
  37. package/src/util/__tests__/request-fulfillment.test.ts +0 -146
  38. package/src/util/__tests__/request-tracking.test.tsx +0 -321
  39. package/src/util/__tests__/result-from-cache-response.test.ts +0 -79
  40. package/src/util/__tests__/scoped-in-memory-cache.test.ts +0 -316
  41. package/src/util/__tests__/serializable-in-memory-cache.test.ts +0 -397
  42. package/src/util/__tests__/ssr-cache.test.ts +0 -636
  43. package/src/util/__tests__/to-gql-operation.test.ts +0 -41
  44. package/src/util/data-error.ts +0 -63
  45. package/src/util/get-gql-data-from-response.ts +0 -65
  46. package/src/util/get-gql-request-id.ts +0 -106
  47. package/src/util/gql-error.ts +0 -43
  48. package/src/util/gql-router-context.ts +0 -9
  49. package/src/util/gql-types.ts +0 -64
  50. package/src/util/graphql-document-node-parser.ts +0 -132
  51. package/src/util/graphql-types.ts +0 -28
  52. package/src/util/hydration-cache-api.ts +0 -30
  53. package/src/util/merge-gql-context.ts +0 -35
  54. package/src/util/purge-caches.ts +0 -14
  55. package/src/util/request-api.ts +0 -65
  56. package/src/util/request-fulfillment.ts +0 -121
  57. package/src/util/request-tracking.ts +0 -211
  58. package/src/util/result-from-cache-response.ts +0 -30
  59. package/src/util/scoped-in-memory-cache.ts +0 -121
  60. package/src/util/serializable-in-memory-cache.ts +0 -44
  61. package/src/util/ssr-cache.ts +0 -193
  62. package/src/util/status.ts +0 -35
  63. package/src/util/to-gql-operation.ts +0 -43
  64. package/src/util/types.ts +0 -145
  65. package/tsconfig-build.json +0 -12
  66. package/tsconfig-build.tsbuildinfo +0 -1
@@ -1,789 +0,0 @@
1
- import * as React from "react";
2
- import {
3
- renderHook as clientRenderHook,
4
- act,
5
- } from "@testing-library/react-hooks";
6
- import {renderHookStatic} from "@khanacademy/wonder-blocks-testing-core";
7
- import {render, act as reactAct} from "@testing-library/react";
8
- import {values} from "@khanacademy/wonder-stuff-core";
9
-
10
- import {Server} from "@khanacademy/wonder-blocks-core";
11
- import {Status} from "../../util/status";
12
-
13
- import {RequestFulfillment} from "../../util/request-fulfillment";
14
- import * as UseRequestInterception from "../use-request-interception";
15
- import * as UseSharedCache from "../use-shared-cache";
16
-
17
- import {useCachedEffect} from "../use-cached-effect";
18
-
19
- import {FetchPolicy} from "../../util/types";
20
-
21
- jest.mock("../use-request-interception");
22
- jest.mock("../use-shared-cache");
23
-
24
- const allPolicies = Array.from(values(FetchPolicy));
25
- const allPoliciesBut = (
26
- ...policies: Array<typeof FetchPolicy[keyof typeof FetchPolicy]>
27
- ) => allPolicies.filter((p: any) => !policies.includes(p));
28
-
29
- describe("#useCachedEffect", () => {
30
- beforeEach(() => {
31
- jest.resetAllMocks();
32
-
33
- // Clear out inflight requests between tests.
34
- RequestFulfillment.Default.abortAll();
35
-
36
- // Simple implementation of request interception that just returns
37
- // the handler.
38
- jest.spyOn(
39
- UseRequestInterception,
40
- "useRequestInterception",
41
- ).mockImplementation((_: any, handler: any) => handler);
42
-
43
- // We need the cache to work a little so that we get our result.
44
- const cache: Record<string, any> = {};
45
- jest.spyOn(UseSharedCache, "useSharedCache").mockImplementation(
46
- (id: any, _: any, defaultValue: any) => {
47
- const setCache = React.useCallback(
48
- (v: any) => (cache[id] = v),
49
- [id],
50
- );
51
- return [cache[id] ?? defaultValue, setCache];
52
- },
53
- );
54
- });
55
-
56
- describe("when server-side", () => {
57
- beforeEach(() => {
58
- jest.spyOn(Server, "isServerSide").mockReturnValue(true);
59
- });
60
-
61
- it("should call useRequestInterception", () => {
62
- // Arrange
63
- const useRequestInterceptSpy = jest
64
- .spyOn(UseRequestInterception, "useRequestInterception")
65
- .mockReturnValue(jest.fn());
66
- const fakeHandler = jest.fn();
67
-
68
- // Act
69
- renderHookStatic(() => useCachedEffect("ID", fakeHandler));
70
-
71
- // Assert
72
- expect(useRequestInterceptSpy).toHaveBeenCalledWith(
73
- "ID",
74
- fakeHandler,
75
- );
76
- });
77
-
78
- it.each`
79
- scope | expectedScope
80
- ${undefined} | ${"useCachedEffect"}
81
- ${"foo"} | ${"foo"}
82
- `(
83
- "should call useSharedCache with id, scope=$scope, without a default",
84
- ({scope, cachedResult, expectedScope}: any) => {
85
- const fakeHandler = jest.fn();
86
- const useSharedCacheSpy = jest.spyOn(
87
- UseSharedCache,
88
- "useSharedCache",
89
- );
90
-
91
- // Act
92
- renderHookStatic(() =>
93
- useCachedEffect("ID", fakeHandler, {scope}),
94
- );
95
-
96
- // Assert
97
- expect(useSharedCacheSpy).toHaveBeenCalledWith(
98
- "ID",
99
- expectedScope,
100
- );
101
- },
102
- );
103
-
104
- it.each(allPolicies)(
105
- "should not request data for FetchPolicy.%s",
106
- (fetchPolicy: any) => {
107
- // Arrange
108
- const fakeHandler = jest.fn().mockResolvedValue("data");
109
-
110
- // Act
111
- renderHookStatic(() =>
112
- useCachedEffect("ID", fakeHandler, {fetchPolicy}),
113
- );
114
-
115
- // Assert
116
- expect(fakeHandler).not.toHaveBeenCalled();
117
- },
118
- );
119
-
120
- describe.each(allPoliciesBut(FetchPolicy.CacheOnly))(
121
- "with FetchPolicy.%s without cached result",
122
- (fetchPolicy: any) => {
123
- it("should return a loading result", () => {
124
- // Arrange
125
- const fakeHandler = jest.fn();
126
-
127
- // Act
128
- const {
129
- result: {
130
- current: [result],
131
- },
132
- } = renderHookStatic(() =>
133
- useCachedEffect("ID", fakeHandler, {fetchPolicy}),
134
- );
135
-
136
- // Assert
137
- expect(result).toStrictEqual(Status.loading());
138
- });
139
- },
140
- );
141
-
142
- describe("with FetchPolicy.CacheOnly without cached result", () => {
143
- it("should return a no-data result", () => {
144
- // Arrange
145
- const fakeHandler = jest.fn();
146
-
147
- // Act
148
- const {
149
- result: {
150
- current: [result],
151
- },
152
- } = renderHookStatic(() =>
153
- useCachedEffect("ID", fakeHandler, {
154
- fetchPolicy: FetchPolicy.CacheOnly,
155
- }),
156
- );
157
-
158
- // Assert
159
- expect(result).toStrictEqual(Status.noData());
160
- });
161
- });
162
-
163
- describe.each(allPoliciesBut(FetchPolicy.NetworkOnly))(
164
- "with FetchPolicy.%s with cached result",
165
- (fetchPolicy: any) => {
166
- it("should return the result", () => {
167
- // Arrange
168
- const fakeHandler = jest.fn();
169
- const cachedResult = Status.success("data");
170
- jest.spyOn(
171
- UseSharedCache,
172
- "useSharedCache",
173
- ).mockReturnValue([cachedResult, jest.fn()]);
174
-
175
- // Act
176
- const {
177
- result: {
178
- current: [result],
179
- },
180
- } = renderHookStatic(() =>
181
- useCachedEffect("ID", fakeHandler, {fetchPolicy}),
182
- );
183
-
184
- // Assert
185
- expect(result).toEqual(cachedResult);
186
- });
187
- },
188
- );
189
-
190
- describe("with FetchPolicy.NetworkOnly with cached result", () => {
191
- it("should return a loading result", () => {
192
- // Arrange
193
- const fakeHandler = jest.fn();
194
- jest.spyOn(UseSharedCache, "useSharedCache").mockReturnValue([
195
- Status.success("data"),
196
- jest.fn(),
197
- ]);
198
-
199
- // Act
200
- const {
201
- result: {
202
- current: [result],
203
- },
204
- } = renderHookStatic(() =>
205
- useCachedEffect("ID", fakeHandler, {
206
- fetchPolicy: FetchPolicy.NetworkOnly,
207
- }),
208
- );
209
-
210
- // Assert
211
- expect(result).toStrictEqual(Status.loading());
212
- });
213
- });
214
- });
215
-
216
- describe("when client-side", () => {
217
- beforeEach(() => {
218
- jest.spyOn(Server, "isServerSide").mockReturnValue(false);
219
- });
220
-
221
- it("should call useRequestInterception", () => {
222
- // Arrange
223
- const useRequestInterceptSpy = jest
224
- .spyOn(UseRequestInterception, "useRequestInterception")
225
- .mockReturnValue(jest.fn());
226
- const fakeHandler = jest.fn();
227
-
228
- // Act
229
- clientRenderHook(() => useCachedEffect("ID", fakeHandler));
230
-
231
- // Assert
232
- expect(useRequestInterceptSpy).toHaveBeenCalledWith(
233
- "ID",
234
- fakeHandler,
235
- );
236
- });
237
-
238
- it("should share inflight requests for the same requestId", () => {
239
- // Arrange
240
- const pending = new Promise((resolve: any, reject: any) => {
241
- /*pending*/
242
- });
243
- const fakeHandler = jest.fn().mockReturnValue(pending);
244
-
245
- // Act
246
- clientRenderHook(() => useCachedEffect("ID", fakeHandler));
247
- clientRenderHook(() => useCachedEffect("ID", fakeHandler));
248
-
249
- // Assert
250
- expect(fakeHandler).toHaveBeenCalledTimes(1);
251
- });
252
-
253
- it.each(allPoliciesBut(FetchPolicy.CacheOnly))(
254
- "should provide function that causes refetch with FetchPolicy.%s",
255
- async (fetchPolicy: any) => {
256
- // Arrange
257
- const response: any = Promise.resolve("DATA1");
258
- const fakeHandler = jest.fn().mockReturnValue(response);
259
-
260
- // Act
261
- const {
262
- result: {
263
- current: [, refetch],
264
- },
265
- } = clientRenderHook(() =>
266
- useCachedEffect("ID", fakeHandler, {fetchPolicy}),
267
- );
268
- fakeHandler.mockClear();
269
- await act(() => response);
270
- act(refetch);
271
- await act(() => response);
272
-
273
- // Assert
274
- expect(fakeHandler).toHaveBeenCalledTimes(1);
275
- },
276
- );
277
-
278
- it("should throw with FetchPolicy.CacheOnly", () => {
279
- // Arrange
280
- const fakeHandler = jest.fn();
281
-
282
- // Act
283
- const {
284
- result: {
285
- current: [, refetch],
286
- },
287
- } = clientRenderHook(() =>
288
- useCachedEffect("ID", fakeHandler, {
289
- fetchPolicy: FetchPolicy.CacheOnly,
290
- }),
291
- );
292
- const underTest = () => refetch();
293
-
294
- // Assert
295
- expect(underTest).toThrowErrorMatchingInlineSnapshot(
296
- `"Cannot fetch with CacheOnly policy"`,
297
- );
298
- });
299
-
300
- it.each(allPoliciesBut(FetchPolicy.CacheOnly))(
301
- "should fulfill request when there is no cached value and FetchPolicy.%s",
302
- (fetchPolicy: any) => {
303
- // Arrange
304
- const fakeHandler = jest.fn();
305
- jest.spyOn(UseSharedCache, "useSharedCache").mockReturnValue([
306
- null,
307
- jest.fn(),
308
- ]);
309
-
310
- // Act
311
- clientRenderHook(() =>
312
- useCachedEffect("ID", fakeHandler, {fetchPolicy}),
313
- );
314
-
315
- // Assert
316
- expect(fakeHandler).toHaveBeenCalled();
317
- },
318
- );
319
-
320
- it.each([FetchPolicy.CacheAndNetwork, FetchPolicy.NetworkOnly])(
321
- "should fulfill request when there is a cached value and FetchPolicy.%s",
322
- (fetchPolicy: any) => {
323
- // Arrange
324
- const fakeHandler = jest.fn();
325
- jest.spyOn(UseSharedCache, "useSharedCache").mockReturnValue([
326
- Status.success("data"),
327
- jest.fn(),
328
- ]);
329
-
330
- // Act
331
- clientRenderHook(() =>
332
- useCachedEffect("ID", fakeHandler, {
333
- fetchPolicy,
334
- }),
335
- );
336
-
337
- // Assert
338
- expect(fakeHandler).toHaveBeenCalled();
339
- },
340
- );
341
-
342
- it.each`
343
- cachedResult
344
- ${Status.error(new Error("some error"))}
345
- ${Status.success("data")}
346
- ${Status.aborted()}
347
- `(
348
- "should not fulfill request when there is a cached response of $cachedResult and FetchPolicy.CacheBeforeNetwork",
349
- ({cachedResult}: any) => {
350
- const fakeHandler = jest.fn();
351
- jest.spyOn(UseSharedCache, "useSharedCache").mockReturnValue([
352
- cachedResult,
353
- jest.fn(),
354
- ]);
355
-
356
- // Act
357
- clientRenderHook(() =>
358
- useCachedEffect("ID", fakeHandler, {
359
- fetchPolicy: FetchPolicy.CacheBeforeNetwork,
360
- }),
361
- );
362
-
363
- // Assert
364
- expect(fakeHandler).not.toHaveBeenCalled();
365
- },
366
- );
367
-
368
- it.each`
369
- cachedResult
370
- ${null}
371
- ${Status.error(new Error("some error"))}
372
- ${Status.success("data")}
373
- ${Status.aborted()}
374
- `(
375
- "should not fulfill request when there is a cached response of $cachedResult and FetchPolicy.CacheOnly",
376
- ({cachedResult}: any) => {
377
- const fakeHandler = jest.fn();
378
- jest.spyOn(UseSharedCache, "useSharedCache").mockReturnValue([
379
- cachedResult,
380
- jest.fn(),
381
- ]);
382
-
383
- // Act
384
- clientRenderHook(() =>
385
- useCachedEffect("ID", fakeHandler, {
386
- fetchPolicy: FetchPolicy.CacheOnly,
387
- }),
388
- );
389
-
390
- // Assert
391
- expect(fakeHandler).not.toHaveBeenCalled();
392
- },
393
- );
394
-
395
- it("should fulfill request once-only if requestId does not change", async () => {
396
- // Arrange
397
- const fakeHandler = jest.fn().mockResolvedValue("data");
398
-
399
- // Act
400
- const {rerender, waitForNextUpdate} = clientRenderHook(() =>
401
- useCachedEffect("ID", fakeHandler),
402
- );
403
- rerender();
404
- await waitForNextUpdate();
405
-
406
- // Assert
407
- expect(fakeHandler).toHaveBeenCalledTimes(1);
408
- });
409
-
410
- it("should fulfill request again if requestId changes", async () => {
411
- // Arrange
412
- const fakeHandler = jest.fn().mockResolvedValue("data");
413
-
414
- // Act
415
- const {rerender, waitForNextUpdate} = clientRenderHook(
416
- ({requestId}: any) => useCachedEffect(requestId, fakeHandler),
417
- {
418
- initialProps: {requestId: "ID"},
419
- },
420
- );
421
- rerender({requestId: "ID2"});
422
- await waitForNextUpdate();
423
-
424
- // Assert
425
- expect(fakeHandler).toHaveBeenCalledTimes(2);
426
- });
427
-
428
- it("should update shared cache with result when request is fulfilled", async () => {
429
- // Arrange
430
- const setCacheFn = jest.fn();
431
- jest.spyOn(UseSharedCache, "useSharedCache").mockReturnValue([
432
- null,
433
- setCacheFn,
434
- ]);
435
- const fakeHandler = jest.fn().mockResolvedValue("DATA");
436
-
437
- // Act
438
- const {waitForNextUpdate} = clientRenderHook(() =>
439
- useCachedEffect("ID", fakeHandler),
440
- );
441
- await waitForNextUpdate();
442
-
443
- // Assert
444
- expect(setCacheFn).toHaveBeenCalledWith(Status.success("DATA"));
445
- });
446
-
447
- it("should ignore inflight request if requestId changes", async () => {
448
- // Arrange
449
- const response1: any = Promise.resolve("DATA1");
450
- const response2 = Promise.resolve("DATA2");
451
- const fakeHandler = jest
452
- .fn()
453
- .mockReturnValueOnce(response1)
454
- .mockReturnValueOnce(response2);
455
-
456
- // Act
457
- const {rerender, result} = clientRenderHook(
458
- ({requestId}: any) => useCachedEffect(requestId, fakeHandler),
459
- {
460
- initialProps: {requestId: "ID"},
461
- },
462
- );
463
- rerender({requestId: "ID2"});
464
- await act((): Promise<any> => Promise.all([response1, response2]));
465
-
466
- // Assert
467
- expect(result.all).not.toContainEqual(Status.success("DATA1"));
468
- });
469
-
470
- it("should return result of fulfilled request for current requestId", async () => {
471
- // Arrange
472
- const response1: any = Promise.resolve("DATA1");
473
- const response2 = Promise.resolve("DATA2");
474
- const fakeHandler = jest
475
- .fn()
476
- .mockReturnValueOnce(response1)
477
- .mockReturnValueOnce(response2);
478
-
479
- // Act
480
- const {rerender, result} = clientRenderHook(
481
- ({requestId}: any) => useCachedEffect(requestId, fakeHandler),
482
- {
483
- initialProps: {requestId: "ID"},
484
- },
485
- );
486
- rerender({requestId: "ID2"});
487
- await act((): Promise<any> => Promise.all([response1, response2]));
488
-
489
- // Assert
490
- expect(result.current[0]).toStrictEqual(Status.success("DATA2"));
491
- });
492
-
493
- it("should not fulfill request when skip is true", () => {
494
- // Arrange
495
- const fakeHandler = jest.fn();
496
-
497
- // Act
498
- clientRenderHook(() =>
499
- useCachedEffect("ID", fakeHandler, {skip: true}),
500
- );
501
-
502
- // Assert
503
- expect(fakeHandler).not.toHaveBeenCalled();
504
- });
505
-
506
- it("should ignore result of inflight request if skip changes", async () => {
507
- // Arrange
508
- const response1: any = Promise.resolve("DATA1");
509
- const fakeHandler = jest.fn().mockReturnValueOnce(response1);
510
-
511
- // Act
512
- const {rerender, result} = clientRenderHook(
513
- ({skip}: any) => useCachedEffect("ID", fakeHandler, {skip}),
514
- {
515
- initialProps: {skip: false},
516
- },
517
- );
518
- rerender({skip: true});
519
- await act(() => response1);
520
-
521
- // Assert
522
- expect(result.all).not.toContainEqual(Status.success("DATA1"));
523
- });
524
-
525
- it("should not ignore result of inflight request if handler changes", async () => {
526
- // Arrange
527
- const response1: any = Promise.resolve("DATA1");
528
- const response2 = Promise.resolve("DATA2");
529
- const fakeHandler1 = jest.fn().mockReturnValueOnce(response1);
530
- const fakeHandler2 = jest.fn().mockReturnValueOnce(response2);
531
-
532
- // Act
533
- const {rerender, result} = clientRenderHook(
534
- ({handler}: any) => useCachedEffect("ID", handler),
535
- {
536
- initialProps: {handler: fakeHandler1},
537
- },
538
- );
539
- rerender({handler: fakeHandler2});
540
- await act((): Promise<any> => Promise.all([response1, response2]));
541
-
542
- // Assert
543
- expect(result.current[0]).toStrictEqual(Status.success("DATA1"));
544
- });
545
-
546
- it("should not ignore inflight request if options (other than skip) change", async () => {
547
- // Arrange
548
- const response1: any = Promise.resolve("DATA1");
549
- const fakeHandler = jest.fn().mockReturnValueOnce(response1);
550
-
551
- // Act
552
- const {rerender, result} = clientRenderHook(
553
- ({options}: any) => useCachedEffect("ID", fakeHandler),
554
- {
555
- initialProps: {options: undefined},
556
- },
557
- );
558
- rerender({
559
- options: {
560
- scope: "BLAH!",
561
- },
562
- } as any);
563
- await act(() => response1);
564
-
565
- // Assert
566
- expect(result.current[0]).toStrictEqual(Status.success("DATA1"));
567
- });
568
-
569
- it("should return previous result when requestId changes and retainResultOnChange is true", async () => {
570
- // Arrange
571
- const response1: any = Promise.resolve("DATA1");
572
- const response2 = Promise.resolve("DATA2");
573
- const fakeHandler = jest
574
- .fn()
575
- .mockReturnValueOnce(response1)
576
- .mockReturnValueOnce(response2);
577
-
578
- // Act
579
- const {
580
- rerender,
581
- result: hookResult,
582
- waitForNextUpdate,
583
- } = clientRenderHook(
584
- ({requestId}: any) =>
585
- useCachedEffect(requestId, fakeHandler, {
586
- retainResultOnChange: true,
587
- }),
588
- {
589
- initialProps: {requestId: "ID"},
590
- },
591
- );
592
- await act(() => response1);
593
- rerender({requestId: "ID2"});
594
- const [result] = hookResult.current;
595
- await waitForNextUpdate();
596
-
597
- // Assert
598
- expect(result).toStrictEqual(Status.success("DATA1"));
599
- });
600
-
601
- it("should return loading status when requestId changes and retainResultOnChange is false", async () => {
602
- // Arrange
603
- const response1: any = Promise.resolve("DATA1");
604
- const response2 = new Promise(() => {
605
- /*pending*/
606
- });
607
- const fakeHandler = jest
608
- .fn()
609
- .mockReturnValueOnce(response1)
610
- .mockReturnValueOnce(response2);
611
-
612
- // Act
613
- const {rerender, result} = clientRenderHook(
614
- ({requestId}: any) =>
615
- useCachedEffect(requestId, fakeHandler, {
616
- retainResultOnChange: false,
617
- }),
618
- {
619
- initialProps: {requestId: "ID"},
620
- },
621
- );
622
- await act(() => response1);
623
- rerender({requestId: "ID2"});
624
-
625
- // Assert
626
- expect(result.current[0]).toStrictEqual(Status.loading());
627
- });
628
-
629
- it("should return no-data status when requestId changes, retainResultOnChange is false, and skip is true", async () => {
630
- // Arrange
631
- const response1: any = Promise.resolve("DATA1");
632
- const response2 = new Promise(() => {
633
- /*pending*/
634
- });
635
- const fakeHandler = jest
636
- .fn()
637
- .mockReturnValueOnce(response1)
638
- .mockReturnValueOnce(response2);
639
-
640
- // Act
641
- const {rerender, result} = clientRenderHook(
642
- ({requestId}: any) =>
643
- useCachedEffect(requestId, fakeHandler, {
644
- retainResultOnChange: false,
645
- skip: true,
646
- }),
647
- {
648
- initialProps: {requestId: "ID"},
649
- },
650
- );
651
- await act(() => response1);
652
- rerender({requestId: "ID2"});
653
-
654
- // Assert
655
- expect(result.current[0]).toStrictEqual(Status.noData());
656
- });
657
-
658
- it.each(allPoliciesBut(FetchPolicy.CacheOnly))(
659
- "should trigger render when request is fulfilled and onResultChanged is undefined for FetchPolicy.%s",
660
- async (fetchPolicy: any) => {
661
- // Arrange
662
- const response: any = Promise.resolve("DATA");
663
- const fakeHandler = jest.fn().mockReturnValue(response);
664
- let renderCount = 0;
665
- const Component = React.memo(() => {
666
- useCachedEffect("ID", fakeHandler, {fetchPolicy});
667
- renderCount++;
668
- return <div>Hello :)</div>;
669
- });
670
-
671
- // Act
672
- render(<Component />);
673
- await reactAct(() => response);
674
-
675
- // Assert
676
- expect(renderCount).toBe(2);
677
- },
678
- );
679
-
680
- it.each(allPoliciesBut(FetchPolicy.CacheOnly))(
681
- "should trigger render once per inflight request being fulfilled and onResultChanged is undefined for FetchPolicy.%s",
682
- async (fetchPolicy: any) => {
683
- // Arrange
684
- const response: any = Promise.resolve("DATA");
685
- const fakeHandler = jest.fn().mockReturnValue(response);
686
- let renderCount = 0;
687
- const Component = React.memo(() => {
688
- const [, refetch] = useCachedEffect("ID", fakeHandler, {
689
- fetchPolicy,
690
- });
691
- React.useEffect(() => {
692
- refetch();
693
- refetch();
694
- refetch();
695
- refetch();
696
- }, [refetch]);
697
- renderCount++;
698
- return <div>Hello :)</div>;
699
- });
700
-
701
- // Act
702
- render(<Component />);
703
- await reactAct(() => response);
704
-
705
- // Assert
706
- expect(renderCount).toBe(2);
707
- },
708
- );
709
-
710
- it.each(allPoliciesBut(FetchPolicy.CacheOnly))(
711
- "should not trigger render when request is fulfilled and onResultChanged is defined for FetchPolicy.%s",
712
- async (fetchPolicy: any) => {
713
- // Arrange
714
- const response: any = Promise.resolve("DATA");
715
- const fakeHandler = jest.fn().mockReturnValue(response);
716
- let renderCount = 0;
717
- const Component = React.memo(() => {
718
- useCachedEffect("ID", fakeHandler, {
719
- onResultChanged: () => {},
720
- fetchPolicy,
721
- });
722
- renderCount++;
723
- return <div>Hello :)</div>;
724
- });
725
-
726
- // Act
727
- render(<Component />);
728
- await reactAct(() => response);
729
-
730
- // Assert
731
- expect(renderCount).toBe(1);
732
- },
733
- );
734
-
735
- it.each(allPoliciesBut(FetchPolicy.CacheOnly))(
736
- "should call onResultChanged when request is fulfilled and onResultChanged is defined for FetchPolicy.%s",
737
- async (fetchPolicy: any) => {
738
- // Arrange
739
- const response: any = Promise.resolve("DATA");
740
- const fakeHandler = jest.fn().mockReturnValue(response);
741
- const onResultChanged = jest.fn();
742
-
743
- // Act
744
- clientRenderHook(() =>
745
- useCachedEffect("ID", fakeHandler, {
746
- onResultChanged,
747
- fetchPolicy,
748
- }),
749
- );
750
- await act(() => response);
751
-
752
- // Assert
753
- expect(onResultChanged).toHaveBeenCalledWith(
754
- Status.success("DATA"),
755
- );
756
- },
757
- );
758
-
759
- it.each(allPoliciesBut(FetchPolicy.CacheOnly))(
760
- "should call onResultChanged once per inflight request being fulfilled and onResultChanged is defined for FetchPolicy.%s",
761
- async (fetchPolicy: any) => {
762
- // Arrange
763
- const response: any = Promise.resolve("DATA");
764
- const fakeHandler = jest.fn().mockReturnValue(response);
765
- const onResultChanged = jest.fn();
766
-
767
- // Act
768
- const {
769
- result: {
770
- current: [, refetch],
771
- },
772
- } = clientRenderHook(() =>
773
- useCachedEffect("ID", fakeHandler, {
774
- onResultChanged,
775
- fetchPolicy,
776
- }),
777
- );
778
- act(refetch);
779
- act(refetch);
780
- act(refetch);
781
- act(refetch);
782
- await act(() => response);
783
-
784
- // Assert
785
- expect(onResultChanged).toHaveBeenCalledTimes(1);
786
- },
787
- );
788
- });
789
- });