sc-theme-builder/test/compile.test.js
2026-07-01 20:07:28 -05:00

74 lines
2.6 KiB
JavaScript

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}$/);
});