@khanacademy/wonder-blocks-data 12.0.0 → 13.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 (33) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/components/data.d.ts +2 -2
  3. package/dist/es/index.js +10 -6
  4. package/dist/hooks/use-gql.d.ts +5 -1
  5. package/dist/index.js +10 -6
  6. package/dist/util/status.d.ts +4 -3
  7. package/dist/util/types.d.ts +2 -0
  8. package/package.json +2 -2
  9. package/src/components/__tests__/data.test.tsx +6 -13
  10. package/src/components/data.ts +2 -4
  11. package/src/hooks/__tests__/use-cached-effect.test.tsx +79 -40
  12. package/src/hooks/__tests__/use-gql-router-context.test.tsx +1 -2
  13. package/src/hooks/__tests__/use-hydratable-effect.test.ts +1 -2
  14. package/src/hooks/__tests__/use-request-interception.test.tsx +2 -5
  15. package/src/hooks/__tests__/use-server-effect.test.ts +3 -6
  16. package/src/hooks/__tests__/use-shared-cache.test.ts +17 -13
  17. package/src/hooks/use-cached-effect.ts +24 -20
  18. package/src/hooks/use-gql.ts +12 -9
  19. package/src/hooks/use-request-interception.ts +13 -11
  20. package/src/hooks/use-shared-cache.ts +4 -2
  21. package/src/util/__tests__/request-api.test.ts +2 -1
  22. package/src/util/__tests__/request-tracking.test.tsx +5 -9
  23. package/src/util/__tests__/result-from-cache-response.test.ts +2 -2
  24. package/src/util/__tests__/serializable-in-memory-cache.test.ts +1 -2
  25. package/src/util/__tests__/ssr-cache.test.ts +2 -4
  26. package/src/util/__tests__/to-gql-operation.test.ts +2 -4
  27. package/src/util/graphql-document-node-parser.ts +6 -6
  28. package/src/util/merge-gql-context.ts +2 -1
  29. package/src/util/request-tracking.ts +6 -2
  30. package/src/util/ssr-cache.ts +11 -8
  31. package/src/util/status.ts +6 -0
  32. package/src/util/types.ts +3 -0
  33. package/tsconfig-build.tsbuildinfo +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @khanacademy/wonder-blocks-data
2
2
 
3
+ ## 13.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 65c02cff: Return new no-data state from useCachedEffect when it is not loading and there is no data to return
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [1920feb8]
12
+ - @khanacademy/wonder-blocks-core@6.0.1
13
+
3
14
  ## 12.0.0
4
15
 
5
16
  ### Major Changes
@@ -41,12 +41,12 @@ TData extends ValidCacheData> = {
41
41
  * loading state and data or error that gets retrieved from cache or loaded
42
42
  * via the request if no cached value is available.
43
43
  */
44
- children: (result: Result<TData>) => React.ReactNode;
44
+ children: (result: Result<TData>) => React.ReactElement | null;
45
45
  };
46
46
  /**
47
47
  * This component is the main component of Wonder Blocks Data. With this, data
48
48
  * requirements can be placed in a React application in a manner that will
49
49
  * support server-side rendering and efficient caching.
50
50
  */
51
- declare const Data: <TData extends ValidCacheData>({ requestId, handler, children, retainResultOnChange, clientBehavior, }: Props<TData>) => React.ReactElement;
51
+ declare const Data: <TData extends ValidCacheData>({ requestId, handler, children, retainResultOnChange, clientBehavior, }: Props<TData>) => React.ReactElement | null;
52
52
  export default Data;
package/dist/es/index.js CHANGED
@@ -162,9 +162,9 @@ class SsrCache {
162
162
  this._ssrOnlyCache.purgeAll(realPredicate);
163
163
  };
164
164
  this.cloneHydratableData = () => {
165
- var _cache$DefaultScope;
165
+ var _ref;
166
166
  const cache = this._hydrationCache.clone();
167
- return (_cache$DefaultScope = cache[DefaultScope$2]) != null ? _cache$DefaultScope : {};
167
+ return (_ref = cache[DefaultScope$2]) != null ? _ref : {};
168
168
  };
169
169
  this._ssrOnlyCache = ssrOnlyCache || new SerializableInMemoryCache();
170
170
  this._hydrationCache = hydrationCache || new SerializableInMemoryCache();
@@ -261,7 +261,7 @@ class RequestTracker {
261
261
  }
262
262
  return _default;
263
263
  }
264
- constructor(responseCache = undefined) {
264
+ constructor(responseCache) {
265
265
  this._trackedRequests = {};
266
266
  this._responseCache = void 0;
267
267
  this._requestFulfillment = void 0;
@@ -379,11 +379,15 @@ class TrackData extends React.Component {
379
379
  const loadingStatus = Object.freeze({
380
380
  status: "loading"
381
381
  });
382
+ const noDataStatus = Object.freeze({
383
+ status: "no-data"
384
+ });
382
385
  const abortedStatus = Object.freeze({
383
386
  status: "aborted"
384
387
  });
385
388
  const Status = Object.freeze({
386
389
  loading: () => loadingStatus,
390
+ noData: () => noDataStatus,
387
391
  aborted: () => abortedStatus,
388
392
  success: data => ({
389
393
  status: "success",
@@ -527,8 +531,8 @@ const useCachedEffect = (requestId, handler, options = {}) => {
527
531
  currentRequestRef.current = null;
528
532
  };
529
533
  }, [shouldFetch, fetchRequest]);
530
- const lastResultAgnosticOfIdRef = React.useRef(Status.loading());
531
- const loadingResult = retainResultOnChange ? lastResultAgnosticOfIdRef.current : Status.loading();
534
+ const lastResultAgnosticOfIdRef = React.useRef(Status.noData());
535
+ const loadingResult = retainResultOnChange ? lastResultAgnosticOfIdRef.current : shouldFetch ? Status.loading() : Status.noData();
532
536
  const result = (_ref = fetchPolicy === FetchPolicy.NetworkOnly ? networkResultRef.current : mostRecentResult) != null ? _ref : loadingResult;
533
537
  lastResultAgnosticOfIdRef.current = result;
534
538
  return [result, fetchRequest];
@@ -841,7 +845,7 @@ const useGql = (context = {}) => {
841
845
  context = {}
842
846
  } = options;
843
847
  const finalContext = mergeGqlContext(defaultContext, context);
844
- return fetch(operation, variables, finalContext).then(getGqlDataFromResponse);
848
+ return fetch(operation, variables, finalContext).then(response => getGqlDataFromResponse(response));
845
849
  }, [gqlRouterContext]);
846
850
  return gqlFetch;
847
851
  };
@@ -1,4 +1,7 @@
1
1
  import type { GqlContext, GqlOperation, GqlFetchOptions } from "../util/gql-types";
2
+ interface GqlFetchFn<TContext extends GqlContext> {
3
+ <TData, TVariables extends Record<any, any>>(operation: GqlOperation<TData, TVariables>, options?: GqlFetchOptions<TVariables, TContext>): Promise<TData>;
4
+ }
2
5
  /**
3
6
  * Hook to obtain a gqlFetch function for performing GraphQL requests.
4
7
  *
@@ -9,4 +12,5 @@ import type { GqlContext, GqlOperation, GqlFetchOptions } from "../util/gql-type
9
12
  * Values in the partial context given to the returned fetch function will
10
13
  * only be included if they have a value other than undefined.
11
14
  */
12
- export declare const useGql: <TContext extends GqlContext>(context?: Partial<TContext>) => <TData, TVariables extends Record<any, any>>(operation: GqlOperation<TData, TVariables>, options?: GqlFetchOptions<TVariables, TContext> | undefined) => Promise<TData>;
15
+ export declare const useGql: <TContext extends GqlContext>(context?: Partial<TContext>) => GqlFetchFn<TContext>;
16
+ export {};
package/dist/index.js CHANGED
@@ -185,9 +185,9 @@ class SsrCache {
185
185
  this._ssrOnlyCache.purgeAll(realPredicate);
186
186
  };
187
187
  this.cloneHydratableData = () => {
188
- var _cache$DefaultScope;
188
+ var _ref;
189
189
  const cache = this._hydrationCache.clone();
190
- return (_cache$DefaultScope = cache[DefaultScope$2]) != null ? _cache$DefaultScope : {};
190
+ return (_ref = cache[DefaultScope$2]) != null ? _ref : {};
191
191
  };
192
192
  this._ssrOnlyCache = ssrOnlyCache || new SerializableInMemoryCache();
193
193
  this._hydrationCache = hydrationCache || new SerializableInMemoryCache();
@@ -284,7 +284,7 @@ class RequestTracker {
284
284
  }
285
285
  return _default;
286
286
  }
287
- constructor(responseCache = undefined) {
287
+ constructor(responseCache) {
288
288
  this._trackedRequests = {};
289
289
  this._responseCache = void 0;
290
290
  this._requestFulfillment = void 0;
@@ -402,11 +402,15 @@ class TrackData extends React__namespace.Component {
402
402
  const loadingStatus = Object.freeze({
403
403
  status: "loading"
404
404
  });
405
+ const noDataStatus = Object.freeze({
406
+ status: "no-data"
407
+ });
405
408
  const abortedStatus = Object.freeze({
406
409
  status: "aborted"
407
410
  });
408
411
  const Status = Object.freeze({
409
412
  loading: () => loadingStatus,
413
+ noData: () => noDataStatus,
410
414
  aborted: () => abortedStatus,
411
415
  success: data => ({
412
416
  status: "success",
@@ -550,8 +554,8 @@ const useCachedEffect = (requestId, handler, options = {}) => {
550
554
  currentRequestRef.current = null;
551
555
  };
552
556
  }, [shouldFetch, fetchRequest]);
553
- const lastResultAgnosticOfIdRef = React__namespace.useRef(Status.loading());
554
- const loadingResult = retainResultOnChange ? lastResultAgnosticOfIdRef.current : Status.loading();
557
+ const lastResultAgnosticOfIdRef = React__namespace.useRef(Status.noData());
558
+ const loadingResult = retainResultOnChange ? lastResultAgnosticOfIdRef.current : shouldFetch ? Status.loading() : Status.noData();
555
559
  const result = (_ref = fetchPolicy === FetchPolicy.NetworkOnly ? networkResultRef.current : mostRecentResult) != null ? _ref : loadingResult;
556
560
  lastResultAgnosticOfIdRef.current = result;
557
561
  return [result, fetchRequest];
@@ -864,7 +868,7 @@ const useGql = (context = {}) => {
864
868
  context = {}
865
869
  } = options;
866
870
  const finalContext = mergeGqlContext(defaultContext, context);
867
- return fetch(operation, variables, finalContext).then(getGqlDataFromResponse);
871
+ return fetch(operation, variables, finalContext).then(response => getGqlDataFromResponse(response));
868
872
  }, [gqlRouterContext]);
869
873
  return gqlFetch;
870
874
  };
@@ -4,7 +4,8 @@ import type { Result, ValidCacheData } from "./types";
4
4
  */
5
5
  export declare const Status: Readonly<{
6
6
  loading: <TData extends ValidCacheData = ValidCacheData>() => Result<TData>;
7
- aborted: <TData_1 extends ValidCacheData = ValidCacheData>() => Result<TData_1>;
8
- success: <TData_2 extends ValidCacheData>(data: TData_2) => Result<TData_2>;
9
- error: <TData_3 extends ValidCacheData = ValidCacheData>(error: Error) => Result<TData_3>;
7
+ noData: <TData_1 extends ValidCacheData = ValidCacheData>() => Result<TData_1>;
8
+ aborted: <TData_2 extends ValidCacheData = ValidCacheData>() => Result<TData_2>;
9
+ success: <TData_3 extends ValidCacheData>(data: TData_3) => Result<TData_3>;
10
+ error: <TData_4 extends ValidCacheData = ValidCacheData>(error: Error) => Result<TData_4>;
10
11
  }>;
@@ -34,6 +34,8 @@ export type ValidCacheData = string | boolean | number | Record<any, any> | Arra
34
34
  */
35
35
  export type Result<TData extends ValidCacheData> = {
36
36
  status: "loading";
37
+ } | {
38
+ status: "no-data";
37
39
  } | {
38
40
  status: "success";
39
41
  data: TData;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-data",
3
- "version": "12.0.0",
3
+ "version": "13.0.0",
4
4
  "design": "v1",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "@babel/runtime": "^7.18.6",
17
- "@khanacademy/wonder-blocks-core": "^6.0.0"
17
+ "@khanacademy/wonder-blocks-core": "^6.0.1"
18
18
  },
19
19
  "peerDependencies": {
20
20
  "@khanacademy/wonder-stuff-core": "^1.2.2",
@@ -47,7 +47,7 @@ describe("Data", () => {
47
47
 
48
48
  it("should make request for data on construction", async () => {
49
49
  // Arrange
50
- const response = Promise.resolve("data");
50
+ const response: any = Promise.resolve("data");
51
51
  const fakeHandler = jest.fn().mockReturnValue(response);
52
52
  const fakeChildrenFn = jest.fn(() => null);
53
53
 
@@ -57,7 +57,6 @@ describe("Data", () => {
57
57
  {fakeChildrenFn}
58
58
  </Data>,
59
59
  );
60
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
61
60
  await act(() => response);
62
61
 
63
62
  // Assert
@@ -66,7 +65,7 @@ describe("Data", () => {
66
65
 
67
66
  it("should initially render children with loading", async () => {
68
67
  // Arrange
69
- const response = Promise.resolve("data");
68
+ const response: any = Promise.resolve("data");
70
69
  const fakeHandler = jest.fn().mockReturnValue(response);
71
70
  const fakeChildrenFn = jest.fn(() => null);
72
71
 
@@ -76,7 +75,6 @@ describe("Data", () => {
76
75
  {fakeChildrenFn}
77
76
  </Data>,
78
77
  );
79
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
80
78
  await act(() => response);
81
79
 
82
80
  // Assert
@@ -272,7 +270,7 @@ describe("Data", () => {
272
270
 
273
271
  it("should ignore resolution of pending handler fulfillment when id changes", async () => {
274
272
  // Arrange
275
- const oldRequest = Promise.resolve("OLD DATA");
273
+ const oldRequest: any = Promise.resolve("OLD DATA");
276
274
  const oldHandler = jest
277
275
  .fn()
278
276
  .mockReturnValueOnce(oldRequest)
@@ -294,7 +292,6 @@ describe("Data", () => {
294
292
  {fakeChildrenFn}
295
293
  </Data>,
296
294
  );
297
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
298
295
  await act(() => oldRequest);
299
296
 
300
297
  // Assert
@@ -343,14 +340,13 @@ describe("Data", () => {
343
340
 
344
341
  it("should ignore catastrophic request fulfillment when id changes", async () => {
345
342
  // Arrange
346
- const catastrophe = Promise.resolve({
343
+ const catastrophe: any = Promise.resolve({
347
344
  status: "error",
348
345
  error: new Error("CATASTROPHE!"),
349
346
  });
350
347
  jest.spyOn(
351
348
  RequestFulfillment.Default,
352
349
  "fulfill",
353
- // @ts-expect-error [FEI-5019] - TS2345 - Argument of type 'Promise<{ status: string; error: Error; }>' is not assignable to parameter of type 'Promise<Result<ValidCacheData>>'.
354
350
  ).mockReturnValueOnce(catastrophe);
355
351
  const oldHandler = jest.fn().mockResolvedValue("OLD DATA");
356
352
 
@@ -367,7 +363,6 @@ describe("Data", () => {
367
363
  </Data>,
368
364
  );
369
365
  await act(() =>
370
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
371
366
  catastrophe.catch(() => {
372
367
  /* ignore */
373
368
  }),
@@ -428,8 +423,8 @@ describe("Data", () => {
428
423
 
429
424
  it("should retain old data while reloading if retainResultOnChange is true", async () => {
430
425
  // Arrange
431
- const response1 = Promise.resolve("data1");
432
- const response2 = Promise.resolve("data2");
426
+ const response1: any = Promise.resolve("data1");
427
+ const response2: any = Promise.resolve("data2");
433
428
  const fakeHandler1 = () => response1;
434
429
  const fakeHandler2 = () => response2;
435
430
  const fakeChildrenFn = jest.fn(() => null);
@@ -445,7 +440,6 @@ describe("Data", () => {
445
440
  </Data>,
446
441
  );
447
442
  fakeChildrenFn.mockClear();
448
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
449
443
  await act(() => response1);
450
444
  wrapper.rerender(
451
445
  <Data
@@ -456,7 +450,6 @@ describe("Data", () => {
456
450
  {fakeChildrenFn}
457
451
  </Data>,
458
452
  );
459
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
460
453
  await act(() => response2);
461
454
 
462
455
  // Assert
@@ -48,7 +48,7 @@ type Props<
48
48
  * loading state and data or error that gets retrieved from cache or loaded
49
49
  * via the request if no cached value is available.
50
50
  */
51
- children: (result: Result<TData>) => React.ReactNode;
51
+ children: (result: Result<TData>) => React.ReactElement | null;
52
52
  };
53
53
 
54
54
  /**
@@ -62,13 +62,11 @@ const Data = <TData extends ValidCacheData>({
62
62
  children,
63
63
  retainResultOnChange = false,
64
64
  clientBehavior = WhenClientSide.ExecuteWhenNoSuccessResult,
65
- }: Props<TData>): React.ReactElement => {
65
+ }: Props<TData>): React.ReactElement | null => {
66
66
  const result = useHydratableEffect(requestId, handler, {
67
67
  retainResultOnChange,
68
68
  clientBehavior,
69
69
  });
70
- // @ts-expect-error: React TS types don't allow functional components to return
71
- // ReactNodes even though React itself does.
72
70
  return children(result);
73
71
  };
74
72
 
@@ -22,8 +22,9 @@ jest.mock("../use-request-interception");
22
22
  jest.mock("../use-shared-cache");
23
23
 
24
24
  const allPolicies = Array.from(values(FetchPolicy));
25
- const allPoliciesBut = (policy: typeof FetchPolicy[keyof typeof FetchPolicy]) =>
26
- allPolicies.filter((p: any) => p !== policy);
25
+ const allPoliciesBut = (
26
+ ...policies: Array<typeof FetchPolicy[keyof typeof FetchPolicy]>
27
+ ) => allPolicies.filter((p: any) => !policies.includes(p));
27
28
 
28
29
  describe("#useCachedEffect", () => {
29
30
  beforeEach(() => {
@@ -116,7 +117,7 @@ describe("#useCachedEffect", () => {
116
117
  },
117
118
  );
118
119
 
119
- describe.each(allPolicies)(
120
+ describe.each(allPoliciesBut(FetchPolicy.CacheOnly))(
120
121
  "with FetchPolicy.%s without cached result",
121
122
  (fetchPolicy: any) => {
122
123
  it("should return a loading result", () => {
@@ -138,6 +139,27 @@ describe("#useCachedEffect", () => {
138
139
  },
139
140
  );
140
141
 
142
+ describe("with FetchPolicy.CacheOnly without cached result", () => {
143
+ it("should return a no-data result", () => {
144
+ // Arrange
145
+ const fakeHandler = jest.fn();
146
+
147
+ // Act
148
+ const {
149
+ result: {
150
+ current: [result],
151
+ },
152
+ } = serverRenderHook(() =>
153
+ useCachedEffect("ID", fakeHandler, {
154
+ fetchPolicy: FetchPolicy.CacheOnly,
155
+ }),
156
+ );
157
+
158
+ // Assert
159
+ expect(result).toStrictEqual(Status.noData());
160
+ });
161
+ });
162
+
141
163
  describe.each(allPoliciesBut(FetchPolicy.NetworkOnly))(
142
164
  "with FetchPolicy.%s with cached result",
143
165
  (fetchPolicy: any) => {
@@ -232,7 +254,7 @@ describe("#useCachedEffect", () => {
232
254
  "should provide function that causes refetch with FetchPolicy.%s",
233
255
  async (fetchPolicy: any) => {
234
256
  // Arrange
235
- const response = Promise.resolve("DATA1");
257
+ const response: any = Promise.resolve("DATA1");
236
258
  const fakeHandler = jest.fn().mockReturnValue(response);
237
259
 
238
260
  // Act
@@ -244,11 +266,9 @@ describe("#useCachedEffect", () => {
244
266
  useCachedEffect("ID", fakeHandler, {fetchPolicy}),
245
267
  );
246
268
  fakeHandler.mockClear();
247
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
248
- await act((): Promise<unknown> => response);
269
+ await act(() => response);
249
270
  act(refetch);
250
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
251
- await act((): Promise<unknown> => response);
271
+ await act(() => response);
252
272
 
253
273
  // Assert
254
274
  expect(fakeHandler).toHaveBeenCalledTimes(1);
@@ -426,7 +446,7 @@ describe("#useCachedEffect", () => {
426
446
 
427
447
  it("should ignore inflight request if requestId changes", async () => {
428
448
  // Arrange
429
- const response1 = Promise.resolve("DATA1");
449
+ const response1: any = Promise.resolve("DATA1");
430
450
  const response2 = Promise.resolve("DATA2");
431
451
  const fakeHandler = jest
432
452
  .fn()
@@ -449,7 +469,7 @@ describe("#useCachedEffect", () => {
449
469
 
450
470
  it("should return result of fulfilled request for current requestId", async () => {
451
471
  // Arrange
452
- const response1 = Promise.resolve("DATA1");
472
+ const response1: any = Promise.resolve("DATA1");
453
473
  const response2 = Promise.resolve("DATA2");
454
474
  const fakeHandler = jest
455
475
  .fn()
@@ -485,7 +505,7 @@ describe("#useCachedEffect", () => {
485
505
 
486
506
  it("should ignore result of inflight request if skip changes", async () => {
487
507
  // Arrange
488
- const response1 = Promise.resolve("DATA1");
508
+ const response1: any = Promise.resolve("DATA1");
489
509
  const fakeHandler = jest.fn().mockReturnValueOnce(response1);
490
510
 
491
511
  // Act
@@ -496,8 +516,7 @@ describe("#useCachedEffect", () => {
496
516
  },
497
517
  );
498
518
  rerender({skip: true});
499
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
500
- await act((): Promise<unknown> => response1);
519
+ await act(() => response1);
501
520
 
502
521
  // Assert
503
522
  expect(result.all).not.toContainEqual(Status.success("DATA1"));
@@ -505,7 +524,7 @@ describe("#useCachedEffect", () => {
505
524
 
506
525
  it("should not ignore result of inflight request if handler changes", async () => {
507
526
  // Arrange
508
- const response1 = Promise.resolve("DATA1");
527
+ const response1: any = Promise.resolve("DATA1");
509
528
  const response2 = Promise.resolve("DATA2");
510
529
  const fakeHandler1 = jest.fn().mockReturnValueOnce(response1);
511
530
  const fakeHandler2 = jest.fn().mockReturnValueOnce(response2);
@@ -526,7 +545,7 @@ describe("#useCachedEffect", () => {
526
545
 
527
546
  it("should not ignore inflight request if options (other than skip) change", async () => {
528
547
  // Arrange
529
- const response1 = Promise.resolve("DATA1");
548
+ const response1: any = Promise.resolve("DATA1");
530
549
  const fakeHandler = jest.fn().mockReturnValueOnce(response1);
531
550
 
532
551
  // Act
@@ -537,13 +556,11 @@ describe("#useCachedEffect", () => {
537
556
  },
538
557
  );
539
558
  rerender({
540
- // @ts-expect-error [FEI-5019] - TS2322 - Type '{ scope: string; }' is not assignable to type 'undefined'.
541
559
  options: {
542
560
  scope: "BLAH!",
543
561
  },
544
- });
545
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
546
- await act((): Promise<unknown> => response1);
562
+ } as any);
563
+ await act(() => response1);
547
564
 
548
565
  // Assert
549
566
  expect(result.current[0]).toStrictEqual(Status.success("DATA1"));
@@ -551,7 +568,7 @@ describe("#useCachedEffect", () => {
551
568
 
552
569
  it("should return previous result when requestId changes and retainResultOnChange is true", async () => {
553
570
  // Arrange
554
- const response1 = Promise.resolve("DATA1");
571
+ const response1: any = Promise.resolve("DATA1");
555
572
  const response2 = Promise.resolve("DATA2");
556
573
  const fakeHandler = jest
557
574
  .fn()
@@ -572,8 +589,7 @@ describe("#useCachedEffect", () => {
572
589
  initialProps: {requestId: "ID"},
573
590
  },
574
591
  );
575
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
576
- await act((): Promise<unknown> => response1);
592
+ await act(() => response1);
577
593
  rerender({requestId: "ID2"});
578
594
  const [result] = hookResult.current;
579
595
  await waitForNextUpdate();
@@ -584,7 +600,7 @@ describe("#useCachedEffect", () => {
584
600
 
585
601
  it("should return loading status when requestId changes and retainResultOnChange is false", async () => {
586
602
  // Arrange
587
- const response1 = Promise.resolve("DATA1");
603
+ const response1: any = Promise.resolve("DATA1");
588
604
  const response2 = new Promise(() => {
589
605
  /*pending*/
590
606
  });
@@ -603,19 +619,47 @@ describe("#useCachedEffect", () => {
603
619
  initialProps: {requestId: "ID"},
604
620
  },
605
621
  );
606
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
607
- await act((): Promise<unknown> => response1);
622
+ await act(() => response1);
608
623
  rerender({requestId: "ID2"});
609
624
 
610
625
  // Assert
611
626
  expect(result.current[0]).toStrictEqual(Status.loading());
612
627
  });
613
628
 
629
+ it("should return no-data status when requestId changes, retainResultOnChange is false, and skip is true", async () => {
630
+ // Arrange
631
+ const response1: any = Promise.resolve("DATA1");
632
+ const response2 = new Promise(() => {
633
+ /*pending*/
634
+ });
635
+ const fakeHandler = jest
636
+ .fn()
637
+ .mockReturnValueOnce(response1)
638
+ .mockReturnValueOnce(response2);
639
+
640
+ // Act
641
+ const {rerender, result} = clientRenderHook(
642
+ ({requestId}: any) =>
643
+ useCachedEffect(requestId, fakeHandler, {
644
+ retainResultOnChange: false,
645
+ skip: true,
646
+ }),
647
+ {
648
+ initialProps: {requestId: "ID"},
649
+ },
650
+ );
651
+ await act(() => response1);
652
+ rerender({requestId: "ID2"});
653
+
654
+ // Assert
655
+ expect(result.current[0]).toStrictEqual(Status.noData());
656
+ });
657
+
614
658
  it.each(allPoliciesBut(FetchPolicy.CacheOnly))(
615
659
  "should trigger render when request is fulfilled and onResultChanged is undefined for FetchPolicy.%s",
616
660
  async (fetchPolicy: any) => {
617
661
  // Arrange
618
- const response = Promise.resolve("DATA");
662
+ const response: any = Promise.resolve("DATA");
619
663
  const fakeHandler = jest.fn().mockReturnValue(response);
620
664
  let renderCount = 0;
621
665
  const Component = React.memo(() => {
@@ -626,8 +670,7 @@ describe("#useCachedEffect", () => {
626
670
 
627
671
  // Act
628
672
  render(<Component />);
629
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
630
- await reactAct((): Promise<unknown> => response);
673
+ await reactAct(() => response);
631
674
 
632
675
  // Assert
633
676
  expect(renderCount).toBe(2);
@@ -638,7 +681,7 @@ describe("#useCachedEffect", () => {
638
681
  "should trigger render once per inflight request being fulfilled and onResultChanged is undefined for FetchPolicy.%s",
639
682
  async (fetchPolicy: any) => {
640
683
  // Arrange
641
- const response = Promise.resolve("DATA");
684
+ const response: any = Promise.resolve("DATA");
642
685
  const fakeHandler = jest.fn().mockReturnValue(response);
643
686
  let renderCount = 0;
644
687
  const Component = React.memo(() => {
@@ -657,8 +700,7 @@ describe("#useCachedEffect", () => {
657
700
 
658
701
  // Act
659
702
  render(<Component />);
660
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
661
- await reactAct((): Promise<unknown> => response);
703
+ await reactAct(() => response);
662
704
 
663
705
  // Assert
664
706
  expect(renderCount).toBe(2);
@@ -669,7 +711,7 @@ describe("#useCachedEffect", () => {
669
711
  "should not trigger render when request is fulfilled and onResultChanged is defined for FetchPolicy.%s",
670
712
  async (fetchPolicy: any) => {
671
713
  // Arrange
672
- const response = Promise.resolve("DATA");
714
+ const response: any = Promise.resolve("DATA");
673
715
  const fakeHandler = jest.fn().mockReturnValue(response);
674
716
  let renderCount = 0;
675
717
  const Component = React.memo(() => {
@@ -683,8 +725,7 @@ describe("#useCachedEffect", () => {
683
725
 
684
726
  // Act
685
727
  render(<Component />);
686
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
687
- await reactAct((): Promise<unknown> => response);
728
+ await reactAct(() => response);
688
729
 
689
730
  // Assert
690
731
  expect(renderCount).toBe(1);
@@ -695,7 +736,7 @@ describe("#useCachedEffect", () => {
695
736
  "should call onResultChanged when request is fulfilled and onResultChanged is defined for FetchPolicy.%s",
696
737
  async (fetchPolicy: any) => {
697
738
  // Arrange
698
- const response = Promise.resolve("DATA");
739
+ const response: any = Promise.resolve("DATA");
699
740
  const fakeHandler = jest.fn().mockReturnValue(response);
700
741
  const onResultChanged = jest.fn();
701
742
 
@@ -706,8 +747,7 @@ describe("#useCachedEffect", () => {
706
747
  fetchPolicy,
707
748
  }),
708
749
  );
709
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
710
- await act((): Promise<unknown> => response);
750
+ await act(() => response);
711
751
 
712
752
  // Assert
713
753
  expect(onResultChanged).toHaveBeenCalledWith(
@@ -720,7 +760,7 @@ describe("#useCachedEffect", () => {
720
760
  "should call onResultChanged once per inflight request being fulfilled and onResultChanged is defined for FetchPolicy.%s",
721
761
  async (fetchPolicy: any) => {
722
762
  // Arrange
723
- const response = Promise.resolve("DATA");
763
+ const response: any = Promise.resolve("DATA");
724
764
  const fakeHandler = jest.fn().mockReturnValue(response);
725
765
  const onResultChanged = jest.fn();
726
766
 
@@ -739,8 +779,7 @@ describe("#useCachedEffect", () => {
739
779
  act(refetch);
740
780
  act(refetch);
741
781
  act(refetch);
742
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
743
- await act((): Promise<unknown> => response);
782
+ await act(() => response);
744
783
 
745
784
  // Assert
746
785
  expect(onResultChanged).toHaveBeenCalledTimes(1);
@@ -123,8 +123,7 @@ describe("#useGqlRouterContext", () => {
123
123
  },
124
124
  );
125
125
  const result1 = wrapper.result.current;
126
- // @ts-expect-error [FEI-5019] - TS2741 - Property 'fiz' is missing in type '{}' but required in type '{ fiz: string; }'.
127
- wrapper.rerender({overrides: {}});
126
+ wrapper.rerender({overrides: {} as any});
128
127
  const result2 = wrapper.result.current;
129
128
 
130
129
  // Assert
@@ -562,10 +562,9 @@ describe("#useHydratableEffect", () => {
562
562
  },
563
563
  );
564
564
  rerender({
565
- // @ts-expect-error [FEI-5019] - TS2322 - Type '{ scope: string; }' is not assignable to type 'undefined'.
566
565
  options: {
567
566
  scope: "BLAH!",
568
- },
567
+ } as any,
569
568
  });
570
569
 
571
570
  await act((): Promise<any> => response1);