import { describe, expect, it } from "vitest"; import { hueMatrix, resolveTone, TONES, toneFilters, toneWash } from "./tone.js"; describe("toneFilters", () => { it("writes each layer's filter as literal values", () => { const filters = toneFilters(TONES.regular.dark); expect(filters.body.full).toBe("blur(1.5px) saturate(0.8) contrast(0.53) brightness(0.43)"); expect(filters.shade.full).toBe("brightness(1.33)"); expect(filters.glow.full).toBe("saturate(1.1) brightness(1.3)"); expect(filters.edge.full).toBe("brightness(0.66)"); expect(filters.highlight.full).toBe("contrast(1.1) brightness(2.4)"); }); it("diffuses floating glass more", () => { expect(toneFilters(TONES.regular.dark, true).body.full).toBe("blur(6px) saturate(0.8) contrast(0.53) brightness(0.43)"); expect(toneFilters(TONES.regular.light, true).body.full).toBe("blur(7px) saturate(0.8) contrast(0.3) brightness(1.73)"); }); it("drops identity functions and clears the same list", () => { const filters = toneFilters(TONES.clear.dark); expect(filters.body).toEqual({ full: "blur(1.5px)", clear: "blur(0px)" }); expect(toneFilters(TONES.clear.light).glow).toEqual({ full: "brightness(1.02)", clear: "brightness(1)" }); }); it("leaves a layer unfiltered when every value is identity", () => { const tone = { ...TONES.clear.dark, blur: 0 }; expect(toneFilters(tone).body).toEqual({ full: "none", clear: "none" }); }); }); describe("resolveTone", () => { it("overrides only the given appearance", () => { const overrides = { dark: { tint: 0.5 } }; expect(resolveTone("regular", "dark", overrides).tint).toBe(0.5); expect(resolveTone("regular", "light", overrides).tint).toBe(TONES.regular.light.tint); }); }); describe("toneWash", () => { it("mixes the tint by the tone's share", () => { expect(toneWash(TONES.regular.light, "var(--surface)")).toBe("color-mix(in srgb, var(--surface) 40%, transparent)"); expect(toneWash(TONES.regular.dark, "black")).toBe("color-mix(in srgb, black 50%, transparent)"); expect(toneWash(TONES.clear.dark, "black")).toBe("transparent"); }); }); describe("hueMatrix", () => { it("leaves neutral colours untinted", () => { expect(hueMatrix([128, 128, 128], 1)).toBeNull(); expect(hueMatrix([255, 255, 255], 1)).toBeNull(); }); it("keeps alpha and shifts channels toward the hue", () => { const rows = hueMatrix([20, 30, 60], 1)?.split(" ").map(Number) ?? []; expect(rows).toHaveLength(20); expect(rows.slice(15)).toEqual([0, 0, 0, 1, 0]); // Blue gains, red loses: the blue row's own weight rises above red's. expect(rows[12]).toBeGreaterThan(rows[0] ?? 0); }); it("scales with strength", () => { const full = hueMatrix([20, 30, 60], 1)?.split(" ").map(Number) ?? []; const half = hueMatrix([20, 30, 60], 0.5)?.split(" ").map(Number) ?? []; expect(Math.abs((half[12] ?? 0) - 1)).toBeCloseTo(Math.abs((full[12] ?? 0) - 1) / 2, 3); }); });