Files
kandev/apps/web/components/plugins/web-app-appearance.test.ts
2026-09-05 18:44:43 +00:00

53 lines
2.0 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
isBoundedCssColor,
resolveWebAppAppearance,
WEB_APP_APPEARANCE_TOKEN_KEYS,
WEB_APP_APPEARANCE_TYPE,
WEB_APP_APPEARANCE_VERSION,
} from "./web-app-appearance";
describe("web app appearance protocol", () => {
it("resolves only the documented semantic token envelope", () => {
document.documentElement.classList.remove("dark");
document.documentElement.style.setProperty("--background", "#123456");
document.documentElement.style.setProperty("--foreground", "oklch(0.2 0 0)");
const message = resolveWebAppAppearance(document);
expect(message).toEqual({
type: WEB_APP_APPEARANCE_TYPE,
version: WEB_APP_APPEARANCE_VERSION,
mode: "light",
tokens: expect.objectContaining({
background: "#123456",
foreground: "oklch(0.2 0 0)",
}),
});
expect(Object.keys(message)).toEqual(["type", "version", "mode", "tokens"]);
expect(Object.keys(message.tokens)).toEqual([...WEB_APP_APPEARANCE_TOKEN_KEYS]);
expect(message.tokens).not.toHaveProperty("workspaceId");
expect(message.tokens).not.toHaveProperty("runtimeUrl");
});
it("uses dark fallbacks for missing or unsafe host values", () => {
document.documentElement.classList.add("dark");
document.documentElement.style.setProperty("--background", "url(https://evil.invalid)");
document.documentElement.style.setProperty("--foreground", "var(--secret)");
const message = resolveWebAppAppearance(document, "dark");
expect(message.mode).toBe("dark");
expect(message.tokens.background).toBe("oklch(0.145 0 0)");
expect(message.tokens.foreground).toBe("oklch(0.985 0 0)");
});
it("bounds serialized color values", () => {
expect(isBoundedCssColor("oklch(0.5 0.2 240)")).toBe(true);
expect(isBoundedCssColor("#abc")).toBe(true);
expect(isBoundedCssColor("url(https://example.com/x)")).toBe(false);
expect(isBoundedCssColor("red; background: url(x)")).toBe(false);
expect(isBoundedCssColor("x".repeat(129))).toBe(false);
});
});