import { describe, expect, it } from "vitest"; import { compileGlobalGovernanceFacts, FactIndex, makeTailwindClassFact, makeTailwindTokenResolvedFact, makeUsageNodeFact, ruleTailwindRawColorViaToken, runRules, } from "../index.js"; const FILE = "src/app.tsx"; const LOC = { file: FILE, line: 1, column: 7 }; function indexWithAllowPolicy(): FactIndex { const ix = new FactIndex(); ix.addMany( compileGlobalGovernanceFacts({ tailwind: { palette: { allow: ["brand-*"], }, }, }) ); return ix; } function addResolvedColor( ix: FactIndex, raw = "bg-red-500", token = "red-500", source: "default" | "theme-css" = "default" ): void { const node = makeUsageNodeFact({ file: FILE, nodePath: "0", element: "div", location: LOC, }); ix.add(node); ix.add( makeTailwindClassFact({ file: FILE, nodeId: node.id, raw, originPath: `attribute#0/class#${raw}`, prefix: null, modifiers: [], important: false, negative: false, utility: "bg", value: { kind: "token", token }, location: LOC, }) ); ix.add( makeTailwindTokenResolvedFact({ utility: "bg", token, resolved: { kind: "color", value: "#ef4444", source }, }) ); } describe("tailwind/raw-color-via-token", () => { it("flags default color tokens outside the allowed palette — ACCEPTANCE §5.30", () => { const ix = indexWithAllowPolicy(); addResolvedColor(ix); const findings = ruleTailwindRawColorViaToken(ix); expect(findings).toHaveLength(1); expect(findings[0]).toMatchObject({ ruleId: "tailwind/raw-color-via-token", severity: "moderate", message: "`bg-red-500` resolves to raw color `#ef4444` (Tailwind default). Project policy requires `brand-*` palette tokens.", attributes: { utility: "bg", token: "red-500", resolvedValue: "#ef4444", source: "default", }, }); }); it("allows tokens matching the palette allow list", () => { const ix = indexWithAllowPolicy(); addResolvedColor(ix, "bg-brand-500", "brand-500"); expect(ruleTailwindRawColorViaToken(ix)).toHaveLength(0); }); it("allows project-defined theme tokens outside the stock palette names", () => { const ix = indexWithAllowPolicy(); addResolvedColor(ix, "bg-danger", "danger", "theme-css"); expect(ruleTailwindRawColorViaToken(ix)).toHaveLength(0); }); it("is registered in runRules", () => { const ix = indexWithAllowPolicy(); addResolvedColor(ix); expect(runRules(ix).map((f) => f.ruleId)).toContain("tailwind/raw-color-via-token"); }); });