@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,282 +0,0 @@
|
|
|
1
|
-
import ViewabilityHelper from "../recyclerview/viewability/ViewabilityHelper";
|
|
2
|
-
import { ErrorMessages } from "../errors/ErrorMessages";
|
|
3
|
-
import {
|
|
4
|
-
RVDimension,
|
|
5
|
-
RVLayout,
|
|
6
|
-
} from "../recyclerview/layout-managers/LayoutManager";
|
|
7
|
-
|
|
8
|
-
describe("ViewabilityHelper", () => {
|
|
9
|
-
const viewableIndicesChanged = jest.fn();
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
jest.resetAllMocks();
|
|
12
|
-
jest.useFakeTimers();
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it("does not report any changes when indices have not changed", () => {
|
|
16
|
-
const viewabilityHelper = new ViewabilityHelper(
|
|
17
|
-
null,
|
|
18
|
-
viewableIndicesChanged
|
|
19
|
-
);
|
|
20
|
-
viewabilityHelper.possiblyViewableIndices = [0, 1, 2];
|
|
21
|
-
updateViewableItems({ viewabilityHelper });
|
|
22
|
-
// Initial call
|
|
23
|
-
expect(viewableIndicesChanged).toHaveBeenCalledWith(
|
|
24
|
-
[0, 1, 2],
|
|
25
|
-
[0, 1, 2],
|
|
26
|
-
[]
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
// No changes
|
|
30
|
-
viewableIndicesChanged.mockReset();
|
|
31
|
-
updateViewableItems({ viewabilityHelper });
|
|
32
|
-
expect(viewableIndicesChanged).not.toHaveBeenCalled();
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it("reports only viewable indices", () => {
|
|
36
|
-
const viewabilityHelper = new ViewabilityHelper(
|
|
37
|
-
null,
|
|
38
|
-
viewableIndicesChanged
|
|
39
|
-
);
|
|
40
|
-
viewabilityHelper.possiblyViewableIndices = [0, 1, 2, 3];
|
|
41
|
-
updateViewableItems({ viewabilityHelper });
|
|
42
|
-
// Items 0, 1, 2 are initially viewable
|
|
43
|
-
expect(viewableIndicesChanged).toHaveBeenCalledWith(
|
|
44
|
-
[0, 1, 2],
|
|
45
|
-
[0, 1, 2],
|
|
46
|
-
[]
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
// After scroll, item 3 becomes viewable, too
|
|
50
|
-
updateViewableItems({ viewabilityHelper, scrollOffset: 50 });
|
|
51
|
-
expect(viewableIndicesChanged).toHaveBeenCalledWith([0, 1, 2, 3], [3], []);
|
|
52
|
-
|
|
53
|
-
// After additional scroll, the first item is no longer viewable
|
|
54
|
-
updateViewableItems({ viewabilityHelper, scrollOffset: 100 });
|
|
55
|
-
expect(viewableIndicesChanged).toHaveBeenCalledWith([1, 2, 3], [], [0]);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it("reports only viewable indices when horizontal", () => {
|
|
59
|
-
const viewabilityHelper = new ViewabilityHelper(
|
|
60
|
-
null,
|
|
61
|
-
viewableIndicesChanged
|
|
62
|
-
);
|
|
63
|
-
viewabilityHelper.possiblyViewableIndices = [0, 1, 2, 3];
|
|
64
|
-
const getLayout = (index: number) => {
|
|
65
|
-
return { x: index * 100, y: 0, height: 300, width: 100 } as RVLayout;
|
|
66
|
-
};
|
|
67
|
-
updateViewableItems({ viewabilityHelper, horizontal: true, getLayout });
|
|
68
|
-
expect(viewableIndicesChanged).toHaveBeenCalledWith(
|
|
69
|
-
[0, 1, 2],
|
|
70
|
-
[0, 1, 2],
|
|
71
|
-
[]
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
updateViewableItems({
|
|
75
|
-
viewabilityHelper,
|
|
76
|
-
horizontal: true,
|
|
77
|
-
scrollOffset: 50,
|
|
78
|
-
getLayout,
|
|
79
|
-
});
|
|
80
|
-
expect(viewableIndicesChanged).toHaveBeenCalledWith([0, 1, 2, 3], [3], []);
|
|
81
|
-
|
|
82
|
-
updateViewableItems({
|
|
83
|
-
viewabilityHelper,
|
|
84
|
-
horizontal: true,
|
|
85
|
-
scrollOffset: 100,
|
|
86
|
-
getLayout,
|
|
87
|
-
});
|
|
88
|
-
expect(viewableIndicesChanged).toHaveBeenCalledWith([1, 2, 3], [], [0]);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it("reports items only after minimumViewTime has elapsed", () => {
|
|
92
|
-
const viewabilityHelper = new ViewabilityHelper(
|
|
93
|
-
{ minimumViewTime: 500 },
|
|
94
|
-
viewableIndicesChanged
|
|
95
|
-
);
|
|
96
|
-
viewabilityHelper.possiblyViewableIndices = [0, 1, 2, 3];
|
|
97
|
-
updateViewableItems({ viewabilityHelper, runAllTimers: false });
|
|
98
|
-
expect(viewableIndicesChanged).not.toHaveBeenCalled();
|
|
99
|
-
jest.advanceTimersByTime(400);
|
|
100
|
-
expect(viewableIndicesChanged).not.toHaveBeenCalled();
|
|
101
|
-
jest.advanceTimersByTime(100);
|
|
102
|
-
expect(viewableIndicesChanged).toHaveBeenCalledWith(
|
|
103
|
-
[0, 1, 2],
|
|
104
|
-
[0, 1, 2],
|
|
105
|
-
[]
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
viewableIndicesChanged.mockReset();
|
|
109
|
-
updateViewableItems({
|
|
110
|
-
viewabilityHelper,
|
|
111
|
-
scrollOffset: 50,
|
|
112
|
-
runAllTimers: false,
|
|
113
|
-
});
|
|
114
|
-
expect(viewableIndicesChanged).not.toHaveBeenCalled();
|
|
115
|
-
jest.advanceTimersByTime(500);
|
|
116
|
-
expect(viewableIndicesChanged).toHaveBeenCalledWith([0, 1, 2, 3], [3], []);
|
|
117
|
-
|
|
118
|
-
viewableIndicesChanged.mockReset();
|
|
119
|
-
updateViewableItems({
|
|
120
|
-
viewabilityHelper,
|
|
121
|
-
scrollOffset: 100,
|
|
122
|
-
runAllTimers: false,
|
|
123
|
-
});
|
|
124
|
-
expect(viewableIndicesChanged).not.toHaveBeenCalled();
|
|
125
|
-
jest.advanceTimersByTime(500);
|
|
126
|
-
expect(viewableIndicesChanged).toHaveBeenCalledWith([1, 2, 3], [], [0]);
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it("reports items that only satisfy itemVisiblePercentThreshold", () => {
|
|
130
|
-
const viewabilityHelper = new ViewabilityHelper(
|
|
131
|
-
{ itemVisiblePercentThreshold: 50 },
|
|
132
|
-
viewableIndicesChanged
|
|
133
|
-
);
|
|
134
|
-
viewabilityHelper.possiblyViewableIndices = [0, 1, 2, 3];
|
|
135
|
-
updateViewableItems({
|
|
136
|
-
viewabilityHelper,
|
|
137
|
-
});
|
|
138
|
-
expect(viewableIndicesChanged).toHaveBeenCalledWith(
|
|
139
|
-
[0, 1, 2],
|
|
140
|
-
[0, 1, 2],
|
|
141
|
-
[]
|
|
142
|
-
);
|
|
143
|
-
viewableIndicesChanged.mockReset();
|
|
144
|
-
|
|
145
|
-
// User scrolled by 50 pixels, making both first and last item visible from 50 %
|
|
146
|
-
updateViewableItems({
|
|
147
|
-
viewabilityHelper,
|
|
148
|
-
scrollOffset: 50,
|
|
149
|
-
});
|
|
150
|
-
expect(viewableIndicesChanged).toHaveBeenCalledWith([0, 1, 2, 3], [3], []);
|
|
151
|
-
viewableIndicesChanged.mockReset();
|
|
152
|
-
|
|
153
|
-
// User scrolled by 55 pixels, first item no longer satisfies threshold
|
|
154
|
-
updateViewableItems({
|
|
155
|
-
viewabilityHelper,
|
|
156
|
-
scrollOffset: 55,
|
|
157
|
-
});
|
|
158
|
-
expect(viewableIndicesChanged).toHaveBeenCalledWith([1, 2, 3], [], [0]);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it("reports items that only satisfy viewAreaCoveragePercentThreshold", () => {
|
|
162
|
-
const getLayout = (index: number) => {
|
|
163
|
-
if (index === 4) {
|
|
164
|
-
return { x: 0, y: index * 100, width: 100, height: 25 } as RVLayout;
|
|
165
|
-
}
|
|
166
|
-
return { x: 0, y: index * 100, height: 100, width: 300 } as RVLayout;
|
|
167
|
-
};
|
|
168
|
-
const viewabilityHelper = new ViewabilityHelper(
|
|
169
|
-
{ viewAreaCoveragePercentThreshold: 25 },
|
|
170
|
-
viewableIndicesChanged
|
|
171
|
-
);
|
|
172
|
-
viewabilityHelper.possiblyViewableIndices = [0, 1, 2, 3];
|
|
173
|
-
updateViewableItems({
|
|
174
|
-
viewabilityHelper,
|
|
175
|
-
getLayout,
|
|
176
|
-
});
|
|
177
|
-
expect(viewableIndicesChanged).toHaveBeenCalledWith(
|
|
178
|
-
[0, 1, 2],
|
|
179
|
-
[0, 1, 2],
|
|
180
|
-
[]
|
|
181
|
-
);
|
|
182
|
-
viewableIndicesChanged.mockReset();
|
|
183
|
-
|
|
184
|
-
// User scrolled by 75 pixels.
|
|
185
|
-
// First item is visible only from 25 pixels, not meeting the threshold.
|
|
186
|
-
// The last item is visible from 75 pixels, which is exactly the threshold (300 / 4 = 75 where 300 is height of the list)
|
|
187
|
-
updateViewableItems({
|
|
188
|
-
viewabilityHelper,
|
|
189
|
-
scrollOffset: 75,
|
|
190
|
-
getLayout,
|
|
191
|
-
});
|
|
192
|
-
expect(viewableIndicesChanged).toHaveBeenCalledWith([1, 2, 3], [3], [0]);
|
|
193
|
-
viewableIndicesChanged.mockReset();
|
|
194
|
-
|
|
195
|
-
// User scrolled by 110 pixels, making the last small item only partially visible, not meeting the threshold.
|
|
196
|
-
viewabilityHelper.possiblyViewableIndices = [1, 2, 3, 4];
|
|
197
|
-
updateViewableItems({
|
|
198
|
-
viewabilityHelper,
|
|
199
|
-
scrollOffset: 110,
|
|
200
|
-
getLayout,
|
|
201
|
-
});
|
|
202
|
-
expect(viewableIndicesChanged).not.toHaveBeenCalled();
|
|
203
|
-
|
|
204
|
-
// User scrolled by 125 pixels, making the last small item completely visible, even when it is not meeting the threshold.
|
|
205
|
-
viewabilityHelper.possiblyViewableIndices = [1, 2, 3, 4];
|
|
206
|
-
updateViewableItems({
|
|
207
|
-
viewabilityHelper,
|
|
208
|
-
scrollOffset: 125,
|
|
209
|
-
getLayout,
|
|
210
|
-
});
|
|
211
|
-
expect(viewableIndicesChanged).toHaveBeenCalledWith([1, 2, 3, 4], [4], []);
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
it("reports viewable items only after interaction if waitForInteraction is set to true", () => {
|
|
215
|
-
const viewabilityHelper = new ViewabilityHelper(
|
|
216
|
-
{ waitForInteraction: true },
|
|
217
|
-
viewableIndicesChanged
|
|
218
|
-
);
|
|
219
|
-
// Even when elements are visible, viewableIndicesChanged will not be called since interaction has not been recorded, yet
|
|
220
|
-
viewabilityHelper.possiblyViewableIndices = [0, 1, 2, 3];
|
|
221
|
-
updateViewableItems({
|
|
222
|
-
viewabilityHelper,
|
|
223
|
-
});
|
|
224
|
-
// View is scrolled but programatically - not resulting in an interaction
|
|
225
|
-
updateViewableItems({
|
|
226
|
-
viewabilityHelper,
|
|
227
|
-
scrollOffset: 50,
|
|
228
|
-
});
|
|
229
|
-
expect(viewableIndicesChanged).not.toHaveBeenCalled();
|
|
230
|
-
|
|
231
|
-
// Interaction is recorded, leading to trigger of viewableIndicesChanged
|
|
232
|
-
viewabilityHelper.hasInteracted = true;
|
|
233
|
-
updateViewableItems({
|
|
234
|
-
viewabilityHelper,
|
|
235
|
-
scrollOffset: 50,
|
|
236
|
-
});
|
|
237
|
-
expect(viewableIndicesChanged).toHaveBeenCalledWith(
|
|
238
|
-
[0, 1, 2, 3],
|
|
239
|
-
[0, 1, 2, 3],
|
|
240
|
-
[]
|
|
241
|
-
);
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
it("throws multipleViewabilityThresholdTypesNotSupported exception when both viewAreaCoveragePercentThreshold and itemVisiblePercentThreshold are defined", () => {
|
|
245
|
-
const viewabilityHelper = new ViewabilityHelper(
|
|
246
|
-
{ viewAreaCoveragePercentThreshold: 1, itemVisiblePercentThreshold: 1 },
|
|
247
|
-
viewableIndicesChanged
|
|
248
|
-
);
|
|
249
|
-
expect(() => updateViewableItems({ viewabilityHelper })).toThrow(
|
|
250
|
-
ErrorMessages.multipleViewabilityThresholdTypesNotSupported
|
|
251
|
-
);
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
const updateViewableItems = ({
|
|
255
|
-
viewabilityHelper,
|
|
256
|
-
horizontal,
|
|
257
|
-
scrollOffset,
|
|
258
|
-
listSize,
|
|
259
|
-
getLayout,
|
|
260
|
-
runAllTimers,
|
|
261
|
-
}: {
|
|
262
|
-
viewabilityHelper: ViewabilityHelper;
|
|
263
|
-
horizontal?: boolean;
|
|
264
|
-
scrollOffset?: number;
|
|
265
|
-
listSize?: RVDimension;
|
|
266
|
-
getLayout?: (index: number) => RVLayout | undefined;
|
|
267
|
-
runAllTimers?: boolean;
|
|
268
|
-
}) => {
|
|
269
|
-
viewabilityHelper.updateViewableItems(
|
|
270
|
-
horizontal ?? false,
|
|
271
|
-
scrollOffset ?? 0,
|
|
272
|
-
listSize ?? { height: 300, width: 300 },
|
|
273
|
-
getLayout ??
|
|
274
|
-
((index) => {
|
|
275
|
-
return { x: 0, y: index * 100, height: 100, width: 300 } as RVLayout;
|
|
276
|
-
})
|
|
277
|
-
);
|
|
278
|
-
if (runAllTimers ?? true) {
|
|
279
|
-
jest.runAllTimers();
|
|
280
|
-
}
|
|
281
|
-
};
|
|
282
|
-
});
|
|
@@ -1,369 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
findFirstVisibleIndex,
|
|
3
|
-
findLastVisibleIndex,
|
|
4
|
-
} from "../recyclerview/utils/findVisibleIndex";
|
|
5
|
-
import { RVLayout } from "../recyclerview/layout-managers/LayoutManager";
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
createPopulatedLayoutManager,
|
|
9
|
-
LayoutManagerType,
|
|
10
|
-
getAllLayouts,
|
|
11
|
-
} from "./helpers/createLayoutManager";
|
|
12
|
-
|
|
13
|
-
describe("findVisibleIndex", () => {
|
|
14
|
-
// Helper function to create mock layouts directly for precise control
|
|
15
|
-
function createMockLayouts(
|
|
16
|
-
count: number,
|
|
17
|
-
startPosition: number,
|
|
18
|
-
itemSize: number,
|
|
19
|
-
isHorizontal: boolean
|
|
20
|
-
): RVLayout[] {
|
|
21
|
-
const layouts: RVLayout[] = [];
|
|
22
|
-
for (let i = 0; i < count; i++) {
|
|
23
|
-
const x = isHorizontal ? startPosition + i * itemSize : 0;
|
|
24
|
-
const y = isHorizontal ? 0 : startPosition + i * itemSize;
|
|
25
|
-
layouts.push({
|
|
26
|
-
x,
|
|
27
|
-
y,
|
|
28
|
-
width: isHorizontal ? itemSize : 100,
|
|
29
|
-
height: isHorizontal ? 100 : itemSize,
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
return layouts;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
describe("findFirstVisibleIndex", () => {
|
|
36
|
-
// Test 1: Basic functionality - vertical layout
|
|
37
|
-
it("finds the first visible index in a vertical layout", () => {
|
|
38
|
-
const layoutManager = createPopulatedLayoutManager(
|
|
39
|
-
LayoutManagerType.LINEAR,
|
|
40
|
-
20,
|
|
41
|
-
{ horizontal: false }
|
|
42
|
-
);
|
|
43
|
-
const layouts = getAllLayouts(layoutManager);
|
|
44
|
-
|
|
45
|
-
// Viewport starts at y=150, so the second item (index 1) should be first visible
|
|
46
|
-
const firstVisibleIndex = findFirstVisibleIndex(layouts, 150, false);
|
|
47
|
-
expect(firstVisibleIndex).toBe(1);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
// Test 2: Basic functionality - horizontal layout
|
|
51
|
-
it("finds the first visible index in a horizontal layout", () => {
|
|
52
|
-
const layoutManager = createPopulatedLayoutManager(
|
|
53
|
-
LayoutManagerType.LINEAR,
|
|
54
|
-
20,
|
|
55
|
-
{ horizontal: true }
|
|
56
|
-
);
|
|
57
|
-
const layouts = getAllLayouts(layoutManager);
|
|
58
|
-
|
|
59
|
-
// Viewport starts at x=150, so the second item (index 1) should be first visible
|
|
60
|
-
const firstVisibleIndex = findFirstVisibleIndex(layouts, 150, true);
|
|
61
|
-
expect(firstVisibleIndex).toBe(1);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
// Test 3: Empty layouts array
|
|
65
|
-
it("returns -1 for empty layouts array", () => {
|
|
66
|
-
const firstVisibleIndex = findFirstVisibleIndex([], 100, false);
|
|
67
|
-
expect(firstVisibleIndex).toBe(-1);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
// Test 4: All items are visible (threshold at 0)
|
|
71
|
-
it("returns 0 when all items are visible (threshold at 0)", () => {
|
|
72
|
-
const layoutManager = createPopulatedLayoutManager(
|
|
73
|
-
LayoutManagerType.LINEAR,
|
|
74
|
-
10
|
|
75
|
-
);
|
|
76
|
-
const layouts = getAllLayouts(layoutManager);
|
|
77
|
-
|
|
78
|
-
const firstVisibleIndex = findFirstVisibleIndex(layouts, 0, false);
|
|
79
|
-
expect(firstVisibleIndex).toBe(0);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
// Test 5: No items are visible (threshold beyond all items)
|
|
83
|
-
it("returns -1 when no items are visible", () => {
|
|
84
|
-
const layouts = createMockLayouts(10, 0, 100, false);
|
|
85
|
-
|
|
86
|
-
// Threshold is beyond all items (10 items * 100 height = 1000)
|
|
87
|
-
const firstVisibleIndex = findFirstVisibleIndex(layouts, 1100, false);
|
|
88
|
-
expect(firstVisibleIndex).toBe(-1);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
// Test 6: Edge case - threshold exactly at item boundary
|
|
92
|
-
it("returns correct index when threshold is exactly at item boundary", () => {
|
|
93
|
-
const layouts = createMockLayouts(10, 0, 100, false);
|
|
94
|
-
|
|
95
|
-
// Threshold exactly at the start of the 5th item
|
|
96
|
-
const firstVisibleIndex = findFirstVisibleIndex(layouts, 400, false);
|
|
97
|
-
expect(firstVisibleIndex).toBe(4);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
// Test 7: Edge case - threshold in the middle of an item
|
|
101
|
-
it("returns correct index when threshold is in the middle of an item", () => {
|
|
102
|
-
const layouts = createMockLayouts(10, 0, 100, false);
|
|
103
|
-
|
|
104
|
-
// Threshold in the middle of the 3rd item
|
|
105
|
-
const firstVisibleIndex = findFirstVisibleIndex(layouts, 250, false);
|
|
106
|
-
expect(firstVisibleIndex).toBe(2);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
// Test 8: With grid layout - threshold crosses multiple columns
|
|
110
|
-
it("finds first visible index with grid layout", () => {
|
|
111
|
-
const layoutManager = createPopulatedLayoutManager(
|
|
112
|
-
LayoutManagerType.GRID,
|
|
113
|
-
20,
|
|
114
|
-
{ maxColumns: 2 }
|
|
115
|
-
);
|
|
116
|
-
const layouts = getAllLayouts(layoutManager);
|
|
117
|
-
|
|
118
|
-
// With 2 columns, items are positioned differently
|
|
119
|
-
const firstVisibleIndex = findFirstVisibleIndex(layouts, 150, false);
|
|
120
|
-
|
|
121
|
-
// Expected result depends on how grid layout positions items
|
|
122
|
-
// This test might need adjustment based on actual grid layout behavior
|
|
123
|
-
expect(firstVisibleIndex).not.toBe(-1);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
// Test 9: With masonry layout - variable height items
|
|
127
|
-
it("finds first visible index with masonry layout and variable item sizes", () => {
|
|
128
|
-
const layoutManager = createPopulatedLayoutManager(
|
|
129
|
-
LayoutManagerType.MASONRY,
|
|
130
|
-
20,
|
|
131
|
-
{ maxColumns: 2 },
|
|
132
|
-
100,
|
|
133
|
-
100,
|
|
134
|
-
true // Variable size
|
|
135
|
-
);
|
|
136
|
-
const layouts = getAllLayouts(layoutManager);
|
|
137
|
-
|
|
138
|
-
const firstVisibleIndex = findFirstVisibleIndex(layouts, 200, false);
|
|
139
|
-
expect(firstVisibleIndex).not.toBe(-1);
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
// Test 10: Partial visibility - item just starting to appear
|
|
143
|
-
it("finds item that is just starting to become visible", () => {
|
|
144
|
-
const layouts = createMockLayouts(10, 0, 100, false);
|
|
145
|
-
|
|
146
|
-
// Threshold just 1px before item 4 ends
|
|
147
|
-
const firstVisibleIndex = findFirstVisibleIndex(layouts, 399, false);
|
|
148
|
-
expect(firstVisibleIndex).toBe(3);
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
describe("findLastVisibleIndex", () => {
|
|
153
|
-
// Test 11: Basic functionality - vertical layout
|
|
154
|
-
it("finds the last visible index in a vertical layout", () => {
|
|
155
|
-
const layoutManager = createPopulatedLayoutManager(
|
|
156
|
-
LayoutManagerType.LINEAR,
|
|
157
|
-
20,
|
|
158
|
-
{ horizontal: false }
|
|
159
|
-
);
|
|
160
|
-
const layouts = getAllLayouts(layoutManager);
|
|
161
|
-
|
|
162
|
-
// Viewport ends at y=250, so the third item (index 2) should be last visible
|
|
163
|
-
const lastVisibleIndex = findLastVisibleIndex(layouts, 250, false);
|
|
164
|
-
expect(lastVisibleIndex).toBe(2);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
// Test 12: Basic functionality - horizontal layout
|
|
168
|
-
it("finds the last visible index in a horizontal layout", () => {
|
|
169
|
-
const layoutManager = createPopulatedLayoutManager(
|
|
170
|
-
LayoutManagerType.LINEAR,
|
|
171
|
-
20,
|
|
172
|
-
{ horizontal: true }
|
|
173
|
-
);
|
|
174
|
-
const layouts = getAllLayouts(layoutManager);
|
|
175
|
-
|
|
176
|
-
// Viewport ends at x=250, so the third item (index 2) should be last visible
|
|
177
|
-
const lastVisibleIndex = findLastVisibleIndex(layouts, 250, true);
|
|
178
|
-
expect(lastVisibleIndex).toBe(2);
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
// Test 13: Empty layouts array
|
|
182
|
-
it("returns -1 for empty layouts array", () => {
|
|
183
|
-
const lastVisibleIndex = findLastVisibleIndex([], 100, false);
|
|
184
|
-
expect(lastVisibleIndex).toBe(-1);
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
// Test 14: All items are within viewport
|
|
188
|
-
it("returns the last item index when all items are within viewport", () => {
|
|
189
|
-
const layouts = createMockLayouts(5, 0, 100, false);
|
|
190
|
-
|
|
191
|
-
// Viewport ends at y=1000, which includes all 5 items
|
|
192
|
-
const lastVisibleIndex = findLastVisibleIndex(layouts, 1000, false);
|
|
193
|
-
expect(lastVisibleIndex).toBe(4); // Last item index is 4
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
// Test 15: No items are visible (threshold before all items)
|
|
197
|
-
it("returns -1 when no items are visible", () => {
|
|
198
|
-
const layouts = createMockLayouts(10, 100, 100, false);
|
|
199
|
-
|
|
200
|
-
// Threshold is before all items start
|
|
201
|
-
const lastVisibleIndex = findLastVisibleIndex(layouts, 50, false);
|
|
202
|
-
expect(lastVisibleIndex).toBe(-1);
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
// Test 16: Edge case - threshold exactly at item boundary
|
|
206
|
-
it("returns correct index when threshold is exactly at item boundary", () => {
|
|
207
|
-
const layouts = createMockLayouts(10, 0, 100, false);
|
|
208
|
-
|
|
209
|
-
// Threshold exactly at the end of the 3rd item
|
|
210
|
-
const lastVisibleIndex = findLastVisibleIndex(layouts, 300, false);
|
|
211
|
-
expect(lastVisibleIndex).toBe(3);
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
// Test 17: Edge case - threshold in the middle of an item
|
|
215
|
-
it("returns correct index when threshold is in the middle of an item", () => {
|
|
216
|
-
const layouts = createMockLayouts(10, 0, 100, false);
|
|
217
|
-
|
|
218
|
-
// Threshold in the middle of the 3rd item
|
|
219
|
-
const lastVisibleIndex = findLastVisibleIndex(layouts, 250, false);
|
|
220
|
-
expect(lastVisibleIndex).toBe(2);
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
// Test 18: With grid layout
|
|
224
|
-
it("finds last visible index with grid layout", () => {
|
|
225
|
-
const layoutManager = createPopulatedLayoutManager(
|
|
226
|
-
LayoutManagerType.GRID,
|
|
227
|
-
20,
|
|
228
|
-
{ maxColumns: 2 }
|
|
229
|
-
);
|
|
230
|
-
const layouts = getAllLayouts(layoutManager);
|
|
231
|
-
|
|
232
|
-
const lastVisibleIndex = findLastVisibleIndex(layouts, 350, false);
|
|
233
|
-
expect(lastVisibleIndex).not.toBe(-1);
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
// Test 19: With masonry layout - variable height items
|
|
237
|
-
it("finds last visible index with masonry layout and variable item sizes", () => {
|
|
238
|
-
const layoutManager = createPopulatedLayoutManager(
|
|
239
|
-
LayoutManagerType.MASONRY,
|
|
240
|
-
20,
|
|
241
|
-
{ maxColumns: 2 },
|
|
242
|
-
100,
|
|
243
|
-
100,
|
|
244
|
-
true // Variable size
|
|
245
|
-
);
|
|
246
|
-
const layouts = getAllLayouts(layoutManager);
|
|
247
|
-
|
|
248
|
-
const lastVisibleIndex = findLastVisibleIndex(layouts, 400, false);
|
|
249
|
-
expect(lastVisibleIndex).not.toBe(-1);
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
// Test 20: Last item partially visible
|
|
253
|
-
it("includes last item when it's partially visible", () => {
|
|
254
|
-
const layouts = createMockLayouts(10, 0, 100, false);
|
|
255
|
-
|
|
256
|
-
// Threshold just 1px into the 5th item
|
|
257
|
-
const lastVisibleIndex = findLastVisibleIndex(layouts, 401, false);
|
|
258
|
-
expect(lastVisibleIndex).toBe(4);
|
|
259
|
-
});
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
describe("Edge cases and complex scenarios", () => {
|
|
263
|
-
// Test 21: Single item layout
|
|
264
|
-
it("correctly handles single item layout for first visible", () => {
|
|
265
|
-
const layouts = createMockLayouts(1, 0, 100, false);
|
|
266
|
-
|
|
267
|
-
const firstVisibleIndex = findFirstVisibleIndex(layouts, 50, false);
|
|
268
|
-
expect(firstVisibleIndex).toBe(0);
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
// Test 22: Single item layout
|
|
272
|
-
it("correctly handles single item layout for last visible", () => {
|
|
273
|
-
const layouts = createMockLayouts(1, 0, 100, false);
|
|
274
|
-
|
|
275
|
-
const lastVisibleIndex = findLastVisibleIndex(layouts, 50, false);
|
|
276
|
-
expect(lastVisibleIndex).toBe(0);
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
// Test 23: Variable size items for first visible index
|
|
280
|
-
it("correctly finds first visible with variable size items", () => {
|
|
281
|
-
const layouts: RVLayout[] = [
|
|
282
|
-
{ x: 0, y: 0, width: 100, height: 50 },
|
|
283
|
-
{ x: 0, y: 50, width: 100, height: 150 },
|
|
284
|
-
{ x: 0, y: 200, width: 100, height: 75 },
|
|
285
|
-
{ x: 0, y: 275, width: 100, height: 100 },
|
|
286
|
-
];
|
|
287
|
-
|
|
288
|
-
const firstVisibleIndex = findFirstVisibleIndex(layouts, 175, false);
|
|
289
|
-
expect(firstVisibleIndex).toBe(1); // Second item is still visible at threshold 175
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
// Test 24: Variable size items for last visible index
|
|
293
|
-
it("correctly finds last visible with variable size items", () => {
|
|
294
|
-
const layouts: RVLayout[] = [
|
|
295
|
-
{ x: 0, y: 0, width: 100, height: 50 },
|
|
296
|
-
{ x: 0, y: 50, width: 100, height: 150 },
|
|
297
|
-
{ x: 0, y: 200, width: 100, height: 75 },
|
|
298
|
-
{ x: 0, y: 275, width: 100, height: 100 },
|
|
299
|
-
];
|
|
300
|
-
|
|
301
|
-
const lastVisibleIndex = findLastVisibleIndex(layouts, 225, false);
|
|
302
|
-
expect(lastVisibleIndex).toBe(2); // Third item is visible at threshold 225
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
// Test 25: Items with zero size
|
|
306
|
-
it("correctly handles items with zero size for first visible", () => {
|
|
307
|
-
const layouts: RVLayout[] = [
|
|
308
|
-
{ x: 0, y: 0, width: 100, height: 0 },
|
|
309
|
-
{ x: 0, y: 0, width: 100, height: 100 },
|
|
310
|
-
];
|
|
311
|
-
|
|
312
|
-
const firstVisibleIndex = findFirstVisibleIndex(layouts, 0, false);
|
|
313
|
-
expect(firstVisibleIndex).toBe(0); // First item is at position but has zero height
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
// Test 26: Items with zero size
|
|
317
|
-
it("correctly handles items with zero size for last visible", () => {
|
|
318
|
-
const layouts: RVLayout[] = [
|
|
319
|
-
{ x: 0, y: 0, width: 100, height: 100 },
|
|
320
|
-
{ x: 0, y: 100, width: 100, height: 0 },
|
|
321
|
-
];
|
|
322
|
-
|
|
323
|
-
const lastVisibleIndex = findLastVisibleIndex(layouts, 100, false);
|
|
324
|
-
expect(lastVisibleIndex).toBe(1); // Second item is at threshold position but has zero height
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
// Test 27: Large number of items - performance test
|
|
328
|
-
it("efficiently finds first visible index in large dataset", () => {
|
|
329
|
-
const layouts = createMockLayouts(1000, 0, 100, false);
|
|
330
|
-
|
|
331
|
-
// Threshold in the middle of the list
|
|
332
|
-
const firstVisibleIndex = findFirstVisibleIndex(layouts, 50000, false);
|
|
333
|
-
expect(firstVisibleIndex).toBe(500);
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
// Test 28: Large number of items - performance test
|
|
337
|
-
it("efficiently finds last visible index in large dataset", () => {
|
|
338
|
-
const layouts = createMockLayouts(1000, 0, 100, false);
|
|
339
|
-
|
|
340
|
-
// Threshold in the middle of the list
|
|
341
|
-
const lastVisibleIndex = findLastVisibleIndex(layouts, 50000, false);
|
|
342
|
-
expect(lastVisibleIndex).toBe(500);
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
// Test 29: Non-sequential indices
|
|
346
|
-
it("works with non-sequential indices for first visible", () => {
|
|
347
|
-
const layouts: RVLayout[] = [
|
|
348
|
-
{ x: 0, y: 0, width: 100, height: 100 },
|
|
349
|
-
{ x: 0, y: 100, width: 100, height: 100 },
|
|
350
|
-
{ x: 0, y: 200, width: 100, height: 100 },
|
|
351
|
-
];
|
|
352
|
-
|
|
353
|
-
const firstVisibleIndex = findFirstVisibleIndex(layouts, 150, false);
|
|
354
|
-
expect(firstVisibleIndex).toBe(1); // Second layout in the array, not index 1
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
// Test 30: Non-sequential indices
|
|
358
|
-
it("works with non-sequential indices for last visible", () => {
|
|
359
|
-
const layouts: RVLayout[] = [
|
|
360
|
-
{ x: 0, y: 0, width: 100, height: 100 },
|
|
361
|
-
{ x: 0, y: 100, width: 100, height: 100 },
|
|
362
|
-
{ x: 0, y: 200, width: 100, height: 100 },
|
|
363
|
-
];
|
|
364
|
-
|
|
365
|
-
const lastVisibleIndex = findLastVisibleIndex(layouts, 150, false);
|
|
366
|
-
expect(lastVisibleIndex).toBe(1); // Second layout in the array, not index 1
|
|
367
|
-
});
|
|
368
|
-
});
|
|
369
|
-
});
|