@khanacademy/wonder-blocks-data 2.3.4 → 3.1.1

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 (48) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/es/index.js +368 -429
  3. package/dist/index.js +457 -460
  4. package/docs.md +19 -13
  5. package/package.json +3 -3
  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 -117
  13. package/src/components/data.md +38 -60
  14. package/src/components/gql-router.js +66 -0
  15. package/src/components/intercept-data.js +2 -34
  16. package/src/components/intercept-data.md +7 -105
  17. package/src/hooks/__tests__/use-data.test.js +826 -0
  18. package/src/hooks/__tests__/use-gql.test.js +233 -0
  19. package/src/hooks/use-data.js +143 -0
  20. package/src/hooks/use-gql.js +77 -0
  21. package/src/index.js +13 -9
  22. package/src/util/__tests__/get-gql-data-from-response.test.js +187 -0
  23. package/src/util/__tests__/memory-cache.test.js +134 -35
  24. package/src/util/__tests__/request-fulfillment.test.js +21 -36
  25. package/src/util/__tests__/request-handler.test.js +30 -30
  26. package/src/util/__tests__/request-tracking.test.js +29 -30
  27. package/src/util/__tests__/response-cache.test.js +521 -561
  28. package/src/util/__tests__/result-from-cache-entry.test.js +68 -0
  29. package/src/util/get-gql-data-from-response.js +69 -0
  30. package/src/util/gql-error.js +36 -0
  31. package/src/util/gql-router-context.js +6 -0
  32. package/src/util/gql-types.js +65 -0
  33. package/src/util/memory-cache.js +18 -14
  34. package/src/util/request-fulfillment.js +4 -0
  35. package/src/util/request-handler.js +2 -27
  36. package/src/util/request-handler.md +0 -32
  37. package/src/util/response-cache.js +50 -110
  38. package/src/util/result-from-cache-entry.js +38 -0
  39. package/src/util/types.js +14 -35
  40. package/LICENSE +0 -21
  41. package/src/components/__tests__/intercept-cache.test.js +0 -124
  42. package/src/components/__tests__/internal-data.test.js +0 -1030
  43. package/src/components/intercept-cache.js +0 -79
  44. package/src/components/intercept-cache.md +0 -103
  45. package/src/components/internal-data.js +0 -219
  46. package/src/util/__tests__/no-cache.test.js +0 -112
  47. package/src/util/no-cache.js +0 -67
  48. package/src/util/no-cache.md +0 -66
@@ -18,6 +18,29 @@ describe("../response-cache.js", () => {
18
18
  jest.restoreAllMocks();
19
19
  });
20
20
 
21
+ describe("@Default", () => {
22
+ it("should return an instance of ResponseCache", () => {
23
+ // Arrange
24
+
25
+ // Act
26
+ const result = ResponseCache.Default;
27
+
28
+ // Assert
29
+ expect(result).toBeInstanceOf(ResponseCache);
30
+ });
31
+
32
+ it("should return the same instance on each call", () => {
33
+ // Arrange
34
+
35
+ // Act
36
+ const result1 = ResponseCache.Default;
37
+ const result2 = ResponseCache.Default;
38
+
39
+ // Assert
40
+ expect(result1).toBe(result2);
41
+ });
42
+ });
43
+
21
44
  describe("#initialize", () => {
22
45
  it("should initialize the cache with the given data", () => {
23
46
  // Arrange
@@ -25,9 +48,7 @@ describe("../response-cache.js", () => {
25
48
  const fakeHandler: IRequestHandler<string, string> = {
26
49
  getKey: () => "MY_KEY",
27
50
  type: "MY_HANDLER",
28
- shouldRefreshCache: () => false,
29
51
  fulfillRequest: jest.fn(),
30
- cache: null,
31
52
  hydrate: true,
32
53
  };
33
54
 
@@ -89,9 +110,7 @@ describe("../response-cache.js", () => {
89
110
  const fakeHandler: IRequestHandler<string, string> = {
90
111
  getKey: () => "MY_KEY",
91
112
  type: "MY_HANDLER",
92
- shouldRefreshCache: () => false,
93
113
  fulfillRequest: jest.fn(),
94
- cache: null,
95
114
  hydrate: true,
96
115
  };
97
116
  const sourceData = {
@@ -112,398 +131,372 @@ describe("../response-cache.js", () => {
112
131
  });
113
132
 
114
133
  describe("#cacheData", () => {
115
- describe("no custom cache", () => {
116
- it("should store the entry in the framework cache", () => {
134
+ describe("when client-side", () => {
135
+ it("should not store the entry in the hydration cache", () => {
117
136
  // Arrange
118
- const internalCache = new MemoryCache();
119
- jest.spyOn(internalCache, "store");
120
- const cache = new ResponseCache(internalCache);
137
+ const hydrationCache = new MemoryCache();
138
+ const cache = new ResponseCache(hydrationCache);
121
139
  const fakeHandler: IRequestHandler<string, string> = {
122
140
  getKey: () => "MY_KEY",
123
141
  type: "MY_HANDLER",
124
- shouldRefreshCache: () => false,
125
142
  fulfillRequest: jest.fn(),
126
- cache: null,
127
143
  hydrate: true,
128
144
  };
145
+ const hydrationStoreSpy = jest.spyOn(hydrationCache, "store");
129
146
 
130
147
  // Act
131
148
  cache.cacheData(fakeHandler, "options", "data");
132
149
 
133
150
  // Assert
134
- expect(internalCache.store).toHaveBeenCalledWith(
135
- fakeHandler,
136
- "options",
137
- {data: "data"},
138
- );
151
+ expect(hydrationStoreSpy).not.toHaveBeenCalled();
139
152
  });
140
- });
141
153
 
142
- describe("with custom cache", () => {
143
- it("SSR should use the framework cache, not the custom cache", () => {
154
+ it("should not store the entry in the ssrOnly cache", () => {
144
155
  // Arrange
145
- jest.spyOn(Server, "isServerSide").mockReturnValue(true);
146
- const internalCache = new MemoryCache();
147
- jest.spyOn(internalCache, "store");
148
- const cache = new ResponseCache(internalCache);
149
- const customCache = {
150
- store: jest.fn(),
151
- retrieve: jest.fn(),
152
- remove: jest.fn(),
153
- removeAll: jest.fn(),
154
- };
156
+ const hydrationCache = new MemoryCache();
157
+ const ssrOnlyCache = new MemoryCache();
158
+ const cache = new ResponseCache(hydrationCache, ssrOnlyCache);
155
159
  const fakeHandler: IRequestHandler<string, string> = {
156
160
  getKey: () => "MY_KEY",
157
161
  type: "MY_HANDLER",
158
- shouldRefreshCache: () => false,
159
162
  fulfillRequest: jest.fn(),
160
- cache: customCache,
161
163
  hydrate: true,
162
164
  };
165
+ const ssrOnlyStoreSpy = jest.spyOn(ssrOnlyCache, "store");
163
166
 
164
167
  // Act
165
168
  cache.cacheData(fakeHandler, "options", "data");
166
169
 
167
170
  // Assert
168
- expect(customCache.store).not.toHaveBeenCalled();
169
- expect(internalCache.store).toHaveBeenCalledWith(
170
- fakeHandler,
171
- "options",
172
- {data: "data"},
173
- );
171
+ expect(ssrOnlyStoreSpy).not.toHaveBeenCalled();
174
172
  });
173
+ });
175
174
 
176
- it("CSR should use the custom cache, not the framework cache", () => {
177
- // Arrange
178
- jest.spyOn(Server, "isServerSide").mockReturnValue(false);
179
- const internalCache = new MemoryCache();
180
- jest.spyOn(internalCache, "store");
181
- const cache = new ResponseCache(internalCache);
182
- const customCache = {
183
- store: jest.fn(),
184
- retrieve: jest.fn(),
185
- remove: jest.fn(),
186
- removeAll: jest.fn(),
187
- };
188
- const fakeHandler: IRequestHandler<string, string> = {
189
- getKey: () => "MY_KEY",
190
- type: "MY_HANDLER",
191
- shouldRefreshCache: () => false,
192
- fulfillRequest: jest.fn(),
193
- cache: customCache,
194
- hydrate: true,
195
- };
175
+ describe("when server-side", () => {
176
+ beforeEach(() => {
177
+ jest.spyOn(Server, "isServerSide").mockReturnValue(true);
178
+ });
196
179
 
197
- // Act
198
- cache.cacheData(fakeHandler, "options", "data");
180
+ describe("when the handler wants hydration", () => {
181
+ it("should store the entry in the hydration cache", () => {
182
+ // Arrange
183
+ const hydrationCache = new MemoryCache();
184
+ const cache = new ResponseCache(hydrationCache);
185
+ const fakeHandler: IRequestHandler<string, string> = {
186
+ getKey: () => "MY_KEY",
187
+ type: "MY_HANDLER",
188
+ fulfillRequest: jest.fn(),
189
+ hydrate: true,
190
+ };
191
+ const hydrationStoreSpy = jest.spyOn(
192
+ hydrationCache,
193
+ "store",
194
+ );
199
195
 
200
- // Assert
201
- expect(customCache.store).toHaveBeenCalledWith(
202
- fakeHandler,
203
- "options",
204
- {data: "data"},
205
- );
206
- expect(internalCache.store).not.toHaveBeenCalled();
207
- });
208
- });
196
+ // Act
197
+ cache.cacheData(fakeHandler, "options", "data");
209
198
 
210
- describe("no hydrate", () => {
211
- it("should store the entry in the ssr-only cache", () => {
212
- // Arrange
213
- jest.spyOn(Server, "isServerSide").mockReturnValue(true);
214
- const ssrOnlyCache = new MemoryCache();
215
- const internalCache = new MemoryCache();
216
- const storeSpy = jest.spyOn(ssrOnlyCache, "store");
217
- const cache = new ResponseCache(internalCache, ssrOnlyCache);
218
- const fakeHandler: IRequestHandler<string, string> = {
219
- getKey: () => "MY_KEY",
220
- type: "MY_HANDLER",
221
- shouldRefreshCache: () => false,
222
- fulfillRequest: jest.fn(),
223
- cache: null,
224
- hydrate: false,
225
- };
199
+ // Assert
200
+ expect(hydrationStoreSpy).toHaveBeenCalledWith(
201
+ fakeHandler,
202
+ "options",
203
+ {data: "data"},
204
+ );
205
+ });
226
206
 
227
- // Act
228
- cache.cacheData(fakeHandler, "options", "data");
207
+ it("should not store the entry in the ssrOnly cache", () => {
208
+ // Arrange
209
+ const hydrationCache = new MemoryCache();
210
+ const ssrOnlyCache = new MemoryCache();
211
+ const cache = new ResponseCache(
212
+ hydrationCache,
213
+ ssrOnlyCache,
214
+ );
215
+ const fakeHandler: IRequestHandler<string, string> = {
216
+ getKey: () => "MY_KEY",
217
+ type: "MY_HANDLER",
218
+ fulfillRequest: jest.fn(),
219
+ hydrate: true,
220
+ };
221
+ const ssrOnlyStoreSpy = jest.spyOn(ssrOnlyCache, "store");
229
222
 
230
- // Assert
231
- expect(storeSpy).toHaveBeenCalledWith(fakeHandler, "options", {
232
- data: "data",
223
+ // Act
224
+ cache.cacheData(fakeHandler, "options", "data");
225
+
226
+ // Assert
227
+ expect(ssrOnlyStoreSpy).not.toHaveBeenCalled();
233
228
  });
234
229
  });
235
230
 
236
- it("should not store the entry in the framework cache", () => {
237
- // Arrange
238
- jest.spyOn(Server, "isServerSide").mockReturnValue(true);
239
- const internalCache = new MemoryCache();
240
- jest.spyOn(internalCache, "store");
241
- const cache = new ResponseCache(internalCache);
242
- const fakeHandler: IRequestHandler<string, string> = {
243
- getKey: () => "MY_KEY",
244
- type: "MY_HANDLER",
245
- shouldRefreshCache: () => false,
246
- fulfillRequest: jest.fn(),
247
- cache: null,
248
- hydrate: false,
249
- };
231
+ describe("when the handler does not hydration", () => {
232
+ it("should store the entry in the ssr-only cache", () => {
233
+ // Arrange
234
+ const hydrationCache = new MemoryCache();
235
+ const ssrOnlyCache = new MemoryCache();
236
+ const cache = new ResponseCache(
237
+ hydrationCache,
238
+ ssrOnlyCache,
239
+ );
240
+ const fakeHandler: IRequestHandler<string, string> = {
241
+ getKey: () => "MY_KEY",
242
+ type: "MY_HANDLER",
243
+ fulfillRequest: jest.fn(),
244
+ hydrate: false,
245
+ };
246
+ const ssrOnlyStoreSpy = jest.spyOn(ssrOnlyCache, "store");
250
247
 
251
- // Act
252
- cache.cacheData(fakeHandler, "options", "data");
248
+ // Act
249
+ cache.cacheData(fakeHandler, "options", "data");
253
250
 
254
- // Assert
255
- expect(internalCache.store).not.toHaveBeenCalled();
256
- });
257
- });
258
- });
251
+ // Assert
252
+ expect(ssrOnlyStoreSpy).toHaveBeenCalledWith(
253
+ fakeHandler,
254
+ "options",
255
+ {
256
+ data: "data",
257
+ },
258
+ );
259
+ });
259
260
 
260
- describe("#cacheError", () => {
261
- describe("no custom cache", () => {
262
- it("should store the entry in the framework cache", () => {
263
- // Arrange
264
- const internalCache = new MemoryCache();
265
- jest.spyOn(internalCache, "store");
266
- const cache = new ResponseCache(internalCache);
267
- const fakeHandler: IRequestHandler<string, string> = {
268
- getKey: () => "MY_KEY",
269
- type: "MY_HANDLER",
270
- shouldRefreshCache: () => false,
271
- fulfillRequest: jest.fn(),
272
- cache: null,
273
- hydrate: true,
274
- };
261
+ it("should not store the entry in the hydration cache", () => {
262
+ // Arrange
263
+ const hydrationCache = new MemoryCache();
264
+ const ssrOnlyCache = new MemoryCache();
265
+ const cache = new ResponseCache(
266
+ hydrationCache,
267
+ ssrOnlyCache,
268
+ );
269
+ const fakeHandler: IRequestHandler<string, string> = {
270
+ getKey: () => "MY_KEY",
271
+ type: "MY_HANDLER",
272
+ fulfillRequest: jest.fn(),
273
+ hydrate: false,
274
+ };
275
+ const hydrationStoreSpy = jest.spyOn(
276
+ hydrationCache,
277
+ "store",
278
+ );
275
279
 
276
- // Act
277
- cache.cacheError(fakeHandler, "options", new Error("Ooops!"));
280
+ // Act
281
+ cache.cacheData(fakeHandler, "options", "data");
278
282
 
279
- // Assert
280
- expect(internalCache.store).toHaveBeenCalledWith(
281
- fakeHandler,
282
- "options",
283
- {error: "Ooops!"},
284
- );
283
+ // Assert
284
+ expect(hydrationStoreSpy).not.toHaveBeenCalled();
285
+ });
285
286
  });
286
287
  });
288
+ });
287
289
 
288
- describe("with custom cache", () => {
289
- it("SSR should use the framework cache, not the custom cache", () => {
290
+ describe("#cacheError", () => {
291
+ describe("when client-side", () => {
292
+ it("should not store the entry in the hydration cache", () => {
290
293
  // Arrange
291
- jest.spyOn(Server, "isServerSide").mockReturnValue(true);
292
- const internalCache = new MemoryCache();
293
- jest.spyOn(internalCache, "store");
294
- const cache = new ResponseCache(internalCache);
295
- const customCache = {
296
- store: jest.fn(),
297
- retrieve: jest.fn(),
298
- remove: jest.fn(),
299
- removeAll: jest.fn(),
300
- };
294
+ const hydrationCache = new MemoryCache();
295
+ const cache = new ResponseCache(hydrationCache);
301
296
  const fakeHandler: IRequestHandler<string, string> = {
302
297
  getKey: () => "MY_KEY",
303
298
  type: "MY_HANDLER",
304
- shouldRefreshCache: () => false,
305
299
  fulfillRequest: jest.fn(),
306
- cache: customCache,
307
300
  hydrate: true,
308
301
  };
302
+ const hydrationStoreSpy = jest.spyOn(hydrationCache, "store");
309
303
 
310
304
  // Act
311
305
  cache.cacheError(fakeHandler, "options", new Error("Ooops!"));
312
306
 
313
307
  // Assert
314
- expect(internalCache.store).toHaveBeenCalledWith(
315
- fakeHandler,
316
- "options",
317
- {error: "Ooops!"},
318
- );
319
- expect(customCache.store).not.toHaveBeenCalled();
308
+ expect(hydrationStoreSpy).not.toHaveBeenCalled();
320
309
  });
321
310
 
322
- it("CSR should use the custom cache, not the framework cache", () => {
311
+ it("should not store the entry in the ssrOnly cache", () => {
323
312
  // Arrange
324
- jest.spyOn(Server, "isServerSide").mockReturnValue(false);
325
- const internalCache = new MemoryCache();
326
- jest.spyOn(internalCache, "store");
327
- const cache = new ResponseCache(internalCache);
328
- const customCache = {
329
- store: jest.fn(),
330
- retrieve: jest.fn(),
331
- remove: jest.fn(),
332
- removeAll: jest.fn(),
333
- };
313
+ const hydrationCache = new MemoryCache();
314
+ const ssrOnlyCache = new MemoryCache();
315
+ const cache = new ResponseCache(hydrationCache, ssrOnlyCache);
334
316
  const fakeHandler: IRequestHandler<string, string> = {
335
317
  getKey: () => "MY_KEY",
336
318
  type: "MY_HANDLER",
337
- shouldRefreshCache: () => false,
338
319
  fulfillRequest: jest.fn(),
339
- cache: customCache,
340
320
  hydrate: true,
341
321
  };
322
+ const ssrOnlyStoreSpy = jest.spyOn(ssrOnlyCache, "store");
342
323
 
343
324
  // Act
344
- cache.cacheError(fakeHandler, "options", new Error("Ooops!"));
325
+ cache.cacheError(fakeHandler, "options", "Ooops!");
345
326
 
346
327
  // Assert
347
- expect(customCache.store).toHaveBeenCalledWith(
348
- fakeHandler,
349
- "options",
350
- {error: "Ooops!"},
351
- );
352
- expect(internalCache.store).not.toHaveBeenCalled();
328
+ expect(ssrOnlyStoreSpy).not.toHaveBeenCalled();
353
329
  });
354
330
  });
355
331
 
356
- describe("no hydrate", () => {
357
- it("should store the entry in the ssr-only cache", () => {
358
- // Arrange
332
+ describe("when server-side", () => {
333
+ beforeEach(() => {
359
334
  jest.spyOn(Server, "isServerSide").mockReturnValue(true);
360
- const ssrOnlyCache = new MemoryCache();
361
- const internalCache = new MemoryCache();
362
- const storeSpy = jest.spyOn(ssrOnlyCache, "store");
363
- const cache = new ResponseCache(internalCache, ssrOnlyCache);
364
- const fakeHandler: IRequestHandler<string, string> = {
365
- getKey: () => "MY_KEY",
366
- type: "MY_HANDLER",
367
- shouldRefreshCache: () => false,
368
- fulfillRequest: jest.fn(),
369
- cache: null,
370
- hydrate: false,
371
- };
335
+ });
372
336
 
373
- // Act
374
- cache.cacheError(fakeHandler, "options", new Error("Ooops!"));
337
+ describe("when the handler wants hydration", () => {
338
+ it("should store the entry in the hydration cache", () => {
339
+ // Arrange
340
+ const hydrationCache = new MemoryCache();
341
+ const cache = new ResponseCache(hydrationCache);
342
+ const fakeHandler: IRequestHandler<string, string> = {
343
+ getKey: () => "MY_KEY",
344
+ type: "MY_HANDLER",
345
+ fulfillRequest: jest.fn(),
346
+ hydrate: true,
347
+ };
348
+ const hydrationStoreSpy = jest.spyOn(
349
+ hydrationCache,
350
+ "store",
351
+ );
375
352
 
376
- // Assert
377
- expect(storeSpy).toHaveBeenCalledWith(fakeHandler, "options", {
378
- error: "Ooops!",
353
+ // Act
354
+ cache.cacheError(
355
+ fakeHandler,
356
+ "options",
357
+ new Error("Ooops!"),
358
+ );
359
+
360
+ // Assert
361
+ expect(hydrationStoreSpy).toHaveBeenCalledWith(
362
+ fakeHandler,
363
+ "options",
364
+ {error: "Ooops!"},
365
+ );
379
366
  });
380
- });
381
367
 
382
- it("should not store the entry in the framework cache", () => {
383
- // Arrange
384
- jest.spyOn(Server, "isServerSide").mockReturnValue(true);
385
- const internalCache = new MemoryCache();
386
- jest.spyOn(internalCache, "store");
387
- const cache = new ResponseCache(internalCache);
388
- const fakeHandler: IRequestHandler<string, string> = {
389
- getKey: () => "MY_KEY",
390
- type: "MY_HANDLER",
391
- shouldRefreshCache: () => false,
392
- fulfillRequest: jest.fn(),
393
- cache: null,
394
- hydrate: false,
395
- };
368
+ it("should not store the entry in the ssrOnly cache", () => {
369
+ // Arrange
370
+ const hydrationCache = new MemoryCache();
371
+ const ssrOnlyCache = new MemoryCache();
372
+ const cache = new ResponseCache(
373
+ hydrationCache,
374
+ ssrOnlyCache,
375
+ );
376
+ const fakeHandler: IRequestHandler<string, string> = {
377
+ getKey: () => "MY_KEY",
378
+ type: "MY_HANDLER",
379
+ fulfillRequest: jest.fn(),
380
+ hydrate: true,
381
+ };
382
+ const ssrOnlyStoreSpy = jest.spyOn(ssrOnlyCache, "store");
396
383
 
397
- // Act
398
- cache.cacheError(fakeHandler, "options", new Error("Ooops!"));
384
+ // Act
385
+ cache.cacheError(
386
+ fakeHandler,
387
+ "options",
388
+ new Error("Ooops!"),
389
+ );
399
390
 
400
- // Assert
401
- expect(internalCache.store).not.toHaveBeenCalled();
391
+ // Assert
392
+ expect(ssrOnlyStoreSpy).not.toHaveBeenCalled();
393
+ });
402
394
  });
403
- });
404
- });
405
-
406
- describe("#getEntry", () => {
407
- describe("no custom cache", () => {
408
- it("should return null if not in the framework cache", () => {
409
- // Arrange
410
- const internalCache = new MemoryCache();
411
- jest.spyOn(internalCache, "retrieve").mockReturnValue(null);
412
- const cache = new ResponseCache();
413
- const fakeHandler: IRequestHandler<string, string> = {
414
- getKey: () => "MY_KEY",
415
- type: "MY_HANDLER",
416
- shouldRefreshCache: () => false,
417
- fulfillRequest: jest.fn(),
418
- cache: null,
419
- hydrate: true,
420
- };
421
395
 
422
- // Act
423
- const result = cache.getEntry(fakeHandler, "options");
396
+ describe("when the handler does not hydration", () => {
397
+ it("should store the entry in the ssr-only cache", () => {
398
+ // Arrange
399
+ const hydrationCache = new MemoryCache();
400
+ const ssrOnlyCache = new MemoryCache();
401
+ const cache = new ResponseCache(
402
+ hydrationCache,
403
+ ssrOnlyCache,
404
+ );
405
+ const fakeHandler: IRequestHandler<string, string> = {
406
+ getKey: () => "MY_KEY",
407
+ type: "MY_HANDLER",
408
+ fulfillRequest: jest.fn(),
409
+ hydrate: false,
410
+ };
411
+ const ssrOnlyStoreSpy = jest.spyOn(ssrOnlyCache, "store");
424
412
 
425
- // Assert
426
- expect(result).toBeNull();
427
- });
413
+ // Act
414
+ cache.cacheError(
415
+ fakeHandler,
416
+ "options",
417
+ new Error("Ooops!"),
418
+ );
428
419
 
429
- it("should return the cached entry", () => {
430
- // Arrange
431
- const internalCache = new MemoryCache();
432
- jest.spyOn(internalCache, "retrieve").mockReturnValue({
433
- data: "data!",
420
+ // Assert
421
+ expect(ssrOnlyStoreSpy).toHaveBeenCalledWith(
422
+ fakeHandler,
423
+ "options",
424
+ {error: "Ooops!"},
425
+ );
434
426
  });
435
- const cache = new ResponseCache(internalCache);
436
- const fakeHandler: IRequestHandler<string, string> = {
437
- getKey: () => "MY_KEY",
438
- type: "MY_HANDLER",
439
- shouldRefreshCache: () => false,
440
- fulfillRequest: jest.fn(),
441
- cache: null,
442
- hydrate: true,
443
- };
444
427
 
445
- // Act
446
- const result = cache.getEntry(fakeHandler, "options");
428
+ it("should not store the entry in the hydration cache", () => {
429
+ // Arrange
430
+ const hydrationCache = new MemoryCache();
431
+ const ssrOnlyCache = new MemoryCache();
432
+ const cache = new ResponseCache(
433
+ hydrationCache,
434
+ ssrOnlyCache,
435
+ );
436
+ const fakeHandler: IRequestHandler<string, string> = {
437
+ getKey: () => "MY_KEY",
438
+ type: "MY_HANDLER",
439
+ fulfillRequest: jest.fn(),
440
+ hydrate: false,
441
+ };
442
+ const hydrationStoreSpy = jest.spyOn(
443
+ hydrationCache,
444
+ "store",
445
+ );
447
446
 
448
- // Assert
449
- expect(result).toStrictEqual({data: "data!"});
447
+ // Act
448
+ cache.cacheError(
449
+ fakeHandler,
450
+ "options",
451
+ new Error("Ooops!"),
452
+ );
453
+
454
+ // Assert
455
+ expect(hydrationStoreSpy).not.toHaveBeenCalled();
456
+ });
450
457
  });
451
458
  });
459
+ });
452
460
 
453
- describe("with custom cache", () => {
454
- describe("SSR", () => {
455
- it("should use framework cache, not custom cache", () => {
461
+ describe("#getEntry", () => {
462
+ describe("when client-side", () => {
463
+ beforeEach(() => {
464
+ jest.spyOn(Server, "isServerSide").mockReturnValue(false);
465
+ });
466
+
467
+ describe("handler wants hydration", () => {
468
+ it("should return null if not in the hydration cache", () => {
456
469
  // Arrange
457
- jest.spyOn(Server, "isServerSide").mockReturnValue(true);
458
- const internalCache = new MemoryCache();
459
- jest.spyOn(internalCache, "retrieve");
460
- const cache = new ResponseCache(internalCache);
461
- const customCache = {
462
- store: jest.fn(),
463
- retrieve: jest.fn(),
464
- remove: jest.fn(),
465
- removeAll: jest.fn(),
466
- };
470
+ const hydrationCache = new MemoryCache();
471
+ jest.spyOn(hydrationCache, "retrieve").mockReturnValue(
472
+ null,
473
+ );
474
+ const cache = new ResponseCache(hydrationCache);
467
475
  const fakeHandler: IRequestHandler<string, string> = {
468
476
  getKey: () => "MY_KEY",
469
477
  type: "MY_HANDLER",
470
- shouldRefreshCache: () => false,
471
478
  fulfillRequest: jest.fn(),
472
- cache: customCache,
473
479
  hydrate: true,
474
480
  };
475
481
 
476
482
  // Act
477
- cache.getEntry(fakeHandler, "options");
483
+ const result = cache.getEntry(fakeHandler, "options");
478
484
 
479
485
  // Assert
480
- expect(internalCache.retrieve).toHaveBeenCalledWith(
481
- fakeHandler,
482
- "options",
483
- );
484
- expect(customCache.retrieve).not.toHaveBeenCalled();
486
+ expect(result).toBeNull();
485
487
  });
486
488
 
487
- it("should not store framework entry in custom cache", () => {
489
+ it("should return the cached entry if in the hydration cache", () => {
488
490
  // Arrange
489
- jest.spyOn(Server, "isServerSide").mockReturnValue(true);
490
- const internalCache = new MemoryCache();
491
- jest.spyOn(internalCache, "retrieve").mockReturnValue({
491
+ const hydrationCache = new MemoryCache();
492
+ jest.spyOn(hydrationCache, "retrieve").mockReturnValue({
492
493
  data: "data!",
493
494
  });
494
- const cache = new ResponseCache(internalCache);
495
- const customCache = {
496
- store: jest.fn(),
497
- retrieve: jest.fn(),
498
- remove: jest.fn(),
499
- removeAll: jest.fn(),
500
- };
495
+ const cache = new ResponseCache(hydrationCache);
501
496
  const fakeHandler: IRequestHandler<string, string> = {
502
497
  getKey: () => "MY_KEY",
503
498
  type: "MY_HANDLER",
504
- shouldRefreshCache: () => false,
505
499
  fulfillRequest: jest.fn(),
506
- cache: customCache,
507
500
  hydrate: true,
508
501
  };
509
502
 
@@ -512,96 +505,71 @@ describe("../response-cache.js", () => {
512
505
 
513
506
  // Assert
514
507
  expect(result).toStrictEqual({data: "data!"});
515
- expect(customCache.store).not.toHaveBeenCalled();
516
508
  });
509
+ });
517
510
 
518
- it("should not remove framework entry", () => {
511
+ describe("handler does not want hyrdation", () => {
512
+ it("should return undefined", () => {
519
513
  // Arrange
520
- jest.spyOn(Server, "isServerSide").mockReturnValue(true);
521
- const internalCache = new MemoryCache();
522
- jest.spyOn(internalCache, "retrieve").mockReturnValue({
514
+ const hydrationCache = new MemoryCache();
515
+ jest.spyOn(hydrationCache, "retrieve").mockReturnValue({
523
516
  data: "data!",
524
517
  });
525
- jest.spyOn(internalCache, "remove");
526
- const cache = new ResponseCache(internalCache);
527
- const customCache = {
528
- store: jest.fn(),
529
- retrieve: jest.fn(),
530
- remove: jest.fn(),
531
- removeAll: jest.fn(),
532
- };
518
+ const cache = new ResponseCache(hydrationCache);
533
519
  const fakeHandler: IRequestHandler<string, string> = {
534
520
  getKey: () => "MY_KEY",
535
521
  type: "MY_HANDLER",
536
- shouldRefreshCache: () => false,
537
522
  fulfillRequest: jest.fn(),
538
- cache: customCache,
539
- hydrate: true,
523
+ hydrate: false,
540
524
  };
541
525
 
542
526
  // Act
543
- cache.getEntry(fakeHandler, "options");
527
+ const result = cache.getEntry(fakeHandler, "options");
544
528
 
545
529
  // Assert
546
- expect(internalCache.remove).not.toHaveBeenCalled();
530
+ expect(result).toBeUndefined();
547
531
  });
548
532
  });
533
+ });
534
+
535
+ describe("when server-side", () => {
536
+ beforeEach(() => {
537
+ jest.spyOn(Server, "isServerSide").mockReturnValue(true);
538
+ });
549
539
 
550
- describe("CSR", () => {
551
- it("should return custom cached entry", () => {
540
+ describe("handler wants hydration", () => {
541
+ it("should return null if not in the hydration cache", () => {
552
542
  // Arrange
553
- jest.spyOn(Server, "isServerSide").mockReturnValue(false);
554
- const internalCache = new MemoryCache();
555
- jest.spyOn(internalCache, "retrieve");
556
- const cache = new ResponseCache(internalCache);
557
- const customCache = {
558
- store: jest.fn(),
559
- retrieve: jest
560
- .fn()
561
- .mockReturnValue({data: "custom data!"}),
562
- remove: jest.fn(),
563
- removeAll: jest.fn(),
564
- };
543
+ const hydrationCache = new MemoryCache();
544
+ jest.spyOn(hydrationCache, "retrieve").mockReturnValue(
545
+ null,
546
+ );
547
+ const cache = new ResponseCache(hydrationCache);
565
548
  const fakeHandler: IRequestHandler<string, string> = {
566
549
  getKey: () => "MY_KEY",
567
550
  type: "MY_HANDLER",
568
- shouldRefreshCache: () => false,
569
551
  fulfillRequest: jest.fn(),
570
- cache: customCache,
571
552
  hydrate: true,
572
553
  };
573
554
 
574
555
  // Act
575
- cache.getEntry(fakeHandler, "options");
556
+ const result = cache.getEntry(fakeHandler, "options");
576
557
 
577
558
  // Assert
578
- expect(customCache.retrieve).toHaveBeenCalledWith(
579
- fakeHandler,
580
- "options",
581
- );
582
- expect(internalCache.retrieve).not.toHaveBeenCalled();
559
+ expect(result).toBeNull();
583
560
  });
584
561
 
585
- it("should store framework entry in custom cache when custom cache misses", () => {
562
+ it("should return the cached entry if in the hydration cache", () => {
586
563
  // Arrange
587
- jest.spyOn(Server, "isServerSide").mockReturnValue(false);
588
- const internalCache = new MemoryCache();
589
- jest.spyOn(internalCache, "retrieve").mockReturnValue({
564
+ const hydrationCache = new MemoryCache();
565
+ jest.spyOn(hydrationCache, "retrieve").mockReturnValue({
590
566
  data: "data!",
591
567
  });
592
- const cache = new ResponseCache(internalCache);
593
- const customCache = {
594
- store: jest.fn(),
595
- retrieve: jest.fn(),
596
- remove: jest.fn(),
597
- removeAll: jest.fn(),
598
- };
568
+ const cache = new ResponseCache(hydrationCache);
599
569
  const fakeHandler: IRequestHandler<string, string> = {
600
570
  getKey: () => "MY_KEY",
601
571
  type: "MY_HANDLER",
602
- shouldRefreshCache: () => false,
603
572
  fulfillRequest: jest.fn(),
604
- cache: customCache,
605
573
  hydrate: true,
606
574
  };
607
575
 
@@ -610,281 +578,273 @@ describe("../response-cache.js", () => {
610
578
 
611
579
  // Assert
612
580
  expect(result).toStrictEqual({data: "data!"});
613
- expect(customCache.store).toBeCalledWith(
614
- fakeHandler,
615
- "options",
616
- {data: "data!"},
581
+ });
582
+ });
583
+
584
+ describe("handler does not want hyrdation", () => {
585
+ it("should return null if not in the ssr-only cache", () => {
586
+ // Arrange
587
+ const hydrationCache = new MemoryCache();
588
+ const ssrOnlyCache = new MemoryCache();
589
+ jest.spyOn(hydrationCache, "retrieve").mockReturnValue(
590
+ "NOT NULL",
591
+ );
592
+ jest.spyOn(ssrOnlyCache, "retrieve").mockReturnValue(null);
593
+ const cache = new ResponseCache(
594
+ hydrationCache,
595
+ ssrOnlyCache,
617
596
  );
597
+ const fakeHandler: IRequestHandler<string, string> = {
598
+ getKey: () => "MY_KEY",
599
+ type: "MY_HANDLER",
600
+ fulfillRequest: jest.fn(),
601
+ hydrate: false,
602
+ };
603
+
604
+ // Act
605
+ const result = cache.getEntry(fakeHandler, "options");
606
+
607
+ // Assert
608
+ expect(result).toBeNull();
618
609
  });
619
610
 
620
- it("should remove framework entry when custom cache misses", () => {
611
+ it("should return the cached entry if in the ssr-only cache", () => {
621
612
  // Arrange
622
- jest.spyOn(Server, "isServerSide").mockReturnValue(false);
623
- const internalCache = new MemoryCache();
624
- jest.spyOn(internalCache, "retrieve").mockReturnValue({
613
+ const hydrationCache = new MemoryCache();
614
+ const ssrOnlyCache = new MemoryCache();
615
+ jest.spyOn(hydrationCache, "retrieve").mockReturnValue({
616
+ data: "wrong data!",
617
+ });
618
+ jest.spyOn(ssrOnlyCache, "retrieve").mockReturnValue({
625
619
  data: "data!",
626
620
  });
627
- jest.spyOn(internalCache, "remove");
628
- const cache = new ResponseCache(internalCache);
629
- const customCache = {
630
- store: jest.fn(),
631
- retrieve: jest.fn(),
632
- remove: jest.fn(),
633
- removeAll: jest.fn(),
634
- };
621
+ const cache = new ResponseCache(
622
+ hydrationCache,
623
+ ssrOnlyCache,
624
+ );
635
625
  const fakeHandler: IRequestHandler<string, string> = {
636
626
  getKey: () => "MY_KEY",
637
627
  type: "MY_HANDLER",
638
- shouldRefreshCache: () => false,
639
628
  fulfillRequest: jest.fn(),
640
- cache: customCache,
641
- hydrate: true,
629
+ hydrate: false,
642
630
  };
643
631
 
644
632
  // Act
645
- cache.getEntry(fakeHandler, "options");
633
+ const result = cache.getEntry(fakeHandler, "options");
646
634
 
647
635
  // Assert
648
- expect(internalCache.remove).toHaveBeenCalledWith(
649
- fakeHandler,
650
- "options",
651
- );
636
+ expect(result).toStrictEqual({data: "data!"});
652
637
  });
653
638
  });
654
639
  });
655
640
  });
656
641
 
657
642
  describe("#remove", () => {
658
- it("should return false if nothing was removed", () => {
659
- // Arrange
660
- const internalCache = new MemoryCache();
661
- jest.spyOn(internalCache, "remove").mockReturnValue(false);
662
- const cache = new ResponseCache(internalCache);
663
- const customCache = {
664
- store: jest.fn(),
665
- retrieve: jest.fn(),
666
- remove: jest.fn().mockReturnValue(false),
667
- removeAll: jest.fn(),
668
- };
669
- const fakeHandler: IRequestHandler<string, string> = {
670
- getKey: () => "MY_KEY",
671
- type: "MY_HANDLER",
672
- shouldRefreshCache: () => false,
673
- fulfillRequest: jest.fn(),
674
- cache: customCache,
675
- hydrate: true,
676
- };
643
+ describe("when handler wants hydration", () => {
644
+ it("should return false if nothing was removed from hydration cache", () => {
645
+ // Arrange
646
+ const hydrationCache = new MemoryCache();
647
+ jest.spyOn(hydrationCache, "remove").mockReturnValue(false);
648
+ const cache = new ResponseCache(hydrationCache);
649
+ const fakeHandler: IRequestHandler<string, string> = {
650
+ getKey: () => "MY_KEY",
651
+ type: "MY_HANDLER",
652
+ fulfillRequest: jest.fn(),
653
+ hydrate: true,
654
+ };
677
655
 
678
- // Act
679
- const result = cache.remove(fakeHandler, "optionsA");
656
+ // Act
657
+ const result = cache.remove(fakeHandler, "optionsA");
680
658
 
681
- // Assert
682
- expect(result).toBeFalsy();
683
- });
659
+ // Assert
660
+ expect(result).toBeFalsy();
661
+ });
684
662
 
685
- it("should return true if something was removed from framework cache", () => {
686
- // Arrange
687
- const internalCache = new MemoryCache();
688
- jest.spyOn(internalCache, "remove").mockReturnValue(true);
689
- const cache = new ResponseCache(internalCache);
690
- const customCache = {
691
- store: jest.fn(),
692
- retrieve: jest.fn(),
693
- remove: jest.fn().mockReturnValue(false),
694
- removeAll: jest.fn(),
695
- };
696
- const fakeHandler: IRequestHandler<string, string> = {
697
- getKey: () => "MY_KEY",
698
- type: "MY_HANDLER",
699
- shouldRefreshCache: () => false,
700
- fulfillRequest: jest.fn(),
701
- cache: customCache,
702
- hydrate: true,
703
- };
663
+ it("should return true if something was removed from hydration cache", () => {
664
+ // Arrange
665
+ const hydrationCache = new MemoryCache();
666
+ jest.spyOn(hydrationCache, "remove").mockReturnValue(true);
667
+ const cache = new ResponseCache(hydrationCache);
668
+ const fakeHandler: IRequestHandler<string, string> = {
669
+ getKey: () => "MY_KEY",
670
+ type: "MY_HANDLER",
671
+ fulfillRequest: jest.fn(),
672
+ hydrate: true,
673
+ };
704
674
 
705
- // Act
706
- const result = cache.remove(fakeHandler, "optionsA");
675
+ // Act
676
+ const result = cache.remove(fakeHandler, "optionsA");
707
677
 
708
- // Assert
709
- expect(result).toBeTruthy();
678
+ // Assert
679
+ expect(result).toBeTruthy();
680
+ });
710
681
  });
711
682
 
712
- it("should return true if something was removed from custom cache", () => {
713
- // Arrange
714
- const internalCache = new MemoryCache();
715
- /**
716
- * This simulates that the internal cache did not remove anything.
717
- * That way, if the custom cache says it does, we can check that
718
- * our method is acknowledging that.
719
- */
720
- jest.spyOn(internalCache, "remove").mockReturnValue(false);
721
- const cache = new ResponseCache(internalCache);
722
- const customCache = {
723
- store: jest.fn(),
724
- retrieve: jest.fn(),
725
- /**
726
- * We're testing that this mocked valiue propagates to the
727
- * framework response cache `remove` call.
728
- */
729
- remove: jest.fn().mockReturnValue(true),
730
- removeAll: jest.fn(),
731
- };
732
- const fakeHandler: IRequestHandler<string, string> = {
733
- getKey: () => "IGNORED",
734
- type: "IGNORED",
735
- shouldRefreshCache: () => false,
736
- fulfillRequest: jest.fn(),
737
- cache: customCache,
738
- hydrate: true,
739
- };
683
+ describe("when handler does not want hydration", () => {
684
+ it("should return false", () => {
685
+ // Arrange
686
+ const hydrationCache = new MemoryCache();
687
+ const ssrOnlyCache = new MemoryCache();
688
+ jest.spyOn(hydrationCache, "remove").mockReturnValue(true);
689
+ jest.spyOn(ssrOnlyCache, "remove").mockReturnValue(true);
690
+ const cache = new ResponseCache(hydrationCache, ssrOnlyCache);
691
+ const fakeHandler: IRequestHandler<string, string> = {
692
+ getKey: () => "MY_KEY",
693
+ type: "MY_HANDLER",
694
+ fulfillRequest: jest.fn(),
695
+ hydrate: false,
696
+ };
740
697
 
741
- // Act
742
- const result = cache.remove(fakeHandler, "PRETEND_KEY");
698
+ // Act
699
+ const result = cache.remove(fakeHandler, "optionsA");
743
700
 
744
- // Assert
745
- expect(result).toBeTruthy();
746
- });
701
+ // Assert
702
+ expect(result).toBeFalsy();
703
+ });
747
704
 
748
- it("SSR should call framework cache, not custom cache", () => {
749
- // Arrange
750
- jest.spyOn(Server, "isServerSide").mockReturnValue(true);
751
- const internalCache = new MemoryCache();
752
- jest.spyOn(internalCache, "remove");
753
- const cache = new ResponseCache(internalCache);
754
- const customCache = {
755
- store: jest.fn(),
756
- retrieve: jest.fn(),
757
- remove: jest.fn(),
758
- removeAll: jest.fn(),
759
- };
760
- const fakeHandler: IRequestHandler<string, string> = {
761
- getKey: () => "MY_KEY",
762
- type: "MY_HANDLER",
763
- shouldRefreshCache: () => false,
764
- fulfillRequest: jest.fn(),
765
- cache: customCache,
766
- hydrate: true,
767
- };
705
+ describe("when server-side", () => {
706
+ beforeEach(() => {
707
+ jest.spyOn(Server, "isServerSide").mockReturnValue(true);
708
+ });
768
709
 
769
- // Act
770
- cache.remove(fakeHandler, "optionsA");
710
+ it("should return false if nothing was removed from ssr-only cache", () => {
711
+ // Arrange
712
+ const hydrationCache = new MemoryCache();
713
+ const ssrOnlyCache = new MemoryCache();
714
+ jest.spyOn(hydrationCache, "remove").mockReturnValue(true);
715
+ jest.spyOn(ssrOnlyCache, "remove").mockReturnValue(false);
716
+ const cache = new ResponseCache(
717
+ hydrationCache,
718
+ ssrOnlyCache,
719
+ );
720
+ const fakeHandler: IRequestHandler<string, string> = {
721
+ getKey: () => "MY_KEY",
722
+ type: "MY_HANDLER",
723
+ fulfillRequest: jest.fn(),
724
+ hydrate: false,
725
+ };
771
726
 
772
- // Assert
773
- expect(customCache.remove).not.toHaveBeenCalled();
774
- expect(internalCache.remove).toHaveBeenCalledWith(
775
- fakeHandler,
776
- "optionsA",
777
- );
727
+ // Act
728
+ const result = cache.remove(fakeHandler, "optionsA");
729
+
730
+ // Assert
731
+ expect(result).toBeFalsy();
732
+ });
733
+
734
+ it("should return true if something was removed from ssr-only cache", () => {
735
+ // Arrange
736
+ const hydrationCache = new MemoryCache();
737
+ const ssrOnlyCache = new MemoryCache();
738
+ jest.spyOn(ssrOnlyCache, "remove").mockReturnValue(true);
739
+ const cache = new ResponseCache(
740
+ hydrationCache,
741
+ ssrOnlyCache,
742
+ );
743
+ const fakeHandler: IRequestHandler<string, string> = {
744
+ getKey: () => "MY_KEY",
745
+ type: "MY_HANDLER",
746
+ fulfillRequest: jest.fn(),
747
+ hydrate: false,
748
+ };
749
+
750
+ // Act
751
+ const result = cache.remove(fakeHandler, "optionsA");
752
+
753
+ // Assert
754
+ expect(result).toBeTruthy();
755
+ });
756
+ });
778
757
  });
779
758
  });
780
759
 
781
760
  describe("#removeAll", () => {
782
- it("CSR should call removeAll on custom and framework caches", () => {
783
- const internalCache = new MemoryCache();
784
- jest.spyOn(internalCache, "removeAll");
785
- const cache = new ResponseCache(internalCache);
786
- const customCache = {
787
- store: jest.fn(),
788
- retrieve: jest.fn(),
789
- remove: jest.fn(),
790
- removeAll: jest.fn(),
791
- };
792
- const fakeHandler: IRequestHandler<string, string> = {
793
- getKey: () => "MY_KEY",
794
- type: "MY_HANDLER",
795
- shouldRefreshCache: () => false,
796
- fulfillRequest: jest.fn(),
797
- cache: customCache,
798
- hydrate: true,
799
- };
800
- const predicate = () => false;
761
+ describe("when handler wants hydration", () => {
762
+ it("should return total number of entries removed from hydration cache", () => {
763
+ // Arrange
764
+ const hydrationCache = new MemoryCache();
765
+ jest.spyOn(hydrationCache, "removeAll").mockReturnValue(1);
766
+ const cache = new ResponseCache(hydrationCache);
767
+ const fakeHandler: IRequestHandler<string, string> = {
768
+ getKey: () => "MY_KEY",
769
+ type: "MY_HANDLER",
770
+ fulfillRequest: jest.fn(),
771
+ hydrate: true,
772
+ };
801
773
 
802
- // Act
803
- cache.removeAll(fakeHandler, predicate);
774
+ // Act
775
+ const result = cache.removeAll(fakeHandler);
804
776
 
805
- // Assert
806
- expect(customCache.removeAll).toHaveBeenCalledWith(
807
- fakeHandler,
808
- predicate,
809
- );
810
- expect(internalCache.removeAll).toHaveBeenCalledWith(
811
- fakeHandler,
812
- predicate,
813
- );
777
+ // Assert
778
+ expect(result).toBe(1);
779
+ });
814
780
  });
815
781
 
816
- it("should return total number of entries removed", () => {
817
- // Arrange
818
- const internalCache = new MemoryCache();
819
- jest.spyOn(internalCache, "removeAll").mockReturnValue(1);
820
- const cache = new ResponseCache(internalCache);
821
- const customCache = {
822
- store: jest.fn(),
823
- retrieve: jest.fn(),
824
- remove: jest.fn(),
825
- removeAll: jest.fn().mockReturnValue(1),
826
- };
827
- const fakeHandler: IRequestHandler<string, string> = {
828
- getKey: () => "MY_KEY",
829
- type: "MY_HANDLER",
830
- shouldRefreshCache: () => false,
831
- fulfillRequest: jest.fn(),
832
- cache: customCache,
833
- hydrate: true,
834
- };
782
+ describe("when handler does not want hydration", () => {
783
+ it("should return zero", () => {
784
+ // Arrange
785
+ const hydrationCache = new MemoryCache();
786
+ const ssrOnlyCache = new MemoryCache();
787
+ jest.spyOn(hydrationCache, "removeAll").mockReturnValue(42);
788
+ jest.spyOn(ssrOnlyCache, "removeAll").mockReturnValue(42);
789
+ const cache = new ResponseCache(hydrationCache, ssrOnlyCache);
790
+ const fakeHandler: IRequestHandler<string, string> = {
791
+ getKey: () => "MY_KEY",
792
+ type: "MY_HANDLER",
793
+ fulfillRequest: jest.fn(),
794
+ hydrate: false,
795
+ };
835
796
 
836
- // Act
837
- const result = cache.removeAll(fakeHandler);
797
+ // Act
798
+ const result = cache.removeAll(fakeHandler);
838
799
 
839
- // Assert
840
- expect(result).toBe(2);
841
- });
800
+ // Assert
801
+ expect(result).toBe(0);
802
+ });
842
803
 
843
- it("SSR should call framework cache, not custom cache", () => {
844
- // Arrange
845
- jest.spyOn(Server, "isServerSide").mockReturnValue(true);
846
- const internalCache = new MemoryCache();
847
- jest.spyOn(internalCache, "removeAll");
848
- const cache = new ResponseCache(internalCache);
849
- const customCache = {
850
- store: jest.fn(),
851
- retrieve: jest.fn(),
852
- remove: jest.fn(),
853
- removeAll: jest.fn(),
854
- };
855
- const fakeHandler: IRequestHandler<string, string> = {
856
- getKey: () => "MY_KEY",
857
- type: "MY_HANDLER",
858
- shouldRefreshCache: () => false,
859
- fulfillRequest: jest.fn(),
860
- cache: customCache,
861
- hydrate: true,
862
- };
804
+ describe("when server-side", () => {
805
+ beforeEach(() => {
806
+ jest.spyOn(Server, "isServerSide").mockReturnValue(true);
807
+ });
863
808
 
864
- // Act
865
- cache.removeAll(fakeHandler);
809
+ it("should return total number of entries removed from ssr-only cache", () => {
810
+ // Arrange
811
+ const hydrationCache = new MemoryCache();
812
+ const ssrOnlyCache = new MemoryCache();
813
+ jest.spyOn(hydrationCache, "removeAll").mockReturnValue(13);
814
+ jest.spyOn(ssrOnlyCache, "removeAll").mockReturnValue(42);
815
+ const cache = new ResponseCache(
816
+ hydrationCache,
817
+ ssrOnlyCache,
818
+ );
819
+ const fakeHandler: IRequestHandler<string, string> = {
820
+ getKey: () => "MY_KEY",
821
+ type: "MY_HANDLER",
822
+ fulfillRequest: jest.fn(),
823
+ hydrate: false,
824
+ };
866
825
 
867
- // Assert
868
- expect(customCache.removeAll).not.toHaveBeenCalled();
869
- expect(internalCache.removeAll).toHaveBeenCalledWith(
870
- fakeHandler,
871
- undefined,
872
- );
826
+ // Act
827
+ const result = cache.removeAll(fakeHandler);
828
+
829
+ // Assert
830
+ expect(result).toBe(42);
831
+ });
832
+ });
873
833
  });
874
834
  });
875
835
 
876
836
  describe("#cloneHydratableData", () => {
877
- it("should clone the internal hydration cache", () => {
837
+ it("should clone the hydration cache", () => {
878
838
  // Arrange
879
- const internalCache = new MemoryCache();
880
- jest.spyOn(internalCache, "cloneData").mockReturnValue("CLONE!");
881
- const cache = new ResponseCache(internalCache);
839
+ const hydrationCache = new MemoryCache();
840
+ const cloneSpy = jest
841
+ .spyOn(hydrationCache, "cloneData")
842
+ .mockReturnValue("CLONE!");
843
+ const cache = new ResponseCache(hydrationCache);
882
844
  const fakeHandler: IRequestHandler<string, string> = {
883
845
  getKey: (options) => options,
884
846
  type: "MY_HANDLER",
885
- shouldRefreshCache: () => false,
886
847
  fulfillRequest: jest.fn(),
887
- cache: null,
888
848
  hydrate: true,
889
849
  };
890
850
  // Let's add to the initialized state to check that everything
@@ -896,7 +856,7 @@ describe("../response-cache.js", () => {
896
856
  const result = cache.cloneHydratableData();
897
857
 
898
858
  // Assert
899
- expect(internalCache.cloneData).toHaveBeenCalled();
859
+ expect(cloneSpy).toHaveBeenCalled();
900
860
  expect(result).toBe("CLONE!");
901
861
  });
902
862