import { readdir, readFile } from "node:fs/promises"; import path from "node:path"; import { fileURLToPath } from "node:url"; import { ekklesiaDesignTokens } from "@ekklesia/design-tokens"; import { describe, expect, it } from "vitest"; import { EKKLESIA_UI_STYLE_ATTRIBUTE, EKKLESIA_UI_STYLESHEET, installEkklesiaUiStyles, } from "../src/index.js"; const packageDirectory = path.dirname(path.dirname(fileURLToPath(import.meta.url))); async function sourceFiles(): Promise { const directory = path.join(packageDirectory, "src"); return (await readdir(directory)) .filter((entry) => entry.endsWith(".ts") || entry.endsWith(".tsx")) .map((entry) => path.join(directory, entry)); } /** Any literal that would be a theme decision rather than a layout one. */ const THEME_LITERAL_PATTERN = /#[0-9a-f]{3,8}\b|\brgba?\s*\(|\bhsla?\s*\(|\boklch\s*\(|\bsystem-ui\b|\bsans-serif\b/giu; describe("the shared elements consume design tokens, never hardcoded theme values", () => { it("expresses every theme value in the stylesheet as a token reference", () => { expect(EKKLESIA_UI_STYLESHEET.match(THEME_LITERAL_PATTERN)).toBeNull(); expect(EKKLESIA_UI_STYLESHEET).toContain("var(--ekklesia-"); }); it("references only registered tokens", () => { const referenced = [...EKKLESIA_UI_STYLESHEET.matchAll(/var\((--ekklesia-[a-z0-9-]+)\)/gu)].map( ([, variable]) => String(variable), ); const registered = new Set(ekklesiaDesignTokens.list().map((token) => token.cssVariable)); expect(referenced.length).toBeGreaterThan(0); expect([...new Set(referenced)].filter((variable) => !registered.has(variable))).toEqual([]); }); it("never defines a global Ekklesia theme variable of its own", () => { // Referencing `--ekklesia-*` is the contract; *declaring* one would invent a global theme // variable outside the registry, which is precisely what the design-token contract forbids. expect(EKKLESIA_UI_STYLESHEET).not.toMatch(/--ekklesia-[a-z0-9-]+\s*:/u); }); it("hardcodes no theme value in component source either", async () => { for (const file of await sourceFiles()) { if (path.basename(file) === "styles.ts") { continue; } expect(await readFile(file, "utf8")).not.toMatch(THEME_LITERAL_PATTERN); } }); it("never names a Node built-in or reads the environment", async () => { for (const file of await sourceFiles()) { const source = await readFile(file, "utf8"); expect(source).not.toContain('"node:'); expect(source).not.toContain("process.env"); } }); it("depends only on the design tokens and React", async () => { const manifest = JSON.parse( await readFile(path.join(packageDirectory, "package.json"), "utf8"), ) as { dependencies?: Record; devDependencies?: Record; peerDependencies?: Record; }; // React is a peer only (ADR 0053): the consumer's React is the one in every bundle these // elements are built into. The development dependency resolves the package's own imports for its // builds and tests; nothing loads it from this workspace in a production Node.js process // (`runtime-imports-are-production-dependencies` allows exactly this peer). expect(Object.keys(manifest.dependencies ?? {})).toEqual(["@ekklesia/design-tokens"]); expect(manifest.devDependencies?.react).toBeDefined(); expect(Object.keys(manifest.peerDependencies ?? {})).toEqual(["react"]); }); it("installs its stylesheet into a document root exactly once", () => { const remove = installEkklesiaUiStyles(document); installEkklesiaUiStyles(document); expect(document.querySelectorAll(`style[${EKKLESIA_UI_STYLE_ATTRIBUTE}]`).length).toBe(1); remove(); remove(); expect(document.querySelectorAll(`style[${EKKLESIA_UI_STYLE_ATTRIBUTE}]`).length).toBe(0); }); });