Files
oh-my-pi/packages/tui/test/loader.test.ts
T
can1357 9b98dafe4e test(packages/tui): updated tui test timing for 30fps render cadence
- Updated settle helpers in repro tests to wait 40ms before terminal flush.
- Raised process-terminal-render-harness SETTLE_MS to 67ms for 30fps timing.
- Updated render-throttle mocks to advance mock time by 40ms per frame.
- Added Loader component cadence test for 30fps animated repaint timing.
- Added render-regressions check that non-force renders are scheduled at ~33ms.
2026-06-07 08:42:51 +02:00

69 lines
1.9 KiB
TypeScript

import { afterEach, describe, expect, it, spyOn, vi } from "bun:test";
import { TUI } from "@oh-my-pi/pi-tui";
import { Loader, type LoaderMessageColorFn } from "@oh-my-pi/pi-tui/components/loader";
import { visibleWidth } from "@oh-my-pi/pi-tui/utils";
import { VirtualTerminal } from "./virtual-terminal";
describe("Loader component", () => {
afterEach(() => {
vi.useRealTimers();
vi.restoreAllMocks();
});
it("clamps rendered lines to terminal width", async () => {
const term = new VirtualTerminal(1, 4);
const tui = new TUI(term);
const loader = new Loader(
tui,
text => text,
text => text,
"Checking",
["⠸"],
);
tui.addChild(loader);
tui.start();
await Bun.sleep(0);
await term.flush();
for (const line of term.getViewport()) {
expect(visibleWidth(line)).toBeLessThanOrEqual(1);
}
loader.stop();
tui.stop();
});
it("keeps spinner cadence when animated messages repaint at 30fps", () => {
vi.useFakeTimers();
const ui = { requestRender: vi.fn() } as unknown as TUI;
const colorMessage = ((text: string) => text) as LoaderMessageColorFn & { animated: true };
colorMessage.animated = true;
const loader = new Loader(ui, text => text, colorMessage, "Checking", ["0", "1", "2", "3"]);
vi.advanceTimersByTime(170);
expect(loader.render(20).join("\n")).toContain("2 Checking");
loader.stop();
});
it("dispose() stops the animation so no further renders are scheduled", async () => {
const term = new VirtualTerminal(20, 4);
const tui = new TUI(term);
const loader = new Loader(
tui,
text => text,
text => text,
"Checking",
["a", "b", "c"],
);
const spy = spyOn(tui, "requestRender");
loader.dispose();
const after = spy.mock.calls.length;
await Bun.sleep(40); // longer than the spinner interval
expect(spy.mock.calls.length).toBe(after);
expect(() => loader.dispose()).not.toThrow(); // idempotent
tui.stop();
});
});