80 lines
2.5 KiB
TypeScript
80 lines
2.5 KiB
TypeScript
import { describe, expect, it } from "bun:test";
|
|
import { ScrollView } from "../src/components/scroll-view";
|
|
import { visibleWidth } from "../src/utils";
|
|
|
|
const theme = {
|
|
track: () => "T",
|
|
thumb: () => "B",
|
|
};
|
|
|
|
describe("ScrollView", () => {
|
|
it("renders a fixed-height viewport and omits auto scrollbar when content fits", () => {
|
|
const view = new ScrollView(["one", "two"], { height: 3, theme });
|
|
|
|
expect(view.render(10)).toEqual(["one", "two", ""]);
|
|
});
|
|
|
|
it("renders a right-edge scrollbar when content overflows", () => {
|
|
const view = new ScrollView(["alpha", "beta", "gamma", "delta", "omega"], { height: 3, theme });
|
|
|
|
expect(view.render(6)).toEqual(["alphaB", "beta T", "gammaT"]);
|
|
});
|
|
|
|
it("scrolls and clamps offsets", () => {
|
|
const view = new ScrollView(["one", "two", "three", "four", "five"], { height: 3, theme });
|
|
|
|
view.scroll(10);
|
|
|
|
expect(view.getScrollOffset()).toBe(2);
|
|
expect(view.render(6)).toEqual(["threeT", "four T", "five B"]);
|
|
|
|
view.scroll(-10);
|
|
|
|
expect(view.getScrollOffset()).toBe(0);
|
|
});
|
|
|
|
it("reserves a scrollbar column in always mode", () => {
|
|
const view = new ScrollView(["one"], { height: 2, scrollbar: "always", theme });
|
|
|
|
expect(view.render(5)).toEqual(["one B", " B"]);
|
|
});
|
|
|
|
it("does not reserve a scrollbar column in never mode", () => {
|
|
const view = new ScrollView(["alpha", "beta", "gamma"], { height: 2, scrollbar: "never", theme });
|
|
|
|
expect(view.render(6)).toEqual(["alpha", "beta"]);
|
|
});
|
|
|
|
it("renders scrollbar geometry for pre-windowed lines", () => {
|
|
const view = new ScrollView(["gamma", "delta"], { height: 2, totalRows: 4, theme });
|
|
view.setScrollOffset(2);
|
|
|
|
expect(view.render(6)).toEqual(["gammaT", "deltaB"]);
|
|
});
|
|
|
|
it("does not render a scrollbar when width is zero", () => {
|
|
const view = new ScrollView(["one", "two"], { height: 1, theme });
|
|
|
|
expect(view.render(0)).toEqual([""]);
|
|
});
|
|
|
|
it("clamps scroll offset when content shrinks", () => {
|
|
const view = new ScrollView(["one", "two", "three", "four"], { height: 2, theme });
|
|
view.scrollToBottom();
|
|
|
|
view.setLines(["one"]);
|
|
|
|
expect(view.getScrollOffset()).toBe(0);
|
|
expect(view.render(10)).toEqual(["one", ""]);
|
|
});
|
|
|
|
it("keeps rendered rows within requested width with ANSI input", () => {
|
|
const view = new ScrollView(["\x1b[31malphabet\x1b[0m", "plain", "tail"], { height: 2, theme });
|
|
const rendered = view.render(5);
|
|
|
|
expect(rendered).toHaveLength(2);
|
|
expect(rendered.every(line => visibleWidth(line) <= 5)).toBe(true);
|
|
expect(rendered[0]).toContain("B");
|
|
});
|
|
});
|