Skip to content

Commit c347b7f

Browse files
RtlZeroMemoryRezoR0xFF
authored andcommitted
test/docs: cover VirtualList onScroll
Add an integration test for wheel + key-driven scroll callbacks and document the onScroll range semantics.
1 parent cb9ed50 commit c347b7f

2 files changed

Lines changed: 48 additions & 16 deletions

File tree

docs/widgets/virtual-list.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ ui.virtualList({
4242

4343
- Use `itemHeight` callback for variable-height rows.
4444
- `renderItem` receives a `focused` flag for styling.
45+
- The `range` passed to `onScroll` is `[startIndex, endIndex)` and includes overscan.
4546

4647
## Related
4748

packages/core/src/app/__tests__/widgetRenderer.integration.test.ts

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,27 @@ function keyEvent(key: number, mods = 0): ZrevEvent {
1818
return { kind: "key", timeMs: 0, key, mods, action: "down" };
1919
}
2020

21-
function mouseDownEvent(x: number, y: number): ZrevEvent {
21+
function mouseEvent(
22+
x: number,
23+
y: number,
24+
mouseKind: 1 | 2 | 3 | 4 | 5,
25+
opts: Readonly<{ wheelX?: number; wheelY?: number }> = {},
26+
): ZrevEvent {
2227
return {
2328
kind: "mouse",
2429
timeMs: 0,
2530
x,
2631
y,
27-
mouseKind: 3,
32+
mouseKind,
2833
mods: 0,
2934
buttons: 0,
30-
wheelX: 0,
31-
wheelY: 0,
35+
wheelX: opts.wheelX ?? 0,
36+
wheelY: opts.wheelY ?? 0,
3237
};
3338
}
3439

35-
function mouseEvent(x: number, y: number, mouseKind: 1 | 2 | 3 | 4 | 5): ZrevEvent {
36-
return {
37-
kind: "mouse",
38-
timeMs: 0,
39-
x,
40-
y,
41-
mouseKind,
42-
mods: 0,
43-
buttons: 0,
44-
wheelX: 0,
45-
wheelY: 0,
46-
};
40+
function mouseDownEvent(x: number, y: number): ZrevEvent {
41+
return mouseEvent(x, y, 3);
4742
}
4843

4944
function createNoopBackend(): RuntimeBackend {
@@ -560,6 +555,42 @@ describe("WidgetRenderer integration battery", () => {
560555
assert.deepEqual(selected, ["b:1"]);
561556
});
562557

558+
test("virtualList onScroll fires for wheel and key-driven scroll", () => {
559+
const backend = createNoopBackend();
560+
const renderer = new WidgetRenderer<void>({
561+
backend,
562+
requestRender: () => {},
563+
});
564+
565+
const scrolled: Array<Readonly<{ scrollTop: number; range: [number, number] }>> = [];
566+
567+
const vnode = ui.virtualList({
568+
id: "v",
569+
items: new Array<number>(100).fill(0).map((_, i) => i),
570+
itemHeight: 1,
571+
renderItem: (item) => ui.text(String(item)),
572+
onScroll: (scrollTop, range) => scrolled.push(Object.freeze({ scrollTop, range })),
573+
});
574+
575+
const res = renderer.submitFrame(
576+
() => vnode,
577+
undefined,
578+
{ cols: 20, rows: 10 },
579+
defaultTheme,
580+
noRenderHooks(),
581+
);
582+
assert.ok(res.ok);
583+
584+
renderer.routeEngineEvent(mouseEvent(1, 1, 5, { wheelY: 1 }));
585+
renderer.routeEngineEvent(keyEvent(3 /* TAB */));
586+
renderer.routeEngineEvent(keyEvent(13 /* END */));
587+
588+
assert.deepEqual(scrolled, [
589+
{ scrollTop: 3, range: [0, 16] },
590+
{ scrollTop: 90, range: [87, 100] },
591+
]);
592+
});
593+
563594
test("table routing moves focused row and activates on Enter", () => {
564595
const backend = createNoopBackend();
565596
const renderer = new WidgetRenderer<void>({

0 commit comments

Comments
 (0)