|
1 | 1 | /** |
2 | | - * Windowing semantics of the shell's overlay list, which delegates selection |
3 | | - * clamping and scroll-keep-visible to @opentui/core's SelectRenderable. |
4 | | - * Ported from list-viewport.test.ts when the hand-rolled viewport kit was |
5 | | - * deleted; assertions are behavioural (active stays inside the window) rather |
6 | | - * than pinning the old edge-follow scroll rule. |
| 2 | + * Selection continuity of the shell's overlay list across count and height |
| 3 | + * changes. Scroll clamping and windowing itself are delegated to |
| 4 | + * @opentui/core's SelectRenderable and are not re-tested here; what this pins |
| 5 | + * is the wrapper's own reshape/setCount logic that carries the live selection |
| 6 | + * across a rebuild so a resize does not snap the cursor back. |
7 | 7 | */ |
8 | 8 | import { describe, expect, test } from "bun:test"; |
9 | 9 | import { withTestRenderer } from "./harness"; |
@@ -31,74 +31,7 @@ async function withList( |
31 | 31 | }); |
32 | 32 | } |
33 | 33 |
|
34 | | -describe("createOverlayList", () => { |
35 | | - test("empty list shows nothing", async () => { |
36 | | - await withList({ count: 0, items: 5 }, (list) => { |
37 | | - expect(list.count).toBe(0); |
38 | | - expect(list.activeIndex).toBe(0); |
39 | | - expect(list.visibleRange()).toEqual({ start: 0, end: 0 }); |
40 | | - }); |
41 | | - }); |
42 | | - |
43 | | - test("short list fits entirely", async () => { |
44 | | - await withList({ count: 3, items: 10 }, (list) => { |
45 | | - expect(list.offset).toBe(0); |
46 | | - expect(windowOf(list)).toEqual([0, 1, 2]); |
47 | | - }); |
48 | | - }); |
49 | | - |
50 | | - test("tall list starts at top", async () => { |
51 | | - await withList({ count: 30, items: 5 }, (list) => { |
52 | | - expect(list.offset).toBe(0); |
53 | | - expect(windowOf(list)).toEqual([0, 1, 2, 3, 4]); |
54 | | - }); |
55 | | - }); |
56 | | - |
57 | | - test("initial activeIndex deep in the list scrolls the window to it", async () => { |
58 | | - await withList({ count: 30, items: 5, activeIndex: 20 }, (list) => { |
59 | | - expect(list.activeIndex).toBe(20); |
60 | | - expect(windowOf(list)).toContain(20); |
61 | | - expect(list.offset).toBeGreaterThan(0); |
62 | | - }); |
63 | | - }); |
64 | | - |
65 | | - test("clamps negative and oversized activeIndex", async () => { |
66 | | - await withList({ count: 10, items: 3, activeIndex: 99 }, (list) => { |
67 | | - expect(list.activeIndex).toBe(9); |
68 | | - }); |
69 | | - }); |
70 | | -}); |
71 | | - |
72 | | -describe("move / page / jump", () => { |
73 | | - test("moves down and keeps active visible", async () => { |
74 | | - await withList({ count: 20, items: 4 }, (list) => { |
75 | | - for (let i = 0; i < 6; i++) list.move(1); |
76 | | - expect(list.activeIndex).toBe(6); |
77 | | - activeVisible(list); |
78 | | - }); |
79 | | - }); |
80 | | - |
81 | | - test("moves up and keeps active visible", async () => { |
82 | | - await withList({ count: 20, items: 4, activeIndex: 10 }, (list) => { |
83 | | - list.move(-3); |
84 | | - expect(list.activeIndex).toBe(7); |
85 | | - activeVisible(list); |
86 | | - }); |
87 | | - }); |
88 | | - |
89 | | - test("clamps at ends", async () => { |
90 | | - await withList({ count: 5, items: 3, activeIndex: 4 }, (list) => { |
91 | | - list.move(1); |
92 | | - expect(list.activeIndex).toBe(4); |
93 | | - list.move(1); |
94 | | - expect(list.activeIndex).toBe(4); |
95 | | - list.move(-99); |
96 | | - expect(list.activeIndex).toBe(0); |
97 | | - list.move(-1); |
98 | | - expect(list.activeIndex).toBe(0); |
99 | | - }); |
100 | | - }); |
101 | | - |
| 34 | +describe("page / jump", () => { |
102 | 35 | test("page steps by the window height minus one", async () => { |
103 | 36 | await withList({ count: 30, items: 5 }, (list) => { |
104 | 37 | list.page(1); |
|
0 commit comments