Files
oh-my-pi/packages/tui/test/text.test.ts
T
roboomp 93d032a144 fix(tui): re-resolve transient status colors on theme swap
Status presenters (showWarning/showError/showStatus and extension/tool
error presenters) baked theme.fg() into Text at construction, so a
warning shown while the auto-theme default guess was dark kept the
dark-mode color after async appearance detection switched the active
theme to light — dark-catppuccin Mocha yellow on the light Latte
background (1.12:1 contrast, effectively invisible).

Add Text.setStyleFn(), a foreground styler evaluated at render time, and
route the transient status presenters through it. Because the coding
agent invalidates status components on onThemeChange, a theme swap now
re-shapes them against the live theme instead of replaying the palette
active when they were constructed.

Fixes #6337
2026-07-23 19:20:53 +00:00

37 lines
1.4 KiB
TypeScript

import { describe, expect, it } from "bun:test";
import { Text } from "@oh-my-pi/pi-tui/components/text";
describe("Text component", () => {
it("reports whether setText changed the stored text", () => {
const text = new Text("a");
expect(text.setText("a")).toBe(false);
expect(text.setText("b")).toBe(true);
expect(text.getText()).toBe("b");
});
it("applies the style fn at render time, not construction time", () => {
const text = new Text("hello", 0, 0).setStyleFn(t => `<c>${t}</c>`);
expect(text.render(40).join("\n")).toContain("<c>hello</c>");
});
it("re-resolves the style fn after invalidate so a theme change re-shapes", () => {
// The styler reads a mutable `color`, standing in for the active theme.
// The coding-agent invalidates status components on `onThemeChange`, so a
// lazily-styled Text must pick up the new color on the next render —
// something a baked ANSI string can never do (issue #6337).
let color = "RED";
const text = new Text("hello", 0, 0).setStyleFn(t => `[${color}]${t}`);
expect(text.render(40).join("\n")).toContain("[RED]hello");
// Without invalidation the cached render is returned unchanged.
color = "BLUE";
expect(text.render(40).join("\n")).toContain("[RED]hello");
text.invalidate();
const out = text.render(40).join("\n");
expect(out).toContain("[BLUE]hello");
expect(out).not.toContain("[RED]hello");
});
});