diff --git a/canvas/src/lib/__tests__/theme.test.ts b/canvas/src/lib/__tests__/theme.test.ts new file mode 100644 index 000000000..02983f78c --- /dev/null +++ b/canvas/src/lib/__tests__/theme.test.ts @@ -0,0 +1,145 @@ +// @vitest-environment jsdom +/** + * Tests for cssVar — maps a ColorToken to a CSS custom-property string. + */ +import { describe, it, expect } from "vitest"; +import { cssVar, type ColorToken } from "../theme"; + +const ALL_TOKENS: ColorToken[] = [ + // Warm-paper surface (light-flippable) + "surface", + "surface-elevated", + "surface-sunken", + "surface-card", + "line", + "line-soft", + "ink", + "ink-mid", + "ink-soft", + "accent", + "accent-strong", + "warm", + "good", + "bad", + // Always-dark (terminal / console / log surfaces) + "bg", + "bg-elev", + "bg-card", + "line-strong", + "ink-mute", + "ink-dim", + "accent-dim", + "plasma", + "warn", +]; + +describe("cssVar", () => { + it("returns var(--color-surface) for 'surface'", () => { + expect(cssVar("surface")).toBe("var(--color-surface)"); + }); + + it("returns var(--color-surface-elevated) for 'surface-elevated'", () => { + expect(cssVar("surface-elevated")).toBe("var(--color-surface-elevated)"); + }); + + it("returns var(--color-surface-sunken) for 'surface-sunken'", () => { + expect(cssVar("surface-sunken")).toBe("var(--color-surface-sunken)"); + }); + + it("returns var(--color-surface-card) for 'surface-card'", () => { + expect(cssVar("surface-card")).toBe("var(--color-surface-card)"); + }); + + it("returns var(--color-line) for 'line'", () => { + expect(cssVar("line")).toBe("var(--color-line)"); + }); + + it("returns var(--color-line-soft) for 'line-soft'", () => { + expect(cssVar("line-soft")).toBe("var(--color-line-soft)"); + }); + + it("returns var(--color-ink) for 'ink'", () => { + expect(cssVar("ink")).toBe("var(--color-ink)"); + }); + + it("returns var(--color-ink-mid) for 'ink-mid'", () => { + expect(cssVar("ink-mid")).toBe("var(--color-ink-mid)"); + }); + + it("returns var(--color-ink-soft) for 'ink-soft'", () => { + expect(cssVar("ink-soft")).toBe("var(--color-ink-soft)"); + }); + + it("returns var(--color-accent) for 'accent'", () => { + expect(cssVar("accent")).toBe("var(--color-accent)"); + }); + + it("returns var(--color-accent-strong) for 'accent-strong'", () => { + expect(cssVar("accent-strong")).toBe("var(--color-accent-strong)"); + }); + + it("returns var(--color-warm) for 'warm'", () => { + expect(cssVar("warm")).toBe("var(--color-warm)"); + }); + + it("returns var(--color-good) for 'good'", () => { + expect(cssVar("good")).toBe("var(--color-good)"); + }); + + it("returns var(--color-bad) for 'bad'", () => { + expect(cssVar("bad")).toBe("var(--color-bad)"); + }); + + it("returns var(--color-bg) for 'bg'", () => { + expect(cssVar("bg")).toBe("var(--color-bg)"); + }); + + it("returns var(--color-bg-elev) for 'bg-elev'", () => { + expect(cssVar("bg-elev")).toBe("var(--color-bg-elev)"); + }); + + it("returns var(--color-bg-card) for 'bg-card'", () => { + expect(cssVar("bg-card")).toBe("var(--color-bg-card)"); + }); + + it("returns var(--color-line-strong) for 'line-strong'", () => { + expect(cssVar("line-strong")).toBe("var(--color-line-strong)"); + }); + + it("returns var(--color-ink-mute) for 'ink-mute'", () => { + expect(cssVar("ink-mute")).toBe("var(--color-ink-mute)"); + }); + + it("returns var(--color-ink-dim) for 'ink-dim'", () => { + expect(cssVar("ink-dim")).toBe("var(--color-ink-dim)"); + }); + + it("returns var(--color-accent-dim) for 'accent-dim'", () => { + expect(cssVar("accent-dim")).toBe("var(--color-accent-dim)"); + }); + + it("returns var(--color-plasma) for 'plasma'", () => { + expect(cssVar("plasma")).toBe("var(--color-plasma)"); + }); + + it("returns var(--color-warn) for 'warn'", () => { + expect(cssVar("warn")).toBe("var(--color-warn)"); + }); + + it("returns a var() string for every ColorToken", () => { + for (const token of ALL_TOKENS) { + const result = cssVar(token); + expect(result).toBe(`var(--color-${token})`); + expect(result.startsWith("var(--color-")).toBe(true); + expect(result.endsWith(")")).toBe(true); + } + }); + + it("is a pure function — same token always returns same output", () => { + for (const token of ALL_TOKENS) { + for (let i = 0; i < 3; i++) { + expect(cssVar(token)).toBe(cssVar(token)); + } + } + }); +});