64 lines
2.2 KiB
TypeScript
64 lines
2.2 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { ScrollContainer, Spacer, Theme, VStack } from '../../src/ui';
|
|
|
|
/** Row tops after a layout; an unlaid-out stack leaves every child at 0. */
|
|
const tops = (stack: VStack) => stack.children.map((c) => c.y);
|
|
|
|
describe('a scroll container told its content changed', () => {
|
|
it('lays out rows that leave the height pinned to the viewport', () => {
|
|
const scroll = new ScrollContainer();
|
|
scroll.resize(200, 300);
|
|
const rows = new VStack();
|
|
// The list tab hands over the stack before filling it, so the empty content is measured first
|
|
// and pinned to the viewport height.
|
|
scroll.setContent(rows);
|
|
rows.add(new Spacer(20));
|
|
rows.add(new Spacer(20));
|
|
rows.add(new Spacer(20));
|
|
|
|
// 60 < 300, so the content keeps the height it already had: `resize` alone would see no
|
|
// change and skip the layout, leaving all three rows stacked at the top.
|
|
scroll.relayoutContent();
|
|
expect(tops(rows)).toEqual([0, 20, 40]);
|
|
});
|
|
|
|
it('still lays out rows that make the content taller than the viewport', () => {
|
|
const scroll = new ScrollContainer();
|
|
scroll.resize(200, 50);
|
|
const rows = new VStack();
|
|
scroll.setContent(rows);
|
|
rows.add(new Spacer(20));
|
|
rows.add(new Spacer(20));
|
|
rows.add(new Spacer(20));
|
|
|
|
scroll.relayoutContent();
|
|
expect(tops(rows)).toEqual([0, 20, 40]);
|
|
expect(scroll.maxScroll).toBe(10);
|
|
});
|
|
});
|
|
|
|
describe('a scroll container and its scrollbar', () => {
|
|
const filled = (viewportH: number, rowCount: number) => {
|
|
const scroll = new ScrollContainer();
|
|
scroll.resize(200, viewportH);
|
|
const rows = new VStack();
|
|
for (let i = 0; i < rowCount; i++) rows.add(new Spacer(20));
|
|
scroll.setContent(rows);
|
|
return { scroll, rows };
|
|
};
|
|
|
|
it('gives content that fits the full width', () => {
|
|
expect(filled(300, 3).rows.w).toBe(200);
|
|
});
|
|
|
|
it('keeps the gutter free for the bar while the content scrolls', () => {
|
|
expect(filled(50, 3).rows.w).toBe(200 - Theme.scrollbarWidth);
|
|
});
|
|
|
|
it('hands the gutter back once the content fits again', () => {
|
|
const { scroll, rows } = filled(50, 3);
|
|
scroll.resize(200, 300);
|
|
expect(rows.w).toBe(200);
|
|
});
|
|
});
|