mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-08-19 21:53:48 +00:00
Some checks are pending
CI / build-check-test (push) Waiting to run
- add `--use-theme` for fixed and terminal-aware theme pairs - keep invocation state non-persistent until an explicit selection - preserve active themes across previews, reloads, and HTML exports
125 lines
4.6 KiB
TypeScript
125 lines
4.6 KiB
TypeScript
import type { TUI } from "@earendil-works/pi-tui";
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import { SettingsManager } from "../src/core/settings-manager.ts";
|
|
import { initTheme, type TerminalTheme, theme } from "../src/modes/interactive/theme/theme.ts";
|
|
import { InteractiveThemeController } from "../src/modes/interactive/theme/theme-controller.ts";
|
|
|
|
function createUi() {
|
|
const queryTerminalBackgroundColor = vi.fn();
|
|
const queryTerminalColorScheme = vi.fn();
|
|
const setTerminalColorSchemeNotifications = vi.fn();
|
|
let terminalColorSchemeListener: ((terminalTheme: TerminalTheme) => void) | undefined;
|
|
const ui = {
|
|
invalidate: vi.fn(),
|
|
requestRender: vi.fn(),
|
|
setTerminalColorSchemeNotifications,
|
|
onTerminalColorSchemeChange: vi.fn((listener: (terminalTheme: TerminalTheme) => void) => {
|
|
terminalColorSchemeListener = listener;
|
|
return vi.fn();
|
|
}),
|
|
queryTerminalBackgroundColor,
|
|
queryTerminalColorScheme,
|
|
} as unknown as TUI;
|
|
return {
|
|
ui,
|
|
queryTerminalBackgroundColor,
|
|
queryTerminalColorScheme,
|
|
setTerminalColorSchemeNotifications,
|
|
emitTerminalColorScheme: (terminalTheme: TerminalTheme) => terminalColorSchemeListener?.(terminalTheme),
|
|
};
|
|
}
|
|
|
|
function createController(ui: TUI, getSettingsManager: () => SettingsManager, initialThemeSetting?: string) {
|
|
return new InteractiveThemeController(ui, {
|
|
getSettingsManager,
|
|
showError: vi.fn(),
|
|
onChanged: vi.fn(),
|
|
initialThemeSetting,
|
|
});
|
|
}
|
|
|
|
afterEach(() => {
|
|
initTheme("dark");
|
|
vi.unstubAllEnvs();
|
|
});
|
|
|
|
describe("InteractiveThemeController", () => {
|
|
it("uses the initial theme without persisting it", async () => {
|
|
const { ui, queryTerminalBackgroundColor } = createUi();
|
|
const manager = SettingsManager.inMemory({ theme: "dark" });
|
|
const setTheme = vi.spyOn(manager, "setTheme");
|
|
const flush = vi.spyOn(manager, "flush");
|
|
const controller = createController(ui, () => manager, "light");
|
|
|
|
expect(theme.name).toBe("light");
|
|
expect(controller.getThemeSelection()).toBe("light");
|
|
await controller.applyFromSettings();
|
|
|
|
expect(queryTerminalBackgroundColor).not.toHaveBeenCalled();
|
|
expect(setTheme).not.toHaveBeenCalled();
|
|
expect(flush).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("resolves a theme pair and follows terminal appearance changes", async () => {
|
|
vi.stubEnv("COLORFGBG", "15;0");
|
|
const { ui, queryTerminalColorScheme, setTerminalColorSchemeNotifications, emitTerminalColorScheme } = createUi();
|
|
queryTerminalColorScheme.mockResolvedValue("light");
|
|
const manager = SettingsManager.inMemory({ theme: "dark/light" });
|
|
const controller = createController(ui, () => manager, "light/dark");
|
|
|
|
expect(theme.name).toBe("dark");
|
|
await controller.applyFromSettings();
|
|
expect(theme.name).toBe("light");
|
|
expect(setTerminalColorSchemeNotifications).toHaveBeenCalledWith(true);
|
|
|
|
emitTerminalColorScheme("dark");
|
|
expect(theme.name).toBe("dark");
|
|
});
|
|
|
|
it("detects the current terminal appearance when selecting a theme pair", async () => {
|
|
vi.stubEnv("COLORFGBG", "");
|
|
const { ui, queryTerminalColorScheme } = createUi();
|
|
queryTerminalColorScheme.mockResolvedValue("light");
|
|
const manager = SettingsManager.inMemory({ theme: "dark" });
|
|
const controller = createController(ui, () => manager);
|
|
|
|
expect(theme.name).toBe("dark");
|
|
await controller.setThemeSetting("light/dark");
|
|
expect(theme.name).toBe("light");
|
|
expect(queryTerminalColorScheme).toHaveBeenCalledOnce();
|
|
});
|
|
|
|
it("lets an explicit selection replace the initial theme", async () => {
|
|
const { ui } = createUi();
|
|
const firstManager = SettingsManager.inMemory({ theme: "dark" });
|
|
const secondManager = SettingsManager.inMemory({ theme: "light" });
|
|
let manager = firstManager;
|
|
const controller = createController(ui, () => manager, "light");
|
|
await controller.applyFromSettings();
|
|
|
|
expect(controller.setThemeName("dark")).toEqual({ success: true });
|
|
manager = secondManager;
|
|
await controller.applyFromSettings();
|
|
|
|
expect(controller.getThemeSelection()).toBe("dark");
|
|
expect(theme.name).toBe("dark");
|
|
});
|
|
|
|
it("reloads theme settings when no initial theme was supplied", async () => {
|
|
const { ui } = createUi();
|
|
const firstManager = SettingsManager.inMemory({ theme: "dark" });
|
|
const secondManager = SettingsManager.inMemory({ theme: "light" });
|
|
let manager = firstManager;
|
|
const controller = createController(ui, () => manager);
|
|
await controller.applyFromSettings();
|
|
|
|
firstManager.applyOverrides({ theme: "light" });
|
|
await controller.applyFromSettings();
|
|
expect(theme.name).toBe("light");
|
|
|
|
secondManager.applyOverrides({ theme: "dark" });
|
|
manager = secondManager;
|
|
await controller.applyFromSettings();
|
|
expect(theme.name).toBe("dark");
|
|
});
|
|
});
|