@khanacademy/wonder-blocks-data 2.3.4 → 3.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 (39) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/es/index.js +212 -446
  3. package/dist/index.js +230 -478
  4. package/docs.md +19 -13
  5. package/package.json +2 -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__/intercept-data.test.js +9 -66
  10. package/src/components/__tests__/track-data.test.js +6 -5
  11. package/src/components/data.js +9 -117
  12. package/src/components/data.md +38 -60
  13. package/src/components/intercept-data.js +2 -34
  14. package/src/components/intercept-data.md +7 -105
  15. package/src/hooks/__tests__/use-data.test.js +790 -0
  16. package/src/hooks/use-data.js +138 -0
  17. package/src/index.js +1 -3
  18. package/src/util/__tests__/memory-cache.test.js +134 -35
  19. package/src/util/__tests__/request-fulfillment.test.js +21 -36
  20. package/src/util/__tests__/request-handler.test.js +30 -30
  21. package/src/util/__tests__/request-tracking.test.js +29 -30
  22. package/src/util/__tests__/response-cache.test.js +521 -561
  23. package/src/util/__tests__/result-from-cache-entry.test.js +68 -0
  24. package/src/util/memory-cache.js +18 -14
  25. package/src/util/request-fulfillment.js +4 -0
  26. package/src/util/request-handler.js +2 -27
  27. package/src/util/request-handler.md +0 -32
  28. package/src/util/response-cache.js +50 -110
  29. package/src/util/result-from-cache-entry.js +38 -0
  30. package/src/util/types.js +14 -35
  31. package/LICENSE +0 -21
  32. package/src/components/__tests__/intercept-cache.test.js +0 -124
  33. package/src/components/__tests__/internal-data.test.js +0 -1030
  34. package/src/components/intercept-cache.js +0 -79
  35. package/src/components/intercept-cache.md +0 -103
  36. package/src/components/internal-data.js +0 -219
  37. package/src/util/__tests__/no-cache.test.js +0 -112
  38. package/src/util/no-cache.js +0 -67
  39. package/src/util/no-cache.md +0 -66
@@ -14,7 +14,7 @@ describe("../request-handler.js", () => {
14
14
  jest.restoreAllMocks();
15
15
  });
16
16
 
17
- describe("#get type", () => {
17
+ describe("@type", () => {
18
18
  it("should return value passed in construction", () => {
19
19
  // Arrange
20
20
  const handler = new RequestHandler("MY_TYPE");
@@ -27,80 +27,80 @@ describe("../request-handler.js", () => {
27
27
  });
28
28
  });
29
29
 
30
- describe("#getKey", () => {
31
- it("should return a key for given options", () => {
30
+ describe("@hydrate", () => {
31
+ it("should return true when constructed with false", () => {
32
32
  // Arrange
33
- const handler = new RequestHandler("MY_TYPE");
33
+ const handler = new RequestHandler("MY_TYPE", false);
34
34
 
35
35
  // Act
36
- const result = handler.getKey({some: "options"});
36
+ const result = handler.hydrate;
37
37
 
38
38
  // Assert
39
- expect(result).toMatchInlineSnapshot(
40
- `"{\\"some\\":\\"options\\"}"`,
41
- );
39
+ expect(result).toBeFalse();
42
40
  });
43
41
 
44
- it("should return a key for undefined options", () => {
42
+ it("should return true when constructed with true", () => {
45
43
  // Arrange
46
- const handler = new RequestHandler("MY_TYPE");
44
+ const handler = new RequestHandler("MY_TYPE", true);
47
45
 
48
46
  // Act
49
- const result = handler.getKey(undefined);
47
+ const result = handler.hydrate;
50
48
 
51
49
  // Assert
52
- expect(result).toMatchInlineSnapshot(`"undefined"`);
50
+ expect(result).toBeTrue();
53
51
  });
54
52
 
55
- it("should throw if JSON.stringify fails", () => {
53
+ it("should return true by default", () => {
56
54
  // Arrange
57
55
  const handler = new RequestHandler("MY_TYPE");
58
- jest.spyOn(JSON, "stringify").mockImplementation(() => {
59
- throw new Error("OH NOES!");
60
- });
61
56
 
62
57
  // Act
63
- const underTest = () => handler.getKey({});
58
+ const result = handler.hydrate;
64
59
 
65
60
  // Assert
66
- expect(underTest).toThrowErrorMatchingInlineSnapshot(
67
- `"Failed to auto-generate key: Error: OH NOES!"`,
68
- );
61
+ expect(result).toBeTrue();
69
62
  });
70
63
  });
71
64
 
72
- describe("#shouldRefreshCache", () => {
73
- it("should return true if no current cached entry", () => {
65
+ describe("#getKey", () => {
66
+ it("should return a key for given options", () => {
74
67
  // Arrange
75
68
  const handler = new RequestHandler("MY_TYPE");
76
69
 
77
70
  // Act
78
- const result = handler.shouldRefreshCache({}, null);
71
+ const result = handler.getKey({some: "options"});
79
72
 
80
73
  // Assert
81
- expect(result).toBeTruthy();
74
+ expect(result).toMatchInlineSnapshot(
75
+ `"{\\"some\\":\\"options\\"}"`,
76
+ );
82
77
  });
83
78
 
84
- it("should return true if cached entry has error", () => {
79
+ it("should return a key for undefined options", () => {
85
80
  // Arrange
86
81
  const handler = new RequestHandler("MY_TYPE");
87
82
 
88
83
  // Act
89
- const result = handler.shouldRefreshCache({}, {error: "oops!"});
84
+ const result = handler.getKey(undefined);
90
85
 
91
86
  // Assert
92
- expect(result).toBeTruthy();
87
+ expect(result).toMatchInlineSnapshot(`"undefined"`);
93
88
  });
94
89
 
95
- it("should return false if cached entry is data", () => {
90
+ it("should throw if JSON.stringify fails", () => {
96
91
  // Arrange
97
92
  const handler = new RequestHandler("MY_TYPE");
93
+ jest.spyOn(JSON, "stringify").mockImplementation(() => {
94
+ throw new Error("OH NOES!");
95
+ });
98
96
 
99
97
  // Act
100
- const result = handler.shouldRefreshCache({}, {data: "yay! data"});
98
+ const underTest = () => handler.getKey({});
101
99
 
102
100
  // Assert
103
- expect(result).toBeFalsy();
101
+ expect(underTest).toThrowErrorMatchingInlineSnapshot(
102
+ `"Failed to auto-generate key: Error: OH NOES!"`,
103
+ );
104
104
  });
105
105
  });
106
106
 
@@ -1,7 +1,9 @@
1
1
  // @flow
2
2
  import * as React from "react";
3
3
  import {mount} from "enzyme";
4
+ import "jest-enzyme";
4
5
 
6
+ import {Server} from "@khanacademy/wonder-blocks-core";
5
7
  import {RequestTracker, TrackerContext} from "../request-tracking.js";
6
8
  import {ResponseCache} from "../response-cache.js";
7
9
 
@@ -27,6 +29,10 @@ describe("../request-tracking.js", () => {
27
29
  });
28
30
 
29
31
  describe("RequestTracker", () => {
32
+ beforeEach(() => {
33
+ jest.spyOn(Server, "isServerSide").mockReturnValue(true);
34
+ });
35
+
30
36
  const createRequestTracker = () =>
31
37
  /**
32
38
  * We pass our own response cache instance so that the test cases
@@ -34,6 +40,29 @@ describe("../request-tracking.js", () => {
34
40
  */
35
41
  new RequestTracker(new ResponseCache());
36
42
 
43
+ describe("@Default", () => {
44
+ it("should return an instance of RequestTracker", () => {
45
+ // Arrange
46
+
47
+ // Act
48
+ const result = RequestTracker.Default;
49
+
50
+ // Assert
51
+ expect(result).toBeInstanceOf(RequestTracker);
52
+ });
53
+
54
+ it("should return the same instance on each call", () => {
55
+ // Arrange
56
+
57
+ // Act
58
+ const result1 = RequestTracker.Default;
59
+ const result2 = RequestTracker.Default;
60
+
61
+ // Assert
62
+ expect(result1).toBe(result2);
63
+ });
64
+ });
65
+
37
66
  describe("#trackDataRequest", () => {
38
67
  it("should get the key for the request", () => {
39
68
  // Arrange
@@ -42,9 +71,7 @@ describe("../request-tracking.js", () => {
42
71
  const fakeHandler: IRequestHandler<any, any> = {
43
72
  fulfillRequest: jest.fn(() => Promise.resolve(null)),
44
73
  getKey: getKeySpy,
45
- shouldRefreshCache: () => false,
46
74
  type: "MY_TYPE",
47
- cache: null,
48
75
  hydrate: true,
49
76
  };
50
77
  const options = {these: "are options"};
@@ -63,9 +90,7 @@ describe("../request-tracking.js", () => {
63
90
  const fakeHandler: IRequestHandler<any, any> = {
64
91
  fulfillRequest: fulfillRequestSpy,
65
92
  getKey: jest.fn().mockReturnValue("MY_KEY"),
66
- shouldRefreshCache: () => false,
67
93
  type: "MY_TYPE",
68
- cache: null,
69
94
  hydrate: true,
70
95
  };
71
96
  const options = {these: "are options"};
@@ -86,9 +111,7 @@ describe("../request-tracking.js", () => {
86
111
  const fakeHandler: IRequestHandler<any, any> = {
87
112
  fulfillRequest: fulfillRequestSpy,
88
113
  getKey: (options) => JSON.stringify(options),
89
- shouldRefreshCache: () => false,
90
114
  type: "MY_TYPE",
91
- cache: null,
92
115
  hydrate: true,
93
116
  };
94
117
  const options1 = {these: "are options"};
@@ -112,18 +135,14 @@ describe("../request-tracking.js", () => {
112
135
  const fakeHandler1: IRequestHandler<any, any> = {
113
136
  fulfillRequest: fulfillRequestSpy1,
114
137
  getKey: jest.fn().mockReturnValue("MY_KEY1"),
115
- shouldRefreshCache: () => false,
116
138
  type: handlerType,
117
- cache: null,
118
139
  hydrate: true,
119
140
  };
120
141
  const fulfillRequestSpy2 = jest.fn();
121
142
  const fakeHandler2: IRequestHandler<any, any> = {
122
143
  fulfillRequest: fulfillRequestSpy2,
123
144
  getKey: jest.fn().mockReturnValue("MY_KEY2"),
124
- shouldRefreshCache: () => false,
125
145
  type: handlerType,
126
- cache: null,
127
146
  hydrate: true,
128
147
  };
129
148
  const options1 = {these: "are options"};
@@ -160,9 +179,7 @@ describe("../request-tracking.js", () => {
160
179
  const fakeHandler: IRequestHandler<any, any> = {
161
180
  fulfillRequest: jest.fn(),
162
181
  getKey: jest.fn().mockReturnValue("MY_KEY"),
163
- shouldRefreshCache: () => false,
164
182
  type: "MY_TYPE",
165
- cache: null,
166
183
  hydrate: true,
167
184
  };
168
185
  const options = {these: "are options"};
@@ -181,9 +198,7 @@ describe("../request-tracking.js", () => {
181
198
  const fakeHandler: IRequestHandler<any, any> = {
182
199
  fulfillRequest: jest.fn().mockResolvedValue(5),
183
200
  getKey: jest.fn().mockReturnValue("MY_KEY"),
184
- shouldRefreshCache: () => false,
185
201
  type: "MY_TYPE",
186
- cache: null,
187
202
  hydrate: true,
188
203
  };
189
204
  const options = {these: "are options"};
@@ -218,9 +233,7 @@ describe("../request-tracking.js", () => {
218
233
  throw new Error("OH NO!");
219
234
  },
220
235
  getKey: jest.fn().mockReturnValue("MY_KEY"),
221
- shouldRefreshCache: () => false,
222
236
  type: "MY_TYPE",
223
- cache: null,
224
237
  hydrate: true,
225
238
  };
226
239
  requestTracker.trackDataRequest(fakeBadHandler, "OPTIONS");
@@ -245,9 +258,7 @@ describe("../request-tracking.js", () => {
245
258
  fulfillRequest: () =>
246
259
  new Promise((resolve, reject) => reject("OH NO!")),
247
260
  getKey: (o) => o,
248
- shouldRefreshCache: () => false,
249
261
  type: "BAD_REQUEST",
250
- cache: null,
251
262
  hydrate: true,
252
263
  };
253
264
  requestTracker.trackDataRequest(
@@ -280,9 +291,7 @@ describe("../request-tracking.js", () => {
280
291
  fulfillRequest: () =>
281
292
  new Promise((resolve, reject) => reject("OH NO!")),
282
293
  getKey: (o) => o,
283
- shouldRefreshCache: () => false,
284
294
  type: "BAD_REQUEST",
285
- cache: null,
286
295
  hydrate: true,
287
296
  };
288
297
  const fakeBadHandler: IRequestHandler<string, any> = {
@@ -290,9 +299,7 @@ describe("../request-tracking.js", () => {
290
299
  throw new Error("OH NO!");
291
300
  },
292
301
  getKey: (o) => o,
293
- shouldRefreshCache: () => false,
294
302
  type: "BAD_HANDLER",
295
- cache: null,
296
303
  hydrate: true,
297
304
  };
298
305
  const fakeValidHandler: IRequestHandler<string, any> = {
@@ -304,9 +311,7 @@ describe("../request-tracking.js", () => {
304
311
  };
305
312
  })(),
306
313
  getKey: (o) => o,
307
- shouldRefreshCache: () => false,
308
314
  type: "VALID",
309
- cache: null,
310
315
  hydrate: true,
311
316
  };
312
317
  requestTracker.trackDataRequest(
@@ -353,9 +358,7 @@ describe("../request-tracking.js", () => {
353
358
  const fakeValidHandler: IRequestHandler<string, any> = {
354
359
  fulfillRequest: () => Promise.resolve("DATA"),
355
360
  getKey: (o) => o,
356
- shouldRefreshCache: () => false,
357
361
  type: "VALID",
358
- cache: null,
359
362
  hydrate: true,
360
363
  };
361
364
  requestTracker.trackDataRequest(fakeValidHandler, "OPTIONS1");
@@ -374,9 +377,7 @@ describe("../request-tracking.js", () => {
374
377
  const fakeStaticHandler: IRequestHandler<string, any> = {
375
378
  fulfillRequest: fakeFulfiller,
376
379
  getKey: (o) => o,
377
- shouldRefreshCache: () => false,
378
380
  type: "STATIC",
379
- cache: null,
380
381
  hydrate: true,
381
382
  };
382
383
  requestTracker.trackDataRequest(fakeStaticHandler, "1");
@@ -401,9 +402,7 @@ describe("../request-tracking.js", () => {
401
402
  const fakeHandler: IRequestHandler<any, any> = {
402
403
  fulfillRequest: fulfillRequestSpy,
403
404
  getKey: jest.fn().mockReturnValue("MY_KEY"),
404
- shouldRefreshCache: () => false,
405
405
  type: "MY_TYPE",
406
- cache: null,
407
406
  hydrate: true,
408
407
  };
409
408
  requestTracker.trackDataRequest(fakeHandler, "OPTIONS");