@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.
- package/CHANGELOG.md +27 -0
- package/dist/es/index.js +368 -429
- package/dist/index.js +457 -460
- package/docs.md +19 -13
- package/package.json +3 -3
- package/src/__tests__/__snapshots__/generated-snapshot.test.js.snap +40 -160
- package/src/__tests__/generated-snapshot.test.js +15 -195
- package/src/components/__tests__/data.test.js +159 -965
- package/src/components/__tests__/gql-router.test.js +64 -0
- package/src/components/__tests__/intercept-data.test.js +9 -66
- package/src/components/__tests__/track-data.test.js +6 -5
- package/src/components/data.js +9 -117
- package/src/components/data.md +38 -60
- package/src/components/gql-router.js +66 -0
- package/src/components/intercept-data.js +2 -34
- package/src/components/intercept-data.md +7 -105
- package/src/hooks/__tests__/use-data.test.js +826 -0
- package/src/hooks/__tests__/use-gql.test.js +233 -0
- package/src/hooks/use-data.js +143 -0
- package/src/hooks/use-gql.js +77 -0
- package/src/index.js +13 -9
- package/src/util/__tests__/get-gql-data-from-response.test.js +187 -0
- package/src/util/__tests__/memory-cache.test.js +134 -35
- package/src/util/__tests__/request-fulfillment.test.js +21 -36
- package/src/util/__tests__/request-handler.test.js +30 -30
- package/src/util/__tests__/request-tracking.test.js +29 -30
- package/src/util/__tests__/response-cache.test.js +521 -561
- package/src/util/__tests__/result-from-cache-entry.test.js +68 -0
- package/src/util/get-gql-data-from-response.js +69 -0
- package/src/util/gql-error.js +36 -0
- package/src/util/gql-router-context.js +6 -0
- package/src/util/gql-types.js +65 -0
- package/src/util/memory-cache.js +18 -14
- package/src/util/request-fulfillment.js +4 -0
- package/src/util/request-handler.js +2 -27
- package/src/util/request-handler.md +0 -32
- package/src/util/response-cache.js +50 -110
- package/src/util/result-from-cache-entry.js +38 -0
- package/src/util/types.js +14 -35
- package/LICENSE +0 -21
- package/src/components/__tests__/intercept-cache.test.js +0 -124
- package/src/components/__tests__/internal-data.test.js +0 -1030
- package/src/components/intercept-cache.js +0 -79
- package/src/components/intercept-cache.md +0 -103
- package/src/components/internal-data.js +0 -219
- package/src/util/__tests__/no-cache.test.js +0 -112
- package/src/util/no-cache.js +0 -67
- 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("
|
|
116
|
-
it("should store the entry in the
|
|
134
|
+
describe("when client-side", () => {
|
|
135
|
+
it("should not store the entry in the hydration cache", () => {
|
|
117
136
|
// Arrange
|
|
118
|
-
const
|
|
119
|
-
|
|
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(
|
|
135
|
-
fakeHandler,
|
|
136
|
-
"options",
|
|
137
|
-
{data: "data"},
|
|
138
|
-
);
|
|
151
|
+
expect(hydrationStoreSpy).not.toHaveBeenCalled();
|
|
139
152
|
});
|
|
140
|
-
});
|
|
141
153
|
|
|
142
|
-
|
|
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
|
-
|
|
146
|
-
const
|
|
147
|
-
|
|
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(
|
|
169
|
-
expect(internalCache.store).toHaveBeenCalledWith(
|
|
170
|
-
fakeHandler,
|
|
171
|
-
"options",
|
|
172
|
-
{data: "data"},
|
|
173
|
-
);
|
|
171
|
+
expect(ssrOnlyStoreSpy).not.toHaveBeenCalled();
|
|
174
172
|
});
|
|
173
|
+
});
|
|
175
174
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
jest.spyOn(Server, "isServerSide").mockReturnValue(
|
|
179
|
-
|
|
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
|
-
|
|
198
|
-
|
|
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
|
-
|
|
201
|
-
|
|
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
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
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
|
-
|
|
228
|
-
|
|
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
|
-
|
|
231
|
-
|
|
232
|
-
|
|
223
|
+
// Act
|
|
224
|
+
cache.cacheData(fakeHandler, "options", "data");
|
|
225
|
+
|
|
226
|
+
// Assert
|
|
227
|
+
expect(ssrOnlyStoreSpy).not.toHaveBeenCalled();
|
|
233
228
|
});
|
|
234
229
|
});
|
|
235
230
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
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
|
-
|
|
252
|
-
|
|
248
|
+
// Act
|
|
249
|
+
cache.cacheData(fakeHandler, "options", "data");
|
|
253
250
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
251
|
+
// Assert
|
|
252
|
+
expect(ssrOnlyStoreSpy).toHaveBeenCalledWith(
|
|
253
|
+
fakeHandler,
|
|
254
|
+
"options",
|
|
255
|
+
{
|
|
256
|
+
data: "data",
|
|
257
|
+
},
|
|
258
|
+
);
|
|
259
|
+
});
|
|
259
260
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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
|
-
|
|
277
|
-
|
|
280
|
+
// Act
|
|
281
|
+
cache.cacheData(fakeHandler, "options", "data");
|
|
278
282
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
"options",
|
|
283
|
-
{error: "Ooops!"},
|
|
284
|
-
);
|
|
283
|
+
// Assert
|
|
284
|
+
expect(hydrationStoreSpy).not.toHaveBeenCalled();
|
|
285
|
+
});
|
|
285
286
|
});
|
|
286
287
|
});
|
|
288
|
+
});
|
|
287
289
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
+
describe("#cacheError", () => {
|
|
291
|
+
describe("when client-side", () => {
|
|
292
|
+
it("should not store the entry in the hydration cache", () => {
|
|
290
293
|
// Arrange
|
|
291
|
-
|
|
292
|
-
const
|
|
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(
|
|
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("
|
|
311
|
+
it("should not store the entry in the ssrOnly cache", () => {
|
|
323
312
|
// Arrange
|
|
324
|
-
|
|
325
|
-
const
|
|
326
|
-
|
|
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",
|
|
325
|
+
cache.cacheError(fakeHandler, "options", "Ooops!");
|
|
345
326
|
|
|
346
327
|
// Assert
|
|
347
|
-
expect(
|
|
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("
|
|
357
|
-
|
|
358
|
-
// Arrange
|
|
332
|
+
describe("when server-side", () => {
|
|
333
|
+
beforeEach(() => {
|
|
359
334
|
jest.spyOn(Server, "isServerSide").mockReturnValue(true);
|
|
360
|
-
|
|
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
|
-
|
|
374
|
-
|
|
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
|
-
|
|
377
|
-
|
|
378
|
-
|
|
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
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
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
|
-
|
|
398
|
-
|
|
384
|
+
// Act
|
|
385
|
+
cache.cacheError(
|
|
386
|
+
fakeHandler,
|
|
387
|
+
"options",
|
|
388
|
+
new Error("Ooops!"),
|
|
389
|
+
);
|
|
399
390
|
|
|
400
|
-
|
|
401
|
-
|
|
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
|
-
|
|
423
|
-
|
|
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
|
-
|
|
426
|
-
|
|
427
|
-
|
|
413
|
+
// Act
|
|
414
|
+
cache.cacheError(
|
|
415
|
+
fakeHandler,
|
|
416
|
+
"options",
|
|
417
|
+
new Error("Ooops!"),
|
|
418
|
+
);
|
|
428
419
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
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
|
-
|
|
446
|
-
|
|
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
|
-
|
|
449
|
-
|
|
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
|
-
|
|
454
|
-
|
|
455
|
-
|
|
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
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
const
|
|
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(
|
|
481
|
-
fakeHandler,
|
|
482
|
-
"options",
|
|
483
|
-
);
|
|
484
|
-
expect(customCache.retrieve).not.toHaveBeenCalled();
|
|
486
|
+
expect(result).toBeNull();
|
|
485
487
|
});
|
|
486
488
|
|
|
487
|
-
it("should
|
|
489
|
+
it("should return the cached entry if in the hydration cache", () => {
|
|
488
490
|
// Arrange
|
|
489
|
-
|
|
490
|
-
|
|
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(
|
|
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
|
-
|
|
511
|
+
describe("handler does not want hyrdation", () => {
|
|
512
|
+
it("should return undefined", () => {
|
|
519
513
|
// Arrange
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
jest.spyOn(internalCache, "retrieve").mockReturnValue({
|
|
514
|
+
const hydrationCache = new MemoryCache();
|
|
515
|
+
jest.spyOn(hydrationCache, "retrieve").mockReturnValue({
|
|
523
516
|
data: "data!",
|
|
524
517
|
});
|
|
525
|
-
|
|
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
|
-
|
|
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(
|
|
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("
|
|
551
|
-
it("should return
|
|
540
|
+
describe("handler wants hydration", () => {
|
|
541
|
+
it("should return null if not in the hydration cache", () => {
|
|
552
542
|
// Arrange
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
const
|
|
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(
|
|
579
|
-
fakeHandler,
|
|
580
|
-
"options",
|
|
581
|
-
);
|
|
582
|
-
expect(internalCache.retrieve).not.toHaveBeenCalled();
|
|
559
|
+
expect(result).toBeNull();
|
|
583
560
|
});
|
|
584
561
|
|
|
585
|
-
it("should
|
|
562
|
+
it("should return the cached entry if in the hydration cache", () => {
|
|
586
563
|
// Arrange
|
|
587
|
-
|
|
588
|
-
|
|
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(
|
|
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
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
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
|
|
611
|
+
it("should return the cached entry if in the ssr-only cache", () => {
|
|
621
612
|
// Arrange
|
|
622
|
-
|
|
623
|
-
const
|
|
624
|
-
jest.spyOn(
|
|
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
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
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
|
-
|
|
679
|
-
|
|
656
|
+
// Act
|
|
657
|
+
const result = cache.remove(fakeHandler, "optionsA");
|
|
680
658
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
659
|
+
// Assert
|
|
660
|
+
expect(result).toBeFalsy();
|
|
661
|
+
});
|
|
684
662
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
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
|
-
|
|
706
|
-
|
|
675
|
+
// Act
|
|
676
|
+
const result = cache.remove(fakeHandler, "optionsA");
|
|
707
677
|
|
|
708
|
-
|
|
709
|
-
|
|
678
|
+
// Assert
|
|
679
|
+
expect(result).toBeTruthy();
|
|
680
|
+
});
|
|
710
681
|
});
|
|
711
682
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
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
|
-
|
|
742
|
-
|
|
698
|
+
// Act
|
|
699
|
+
const result = cache.remove(fakeHandler, "optionsA");
|
|
743
700
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
701
|
+
// Assert
|
|
702
|
+
expect(result).toBeFalsy();
|
|
703
|
+
});
|
|
747
704
|
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
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
|
-
|
|
770
|
-
|
|
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
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
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
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
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
|
-
|
|
803
|
-
|
|
774
|
+
// Act
|
|
775
|
+
const result = cache.removeAll(fakeHandler);
|
|
804
776
|
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
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
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
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
|
-
|
|
837
|
-
|
|
797
|
+
// Act
|
|
798
|
+
const result = cache.removeAll(fakeHandler);
|
|
838
799
|
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
800
|
+
// Assert
|
|
801
|
+
expect(result).toBe(0);
|
|
802
|
+
});
|
|
842
803
|
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
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
|
-
|
|
865
|
-
|
|
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
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
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
|
|
837
|
+
it("should clone the hydration cache", () => {
|
|
878
838
|
// Arrange
|
|
879
|
-
const
|
|
880
|
-
jest
|
|
881
|
-
|
|
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(
|
|
859
|
+
expect(cloneSpy).toHaveBeenCalled();
|
|
900
860
|
expect(result).toBe("CLONE!");
|
|
901
861
|
});
|
|
902
862
|
|