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