@shopify/flash-list 2.0.4-alpha.1 → 2.2.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.
- package/dist/AnimatedFlashList.js +4 -6
- package/dist/AnimatedFlashList.js.map +1 -1
- package/dist/FlashList.js +1 -5
- package/dist/FlashList.js.map +1 -1
- package/dist/FlashListProps.d.ts +41 -1
- package/dist/FlashListProps.d.ts.map +1 -1
- package/dist/FlashListProps.js +1 -4
- package/dist/FlashListProps.js.map +1 -1
- package/dist/FlashListRef.js +1 -2
- package/dist/benchmark/AutoScrollHelper.js +22 -30
- package/dist/benchmark/AutoScrollHelper.js.map +1 -1
- package/dist/benchmark/JSFPSMonitor.js +27 -33
- package/dist/benchmark/JSFPSMonitor.js.map +1 -1
- package/dist/benchmark/roundToDecimalPlaces.js +2 -5
- package/dist/benchmark/roundToDecimalPlaces.js.map +1 -1
- package/dist/benchmark/useBenchmark.d.ts +9 -1
- package/dist/benchmark/useBenchmark.d.ts.map +1 -1
- package/dist/benchmark/useBenchmark.js +86 -95
- package/dist/benchmark/useBenchmark.js.map +1 -1
- package/dist/benchmark/useDataMultiplier.js +6 -10
- package/dist/benchmark/useDataMultiplier.js.map +1 -1
- package/dist/benchmark/useFlatListBenchmark.d.ts +4 -1
- package/dist/benchmark/useFlatListBenchmark.d.ts.map +1 -1
- package/dist/benchmark/useFlatListBenchmark.js +73 -81
- package/dist/benchmark/useFlatListBenchmark.js.map +1 -1
- package/dist/errors/ErrorMessages.js +1 -4
- package/dist/errors/ErrorMessages.js.map +1 -1
- package/dist/errors/WarningMessages.js +1 -4
- package/dist/errors/WarningMessages.js.map +1 -1
- package/dist/index.js +17 -35
- package/dist/index.js.map +1 -1
- package/dist/isNewArch.js +6 -9
- package/dist/isNewArch.js.map +1 -1
- package/dist/native/config/PlatformHelper.android.js +2 -5
- package/dist/native/config/PlatformHelper.android.js.map +1 -1
- package/dist/native/config/PlatformHelper.ios.js +2 -5
- package/dist/native/config/PlatformHelper.ios.js.map +1 -1
- package/dist/native/config/PlatformHelper.js +2 -5
- package/dist/native/config/PlatformHelper.js.map +1 -1
- package/dist/native/config/PlatformHelper.web.js +2 -5
- package/dist/native/config/PlatformHelper.web.js.map +1 -1
- package/dist/recyclerview/LayoutCommitObserver.js +20 -24
- package/dist/recyclerview/LayoutCommitObserver.js.map +1 -1
- package/dist/recyclerview/RecyclerView.d.ts.map +1 -1
- package/dist/recyclerview/RecyclerView.js +134 -111
- package/dist/recyclerview/RecyclerView.js.map +1 -1
- package/dist/recyclerview/RecyclerViewContextProvider.js +7 -12
- package/dist/recyclerview/RecyclerViewContextProvider.js.map +1 -1
- package/dist/recyclerview/RecyclerViewManager.js +138 -167
- package/dist/recyclerview/RecyclerViewManager.js.map +1 -1
- package/dist/recyclerview/RecyclerViewProps.js +1 -2
- package/dist/recyclerview/RenderStackManager.js +97 -188
- package/dist/recyclerview/RenderStackManager.js.map +1 -1
- package/dist/recyclerview/ViewHolder.d.ts +2 -0
- package/dist/recyclerview/ViewHolder.d.ts.map +1 -1
- package/dist/recyclerview/ViewHolder.js +19 -21
- package/dist/recyclerview/ViewHolder.js.map +1 -1
- package/dist/recyclerview/ViewHolderCollection.d.ts +4 -0
- package/dist/recyclerview/ViewHolderCollection.d.ts.map +1 -1
- package/dist/recyclerview/ViewHolderCollection.js +26 -30
- package/dist/recyclerview/ViewHolderCollection.js.map +1 -1
- package/dist/recyclerview/components/CompatScroller.js +6 -7
- package/dist/recyclerview/components/CompatScroller.js.map +1 -1
- package/dist/recyclerview/components/CompatView.js +6 -7
- package/dist/recyclerview/components/CompatView.js.map +1 -1
- package/dist/recyclerview/components/ScrollAnchor.js +10 -15
- package/dist/recyclerview/components/ScrollAnchor.js.map +1 -1
- package/dist/recyclerview/components/StickyHeaders.d.ts +5 -1
- package/dist/recyclerview/components/StickyHeaders.d.ts.map +1 -1
- package/dist/recyclerview/components/StickyHeaders.js +77 -51
- package/dist/recyclerview/components/StickyHeaders.js.map +1 -1
- package/dist/recyclerview/helpers/ConsecutiveNumbers.js +39 -66
- package/dist/recyclerview/helpers/ConsecutiveNumbers.js.map +1 -1
- package/dist/recyclerview/helpers/EngagedIndicesTracker.js +57 -63
- package/dist/recyclerview/helpers/EngagedIndicesTracker.js.map +1 -1
- package/dist/recyclerview/helpers/RenderTimeTracker.js +19 -24
- package/dist/recyclerview/helpers/RenderTimeTracker.js.map +1 -1
- package/dist/recyclerview/helpers/VelocityTracker.js +16 -22
- package/dist/recyclerview/helpers/VelocityTracker.js.map +1 -1
- package/dist/recyclerview/hooks/useBoundDetection.js +37 -40
- package/dist/recyclerview/hooks/useBoundDetection.js.map +1 -1
- package/dist/recyclerview/hooks/useLayoutState.js +9 -15
- package/dist/recyclerview/hooks/useLayoutState.js.map +1 -1
- package/dist/recyclerview/hooks/useMappingHelper.js +6 -10
- package/dist/recyclerview/hooks/useMappingHelper.js.map +1 -1
- package/dist/recyclerview/hooks/useOnLoad.js +16 -22
- package/dist/recyclerview/hooks/useOnLoad.js.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewController.d.ts.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewController.js +169 -188
- package/dist/recyclerview/hooks/useRecyclerViewController.js.map +1 -1
- package/dist/recyclerview/hooks/useRecyclerViewManager.js +12 -17
- package/dist/recyclerview/hooks/useRecyclerViewManager.js.map +1 -1
- package/dist/recyclerview/hooks/useRecyclingState.js +10 -14
- package/dist/recyclerview/hooks/useRecyclingState.js.map +1 -1
- package/dist/recyclerview/hooks/useSecondaryProps.d.ts +2 -0
- package/dist/recyclerview/hooks/useSecondaryProps.d.ts.map +1 -1
- package/dist/recyclerview/hooks/useSecondaryProps.js +39 -30
- package/dist/recyclerview/hooks/useSecondaryProps.js.map +1 -1
- package/dist/recyclerview/hooks/useUnmountAwareCallbacks.js +17 -22
- package/dist/recyclerview/hooks/useUnmountAwareCallbacks.js.map +1 -1
- package/dist/recyclerview/hooks/useUnmountFlag.js +5 -9
- package/dist/recyclerview/hooks/useUnmountFlag.js.map +1 -1
- package/dist/recyclerview/layout-managers/GridLayoutManager.js +61 -80
- package/dist/recyclerview/layout-managers/GridLayoutManager.js.map +1 -1
- package/dist/recyclerview/layout-managers/LayoutManager.js +83 -123
- package/dist/recyclerview/layout-managers/LayoutManager.js.map +1 -1
- package/dist/recyclerview/layout-managers/LinearLayoutManager.js +51 -91
- package/dist/recyclerview/layout-managers/LinearLayoutManager.js.map +1 -1
- package/dist/recyclerview/layout-managers/MasonryLayoutManager.js +77 -96
- package/dist/recyclerview/layout-managers/MasonryLayoutManager.js.map +1 -1
- package/dist/recyclerview/utils/adjustOffsetForRTL.js +1 -4
- package/dist/recyclerview/utils/adjustOffsetForRTL.js.map +1 -1
- package/dist/recyclerview/utils/componentUtils.js +4 -9
- package/dist/recyclerview/utils/componentUtils.js.map +1 -1
- package/dist/recyclerview/utils/findVisibleIndex.js +9 -13
- package/dist/recyclerview/utils/findVisibleIndex.js.map +1 -1
- package/dist/recyclerview/utils/measureLayout.js +12 -20
- package/dist/recyclerview/utils/measureLayout.js.map +1 -1
- package/dist/recyclerview/utils/measureLayout.web.js +15 -23
- package/dist/recyclerview/utils/measureLayout.web.js.map +1 -1
- package/dist/recyclerview/viewability/ViewToken.js +1 -2
- package/dist/recyclerview/viewability/ViewabilityHelper.js +34 -41
- package/dist/recyclerview/viewability/ViewabilityHelper.js.map +1 -1
- package/dist/recyclerview/viewability/ViewabilityManager.js +48 -61
- package/dist/recyclerview/viewability/ViewabilityManager.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/AverageWindow.js +28 -39
- package/dist/utils/AverageWindow.js.map +1 -1
- package/package.json +4 -6
- package/src/FlashListProps.ts +51 -1
- package/src/benchmark/useBenchmark.ts +47 -4
- package/src/benchmark/useFlatListBenchmark.ts +38 -5
- package/src/recyclerview/RecyclerView.tsx +42 -8
- package/src/recyclerview/ViewHolder.tsx +6 -1
- package/src/recyclerview/ViewHolderCollection.tsx +10 -0
- package/src/recyclerview/components/StickyHeaders.tsx +54 -13
- package/src/recyclerview/hooks/useRecyclerViewController.tsx +7 -4
- package/src/recyclerview/hooks/useSecondaryProps.tsx +23 -0
- package/dist/__tests__/AverageWindow.test.d.ts +0 -2
- package/dist/__tests__/AverageWindow.test.d.ts.map +0 -1
- package/dist/__tests__/AverageWindow.test.js +0 -104
- package/dist/__tests__/AverageWindow.test.js.map +0 -1
- package/dist/__tests__/ConsecutiveNumbers.test.d.ts +0 -2
- package/dist/__tests__/ConsecutiveNumbers.test.d.ts.map +0 -1
- package/dist/__tests__/ConsecutiveNumbers.test.js +0 -224
- package/dist/__tests__/ConsecutiveNumbers.test.js.map +0 -1
- package/dist/__tests__/GridLayoutManager.test.d.ts +0 -2
- package/dist/__tests__/GridLayoutManager.test.d.ts.map +0 -1
- package/dist/__tests__/GridLayoutManager.test.js +0 -69
- package/dist/__tests__/GridLayoutManager.test.js.map +0 -1
- package/dist/__tests__/LayoutCommitObserver.test.d.ts +0 -2
- package/dist/__tests__/LayoutCommitObserver.test.d.ts.map +0 -1
- package/dist/__tests__/LayoutCommitObserver.test.js +0 -37
- package/dist/__tests__/LayoutCommitObserver.test.js.map +0 -1
- package/dist/__tests__/LinearLayoutManager.test.d.ts +0 -2
- package/dist/__tests__/LinearLayoutManager.test.d.ts.map +0 -1
- package/dist/__tests__/LinearLayoutManager.test.js +0 -140
- package/dist/__tests__/LinearLayoutManager.test.js.map +0 -1
- package/dist/__tests__/MasonryLayoutManager.test.d.ts +0 -2
- package/dist/__tests__/MasonryLayoutManager.test.d.ts.map +0 -1
- package/dist/__tests__/MasonryLayoutManager.test.js +0 -148
- package/dist/__tests__/MasonryLayoutManager.test.js.map +0 -1
- package/dist/__tests__/RecyclerView.test.d.ts +0 -2
- package/dist/__tests__/RecyclerView.test.d.ts.map +0 -1
- package/dist/__tests__/RecyclerView.test.js +0 -103
- package/dist/__tests__/RecyclerView.test.js.map +0 -1
- package/dist/__tests__/RecyclerViewManager.test.d.ts +0 -2
- package/dist/__tests__/RecyclerViewManager.test.d.ts.map +0 -1
- package/dist/__tests__/RecyclerViewManager.test.js +0 -56
- package/dist/__tests__/RecyclerViewManager.test.js.map +0 -1
- package/dist/__tests__/RenderStackManager.test.d.ts +0 -2
- package/dist/__tests__/RenderStackManager.test.d.ts.map +0 -1
- package/dist/__tests__/RenderStackManager.test.js +0 -485
- package/dist/__tests__/RenderStackManager.test.js.map +0 -1
- package/dist/__tests__/ViewabilityHelper.test.d.ts +0 -2
- package/dist/__tests__/ViewabilityHelper.test.d.ts.map +0 -1
- package/dist/__tests__/ViewabilityHelper.test.js +0 -186
- package/dist/__tests__/ViewabilityHelper.test.js.map +0 -1
- package/dist/__tests__/findVisibleIndex.test.d.ts +0 -2
- package/dist/__tests__/findVisibleIndex.test.d.ts.map +0 -1
- package/dist/__tests__/findVisibleIndex.test.js +0 -259
- package/dist/__tests__/findVisibleIndex.test.js.map +0 -1
- package/dist/__tests__/helpers/createLayoutManager.d.ts +0 -34
- package/dist/__tests__/helpers/createLayoutManager.d.ts.map +0 -1
- package/dist/__tests__/helpers/createLayoutManager.js +0 -110
- package/dist/__tests__/helpers/createLayoutManager.js.map +0 -1
- package/dist/__tests__/useUnmountAwareCallbacks.test.d.ts +0 -2
- package/dist/__tests__/useUnmountAwareCallbacks.test.d.ts.map +0 -1
- package/dist/__tests__/useUnmountAwareCallbacks.test.js +0 -185
- package/dist/__tests__/useUnmountAwareCallbacks.test.js.map +0 -1
- package/src/__tests__/AverageWindow.test.ts +0 -128
- package/src/__tests__/ConsecutiveNumbers.test.ts +0 -232
- package/src/__tests__/GridLayoutManager.test.ts +0 -113
- package/src/__tests__/LayoutCommitObserver.test.tsx +0 -63
- package/src/__tests__/LinearLayoutManager.test.ts +0 -227
- package/src/__tests__/MasonryLayoutManager.test.ts +0 -202
- package/src/__tests__/RecyclerView.test.tsx +0 -144
- package/src/__tests__/RecyclerViewManager.test.ts +0 -74
- package/src/__tests__/RenderStackManager.test.ts +0 -574
- package/src/__tests__/ViewabilityHelper.test.ts +0 -282
- package/src/__tests__/findVisibleIndex.test.ts +0 -369
- package/src/__tests__/helpers/createLayoutManager.ts +0 -141
- package/src/__tests__/useUnmountAwareCallbacks.test.tsx +0 -285
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @shopify/typescript/prefer-pascal-case-enums */
|
|
2
|
-
import {
|
|
3
|
-
LayoutParams,
|
|
4
|
-
RVDimension,
|
|
5
|
-
RVLayout,
|
|
6
|
-
RVLayoutInfo,
|
|
7
|
-
RVLayoutManager,
|
|
8
|
-
} from "../../recyclerview/layout-managers/LayoutManager";
|
|
9
|
-
import { RVLinearLayoutManagerImpl } from "../../recyclerview/layout-managers/LinearLayoutManager";
|
|
10
|
-
import { RVGridLayoutManagerImpl } from "../../recyclerview/layout-managers/GridLayoutManager";
|
|
11
|
-
import { RVMasonryLayoutManagerImpl } from "../../recyclerview/layout-managers/MasonryLayoutManager";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Layout manager types available in the app
|
|
15
|
-
*/
|
|
16
|
-
export enum LayoutManagerType {
|
|
17
|
-
LINEAR = "linear",
|
|
18
|
-
GRID = "grid",
|
|
19
|
-
MASONRY = "masonry",
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Default window size for layout managers
|
|
24
|
-
*/
|
|
25
|
-
const DEFAULT_WINDOW_SIZE: RVDimension = {
|
|
26
|
-
width: 400,
|
|
27
|
-
height: 900,
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Create layout parameters with sensible defaults
|
|
32
|
-
*/
|
|
33
|
-
export function createLayoutParams(
|
|
34
|
-
params: Partial<LayoutParams> = {}
|
|
35
|
-
): LayoutParams {
|
|
36
|
-
return {
|
|
37
|
-
windowSize: params.windowSize || DEFAULT_WINDOW_SIZE,
|
|
38
|
-
horizontal: params.horizontal ?? false,
|
|
39
|
-
maxColumns: params.maxColumns ?? 1,
|
|
40
|
-
optimizeItemArrangement: params.optimizeItemArrangement ?? true,
|
|
41
|
-
overrideItemLayout: params.overrideItemLayout ?? (() => {}),
|
|
42
|
-
getItemType: params.getItemType ?? (() => "default"),
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Create a layout manager of the specified type
|
|
48
|
-
*/
|
|
49
|
-
export function createLayoutManager(
|
|
50
|
-
type: LayoutManagerType,
|
|
51
|
-
params: Partial<LayoutParams> = {},
|
|
52
|
-
previousLayoutManager?: RVLayoutManager
|
|
53
|
-
): RVLayoutManager {
|
|
54
|
-
const layoutParams = createLayoutParams(params);
|
|
55
|
-
|
|
56
|
-
switch (type) {
|
|
57
|
-
case LayoutManagerType.LINEAR:
|
|
58
|
-
return new RVLinearLayoutManagerImpl(layoutParams, previousLayoutManager);
|
|
59
|
-
case LayoutManagerType.GRID:
|
|
60
|
-
return new RVGridLayoutManagerImpl(layoutParams, previousLayoutManager);
|
|
61
|
-
case LayoutManagerType.MASONRY:
|
|
62
|
-
return new RVMasonryLayoutManagerImpl(
|
|
63
|
-
layoutParams,
|
|
64
|
-
previousLayoutManager
|
|
65
|
-
);
|
|
66
|
-
default:
|
|
67
|
-
throw new Error(`Unknown layout manager type: ${type}`);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Generate mock layout info for testing
|
|
73
|
-
*/
|
|
74
|
-
export function createMockLayoutInfo(
|
|
75
|
-
index: number,
|
|
76
|
-
width: number,
|
|
77
|
-
height: number
|
|
78
|
-
): RVLayoutInfo {
|
|
79
|
-
return {
|
|
80
|
-
index,
|
|
81
|
-
dimensions: {
|
|
82
|
-
width,
|
|
83
|
-
height,
|
|
84
|
-
},
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Populate layout data in a layout manager
|
|
90
|
-
*/
|
|
91
|
-
export function populateLayouts(
|
|
92
|
-
layoutManager: RVLayoutManager,
|
|
93
|
-
itemCount: number,
|
|
94
|
-
itemWidth = 100,
|
|
95
|
-
itemHeight = 100,
|
|
96
|
-
variableSize = false
|
|
97
|
-
): void {
|
|
98
|
-
const layoutInfos: RVLayoutInfo[] = [];
|
|
99
|
-
|
|
100
|
-
for (let i = 0; i < itemCount; i++) {
|
|
101
|
-
// If variableSize is true, add some randomness to the item dimensions
|
|
102
|
-
const width = variableSize ? itemWidth + (i % 3) * 20 : itemWidth;
|
|
103
|
-
const height = variableSize ? itemHeight + (i % 5) * 25 : itemHeight;
|
|
104
|
-
|
|
105
|
-
layoutInfos.push(createMockLayoutInfo(i, width, height));
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
layoutManager.modifyLayout(layoutInfos, itemCount);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Create and populate a layout manager in one step
|
|
113
|
-
*/
|
|
114
|
-
export function createPopulatedLayoutManager(
|
|
115
|
-
type: LayoutManagerType,
|
|
116
|
-
itemCount: number,
|
|
117
|
-
params: Partial<LayoutParams> = {},
|
|
118
|
-
itemWidth = 100,
|
|
119
|
-
itemHeight = 100,
|
|
120
|
-
variableSize = false
|
|
121
|
-
): RVLayoutManager {
|
|
122
|
-
const layoutManager = createLayoutManager(type, params);
|
|
123
|
-
populateLayouts(
|
|
124
|
-
layoutManager,
|
|
125
|
-
itemCount,
|
|
126
|
-
itemWidth,
|
|
127
|
-
itemHeight,
|
|
128
|
-
variableSize
|
|
129
|
-
);
|
|
130
|
-
return layoutManager;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Get all layouts from a layout manager
|
|
135
|
-
*/
|
|
136
|
-
export function getAllLayouts(layoutManager: RVLayoutManager): RVLayout[] {
|
|
137
|
-
// Access the internal layouts array
|
|
138
|
-
return Array.from({ length: layoutManager.getLayoutCount() }, (_, index) =>
|
|
139
|
-
layoutManager.getLayout(index)
|
|
140
|
-
);
|
|
141
|
-
}
|
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { render } from "@quilted/react-testing";
|
|
3
|
-
|
|
4
|
-
import { useUnmountAwareTimeout } from "../recyclerview/hooks/useUnmountAwareCallbacks";
|
|
5
|
-
|
|
6
|
-
const TestComponent = ({
|
|
7
|
-
onRender,
|
|
8
|
-
}: {
|
|
9
|
-
onRender: (api: ReturnType<typeof useUnmountAwareTimeout>) => void;
|
|
10
|
-
}) => {
|
|
11
|
-
const api = useUnmountAwareTimeout();
|
|
12
|
-
onRender(api);
|
|
13
|
-
return null;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
describe("useUnmountAwareCallbacks", () => {
|
|
17
|
-
beforeEach(() => {
|
|
18
|
-
jest.useFakeTimers();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
afterEach(() => {
|
|
22
|
-
jest.clearAllTimers();
|
|
23
|
-
jest.clearAllMocks();
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("returns a setTimeout function", () => {
|
|
27
|
-
let api: ReturnType<typeof useUnmountAwareTimeout> | undefined;
|
|
28
|
-
render(
|
|
29
|
-
<TestComponent
|
|
30
|
-
onRender={(hookApi) => {
|
|
31
|
-
api = hookApi;
|
|
32
|
-
}}
|
|
33
|
-
/>
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
expect(api).toBeDefined();
|
|
37
|
-
expect(api?.setTimeout).toBeDefined();
|
|
38
|
-
expect(typeof api?.setTimeout).toBe("function");
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it("executes the callback after the specified delay", () => {
|
|
42
|
-
const callback = jest.fn();
|
|
43
|
-
let api: ReturnType<typeof useUnmountAwareTimeout> | undefined;
|
|
44
|
-
|
|
45
|
-
render(
|
|
46
|
-
<TestComponent
|
|
47
|
-
onRender={(hookApi) => {
|
|
48
|
-
api = hookApi;
|
|
49
|
-
}}
|
|
50
|
-
/>
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
api?.setTimeout(callback, 1000);
|
|
54
|
-
|
|
55
|
-
expect(callback).not.toHaveBeenCalled();
|
|
56
|
-
|
|
57
|
-
// Fast-forward time
|
|
58
|
-
jest.advanceTimersByTime(1000);
|
|
59
|
-
|
|
60
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it("executes multiple callbacks after their respective delays", () => {
|
|
64
|
-
const callback1 = jest.fn();
|
|
65
|
-
const callback2 = jest.fn();
|
|
66
|
-
let api: ReturnType<typeof useUnmountAwareTimeout> | undefined;
|
|
67
|
-
|
|
68
|
-
render(
|
|
69
|
-
<TestComponent
|
|
70
|
-
onRender={(hookApi) => {
|
|
71
|
-
api = hookApi;
|
|
72
|
-
}}
|
|
73
|
-
/>
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
api?.setTimeout(callback1, 1000);
|
|
77
|
-
api?.setTimeout(callback2, 2000);
|
|
78
|
-
|
|
79
|
-
expect(callback1).not.toHaveBeenCalled();
|
|
80
|
-
expect(callback2).not.toHaveBeenCalled();
|
|
81
|
-
|
|
82
|
-
// Fast-forward time by 1000ms
|
|
83
|
-
jest.advanceTimersByTime(1000);
|
|
84
|
-
|
|
85
|
-
expect(callback1).toHaveBeenCalledTimes(1);
|
|
86
|
-
expect(callback2).not.toHaveBeenCalled();
|
|
87
|
-
|
|
88
|
-
// Fast-forward time by another 1000ms
|
|
89
|
-
jest.advanceTimersByTime(1000);
|
|
90
|
-
|
|
91
|
-
expect(callback1).toHaveBeenCalledTimes(1);
|
|
92
|
-
expect(callback2).toHaveBeenCalledTimes(1);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it("clears all timeouts when the component unmounts", () => {
|
|
96
|
-
const callback = jest.fn();
|
|
97
|
-
let api: ReturnType<typeof useUnmountAwareTimeout> | undefined;
|
|
98
|
-
|
|
99
|
-
const component = render(
|
|
100
|
-
<TestComponent
|
|
101
|
-
onRender={(hookApi) => {
|
|
102
|
-
api = hookApi;
|
|
103
|
-
}}
|
|
104
|
-
/>
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
api?.setTimeout(callback, 1000);
|
|
108
|
-
api?.setTimeout(callback, 2000);
|
|
109
|
-
|
|
110
|
-
// Spy on clearTimeout to verify it's called during unmount
|
|
111
|
-
const clearTimeoutSpy = jest.spyOn(global, "clearTimeout");
|
|
112
|
-
|
|
113
|
-
// Unmount the component
|
|
114
|
-
component.unmount();
|
|
115
|
-
|
|
116
|
-
// Fast-forward time
|
|
117
|
-
jest.advanceTimersByTime(2000);
|
|
118
|
-
|
|
119
|
-
// Expect callbacks not to be called because timeouts were cleared
|
|
120
|
-
expect(callback).not.toHaveBeenCalled();
|
|
121
|
-
expect(clearTimeoutSpy).toHaveBeenCalled();
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it("removes timeout from tracking set once it executes", () => {
|
|
125
|
-
const callback = jest.fn();
|
|
126
|
-
let api: ReturnType<typeof useUnmountAwareTimeout> | undefined;
|
|
127
|
-
|
|
128
|
-
const component = render(
|
|
129
|
-
<TestComponent
|
|
130
|
-
onRender={(hookApi) => {
|
|
131
|
-
api = hookApi;
|
|
132
|
-
}}
|
|
133
|
-
/>
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
api?.setTimeout(callback, 1000);
|
|
137
|
-
|
|
138
|
-
// Fast-forward time
|
|
139
|
-
jest.advanceTimersByTime(1000);
|
|
140
|
-
|
|
141
|
-
// Verify callback was called
|
|
142
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
143
|
-
|
|
144
|
-
// We can't directly check the timeoutIds Set, so we'll verify indirectly
|
|
145
|
-
// by making sure no clearTimeout calls happen on unmount (since the timeout was already cleared)
|
|
146
|
-
const clearTimeoutSpy = jest.spyOn(global, "clearTimeout");
|
|
147
|
-
clearTimeoutSpy.mockClear(); // Reset the mock calls before unmount
|
|
148
|
-
|
|
149
|
-
// Unmount the component
|
|
150
|
-
component.unmount();
|
|
151
|
-
|
|
152
|
-
// If the timeout was properly removed from the set, clearTimeout won't be called on unmount
|
|
153
|
-
expect(clearTimeoutSpy).not.toHaveBeenCalled();
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it("handles multiple timeouts correctly", () => {
|
|
157
|
-
const callback1 = jest.fn();
|
|
158
|
-
const callback2 = jest.fn();
|
|
159
|
-
const callback3 = jest.fn();
|
|
160
|
-
let api: ReturnType<typeof useUnmountAwareTimeout> | undefined;
|
|
161
|
-
|
|
162
|
-
const component = render(
|
|
163
|
-
<TestComponent
|
|
164
|
-
onRender={(hookApi) => {
|
|
165
|
-
api = hookApi;
|
|
166
|
-
}}
|
|
167
|
-
/>
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
// Set up three timeouts with different delays
|
|
171
|
-
api?.setTimeout(callback1, 1000);
|
|
172
|
-
api?.setTimeout(callback2, 2000);
|
|
173
|
-
api?.setTimeout(callback3, 3000);
|
|
174
|
-
|
|
175
|
-
// Fast-forward time by 1500ms (should trigger only the first callback)
|
|
176
|
-
jest.advanceTimersByTime(1500);
|
|
177
|
-
|
|
178
|
-
expect(callback1).toHaveBeenCalledTimes(1);
|
|
179
|
-
expect(callback2).not.toHaveBeenCalled();
|
|
180
|
-
expect(callback3).not.toHaveBeenCalled();
|
|
181
|
-
|
|
182
|
-
// Unmount the component (should clear remaining timeouts)
|
|
183
|
-
component.unmount();
|
|
184
|
-
|
|
185
|
-
// Fast-forward time to when all callbacks would have been called
|
|
186
|
-
jest.advanceTimersByTime(2000);
|
|
187
|
-
|
|
188
|
-
// Only the first callback should have been called
|
|
189
|
-
expect(callback1).toHaveBeenCalledTimes(1);
|
|
190
|
-
expect(callback2).not.toHaveBeenCalled();
|
|
191
|
-
expect(callback3).not.toHaveBeenCalled();
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it("handles callbacks that trigger new timeouts", () => {
|
|
195
|
-
const finalCallback = jest.fn();
|
|
196
|
-
let api: ReturnType<typeof useUnmountAwareTimeout> | undefined;
|
|
197
|
-
|
|
198
|
-
render(
|
|
199
|
-
<TestComponent
|
|
200
|
-
onRender={(hookApi) => {
|
|
201
|
-
api = hookApi;
|
|
202
|
-
}}
|
|
203
|
-
/>
|
|
204
|
-
);
|
|
205
|
-
|
|
206
|
-
const firstCallback = () => {
|
|
207
|
-
api?.setTimeout(finalCallback, 1000);
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
api?.setTimeout(firstCallback, 1000);
|
|
211
|
-
|
|
212
|
-
// Fast-forward time to trigger first callback
|
|
213
|
-
jest.advanceTimersByTime(1000);
|
|
214
|
-
|
|
215
|
-
expect(finalCallback).not.toHaveBeenCalled();
|
|
216
|
-
|
|
217
|
-
// Fast-forward time to trigger second callback
|
|
218
|
-
jest.advanceTimersByTime(1000);
|
|
219
|
-
|
|
220
|
-
expect(finalCallback).toHaveBeenCalledTimes(1);
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
it("handles zero delay timeouts", () => {
|
|
224
|
-
const callback = jest.fn();
|
|
225
|
-
let api: ReturnType<typeof useUnmountAwareTimeout> | undefined;
|
|
226
|
-
|
|
227
|
-
render(
|
|
228
|
-
<TestComponent
|
|
229
|
-
onRender={(hookApi) => {
|
|
230
|
-
api = hookApi;
|
|
231
|
-
}}
|
|
232
|
-
/>
|
|
233
|
-
);
|
|
234
|
-
|
|
235
|
-
api?.setTimeout(callback, 0);
|
|
236
|
-
|
|
237
|
-
expect(callback).not.toHaveBeenCalled();
|
|
238
|
-
|
|
239
|
-
// Even with zero delay, we need to advance the timer to execute
|
|
240
|
-
jest.advanceTimersByTime(0);
|
|
241
|
-
|
|
242
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
it("handles errors in callbacks without affecting other timeouts", () => {
|
|
246
|
-
const errorCallback = jest.fn(() => {
|
|
247
|
-
throw new Error("Test error");
|
|
248
|
-
});
|
|
249
|
-
const successCallback = jest.fn();
|
|
250
|
-
let api: ReturnType<typeof useUnmountAwareTimeout> | undefined;
|
|
251
|
-
|
|
252
|
-
// Suppress error log during test
|
|
253
|
-
const originalConsoleError = console.error;
|
|
254
|
-
console.error = jest.fn();
|
|
255
|
-
|
|
256
|
-
render(
|
|
257
|
-
<TestComponent
|
|
258
|
-
onRender={(hookApi) => {
|
|
259
|
-
api = hookApi;
|
|
260
|
-
}}
|
|
261
|
-
/>
|
|
262
|
-
);
|
|
263
|
-
|
|
264
|
-
api?.setTimeout(errorCallback, 1000);
|
|
265
|
-
api?.setTimeout(successCallback, 2000);
|
|
266
|
-
|
|
267
|
-
// Fast-forward time to trigger error callback
|
|
268
|
-
try {
|
|
269
|
-
jest.advanceTimersByTime(1000);
|
|
270
|
-
} catch (error) {
|
|
271
|
-
// Expected error
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
expect(errorCallback).toHaveBeenCalledTimes(1);
|
|
275
|
-
expect(successCallback).not.toHaveBeenCalled();
|
|
276
|
-
|
|
277
|
-
// Fast-forward time to trigger success callback
|
|
278
|
-
jest.advanceTimersByTime(1000);
|
|
279
|
-
|
|
280
|
-
expect(successCallback).toHaveBeenCalledTimes(1);
|
|
281
|
-
|
|
282
|
-
// Restore console.error
|
|
283
|
-
console.error = originalConsoleError;
|
|
284
|
-
});
|
|
285
|
-
});
|