const { test } = require("node:test"); const assert = require("node:assert"); const { compileTheme, emitOverlayCss, robustnessGuard, contentHash, deriveRgb } = require("../lib/compile"); const { normalizeTokens } = require("../lib/themeSchema"); function bracesBalanced(css) { let depth = 0; for (const ch of css) { if (ch === "{") depth += 1; else if (ch === "}") { depth -= 1; if (depth < 0) return false; } } return depth === 0; } test("compileTheme emits --bs-* overlay with derived rgb companion", () => { const out = compileTheme(normalizeTokens({ colors: { primary: "#ff0000" } })); assert.match(out.css, /--bs-primary: #ff0000;/); assert.match(out.css, /--bs-primary-rgb: 255, 0, 0;/); assert.equal(out.engine, "overlay"); assert.ok(bracesBalanced(out.css)); }); test("compileTheme NEVER throws and is balanced even for a brace-injecting token", () => { // A value containing "}" would close :root{} early -> it must be DROPPED. const out = compileTheme(normalizeTokens({ colors: { primary: "#fff} body{display:none" } })); assert.ok(bracesBalanced(out.css), "braces stay balanced"); assert.doesNotMatch(out.css, /display:none/); assert.ok(out.warnings.length >= 1); }); test("targeted rule tokens emit their own block", () => { const out = emitOverlayCss(normalizeTokens({ components: { navbarBg: "#101010" } })); assert.match(out.css, /\.navbar\{--bs-navbar-bg: #101010;\}/); assert.ok(bracesBalanced(out.css)); }); test("empty/default theme compiles to valid non-white-screen CSS", () => { const out = compileTheme(normalizeTokens({})); assert.ok(bracesBalanced(out.css)); assert.match(out.css, /:root\{/); }); test("custom raw vars pass through, malformed keys are skipped", () => { const out = emitOverlayCss(normalizeTokens({ custom: { "--my-var": "10px", "bad key": "x" } })); assert.match(out.css, /--my-var: 10px;/); assert.doesNotMatch(out.css, /bad key/); }); test("deriveRgb handles #rgb, #rrggbb, and rejects non-hex", () => { assert.equal(deriveRgb("#fff"), "255, 255, 255"); assert.equal(deriveRgb("#0d6efd"), "13, 110, 253"); assert.equal(deriveRgb("rebeccapurple"), null); }); test("robustnessGuard collapses unbalanced CSS to an empty sentinel", () => { const g = robustnessGuard(":root{--x: 1;", []); assert.match(g.css, /empty \(invalid\)/); }); test("contentHash is stable and 8 hex chars", () => { const a = contentHash(":root{--bs-primary: #000;}"); const b = contentHash(":root{--bs-primary: #000;}"); assert.equal(a, b); assert.match(a, /^[0-9a-f]{8}$/); });