/** * @file terminalTheme.test.ts * @description Tests for the xterm theme builder: CSS-variable RGB triplets * become hex, status/accent map to the ANSI hues, bright twins are lighter, * and the probe resolves a named dark theme's variables. * @author Nguyễn Ngọc Trí Vĩ */ import { describe, it, expect } from "vitest"; import { buildTerminalTheme, terminalThemeFor } from "../terminalTheme"; const vars: Record = { "--surface-0": " 17 17 19", "--surface-3": "39 42 45", "--fg-primary": "237 238 240", "--fg-secondary": "176 180 186", "--fg-muted": "105 110 119", "--border-light": "67 72 78", "--accent": "0 144 255", "--status-success": "61 214 140", "--status-danger": "255 149 146", "--status-warning": "255 202 22", }; describe("buildTerminalTheme", () => { it("maps theme tokens onto the xterm palette", () => { const t = buildTerminalTheme((n) => vars[n] ?? ""); expect(t.background).toBe("#111113"); expect(t.foreground).toBe("#edeef0"); expect(t.cursor).toBe("#edeef0"); expect(t.selectionBackground).toBe("#43484e"); expect(t.red).toBe("#ff9592"); expect(t.green).toBe("#3dd68c"); expect(t.yellow).toBe("#ffca16"); expect(t.blue).toBe("#0090ff"); expect(t.black).toBe("#43484e"); expect(t.brightBlack).toBe("#696e77"); expect(t.brightWhite).toBe("#edeef0"); }); it("makes each bright twin lighter than its base colour", () => { const t = buildTerminalTheme((n) => vars[n] ?? ""); const sum = (hex: string) => [1, 3, 5].reduce((a, i) => a + parseInt(hex.slice(i, i + 2), 16), 0); for (const c of ["red", "green", "yellow", "blue", "magenta", "cyan"] as const) { const base = t[c]!; const bright = t[`bright${c[0]!.toUpperCase()}${c.slice(1)}` as keyof typeof t] as string; expect(sum(bright)).toBeGreaterThan(sum(base)); } }); it("leaves a colour unset when its variable is missing, so xterm keeps its default", () => { const t = buildTerminalTheme(() => ""); expect(t.background).toBeUndefined(); expect(t.red).toBeUndefined(); }); }); describe("terminalThemeFor", () => { it("resolves variables on a dark probe scoped to the theme id, then removes it", () => { const style = document.createElement("style"); style.textContent = `.dark { --surface-0: 1 2 3; } .dark[data-theme="darcula"] { --surface-0: 30 31 32; }`; document.head.appendChild(style); try { expect(terminalThemeFor("default").background).toBe("#010203"); expect(terminalThemeFor("darcula").background).toBe("#1e1f20"); expect(document.body.children).toHaveLength(0); } finally { style.remove(); } }); });