72 lines
3.5 KiB
JavaScript
72 lines
3.5 KiB
JavaScript
const { test } = require("node:test");
|
|
const assert = require("node:assert");
|
|
const { colorContrast, shade, tint, toHex, parseHexColor } = require("../lib/bootstrapColor");
|
|
const { solidButtonRule, outlineButtonRule, emitButtonRules } = require("../lib/deepOverlay");
|
|
|
|
// Ground truth extracted from the vendored Bootstrap 5.3.3 compiled CSS:
|
|
// each variant -> { bg, color, hoverBg, activeBorder }.
|
|
const ORACLES = {
|
|
primary: { bg: "#0d6efd", color: "#ffffff", hoverBg: "#0b5ed7", activeBorder: "#0a53be" },
|
|
secondary: { bg: "#6c757d", color: "#ffffff", hoverBg: "#5c636a", activeBorder: "#51585e" },
|
|
success: { bg: "#198754", color: "#ffffff", hoverBg: "#157347", activeBorder: "#13653f" },
|
|
info: { bg: "#0dcaf0", color: "#000000", hoverBg: "#31d2f2", activeBorder: "#25cff2" },
|
|
warning: { bg: "#ffc107", color: "#000000", hoverBg: "#ffca2c", activeBorder: "#ffc720" },
|
|
danger: { bg: "#dc3545", color: "#ffffff", hoverBg: "#bb2d3b", activeBorder: "#a52834" },
|
|
light: { bg: "#f8f9fa", color: "#000000", hoverBg: "#d3d4d5", activeBorder: "#babbbc" },
|
|
dark: { bg: "#212529", color: "#ffffff", hoverBg: "#424649", activeBorder: "#373b3e" },
|
|
};
|
|
|
|
|
|
test("colorContrast matches Bootstrap's --bs-btn-color for all 8 variants", () => {
|
|
for (const [name, o] of Object.entries(ORACLES)) {
|
|
assert.equal(colorContrast(o.bg), o.color, `${name} (${o.bg})`);
|
|
}
|
|
});
|
|
|
|
|
|
test("solid .btn-<variant> rules match Bootstrap's compiled hover/active colors", () => {
|
|
for (const [name, o] of Object.entries(ORACLES)) {
|
|
const rule = solidButtonRule(name, o.bg);
|
|
assert.ok(rule.includes(`--bs-btn-hover-bg:${o.hoverBg};`), `${name} hover-bg -> ${o.hoverBg}\n${rule}`);
|
|
assert.ok(rule.includes(`--bs-btn-active-border-color:${o.activeBorder};`), `${name} active-border -> ${o.activeBorder}`);
|
|
assert.ok(rule.includes(`--bs-btn-bg:${o.bg};`), `${name} bg`);
|
|
}
|
|
});
|
|
|
|
|
|
test("primary focus-shadow-rgb matches Bootstrap (49, 132, 253)", () => {
|
|
assert.ok(solidButtonRule("primary", "#0d6efd").includes("--bs-btn-focus-shadow-rgb:49, 132, 253;"));
|
|
assert.ok(solidButtonRule("warning", "#ffc107").includes("--bs-btn-focus-shadow-rgb:217, 164, 6;"));
|
|
});
|
|
|
|
|
|
test("shade/tint match Bootstrap's Sass math", () => {
|
|
assert.equal(toHex(shade(parseHexColor("#0d6efd"), 15)), "#0b5ed7");
|
|
assert.equal(toHex(tint(parseHexColor("#ffc107"), 15)), "#ffca2c");
|
|
assert.equal(toHex(shade(parseHexColor("#f8f9fa"), 25)), "#babbbc"); // light force-shade
|
|
assert.equal(toHex(tint(parseHexColor("#212529"), 10)), "#373b3e"); // dark force-tint
|
|
});
|
|
|
|
|
|
test("outline button inverts to the variant color", () => {
|
|
const r = outlineButtonRule("primary", "#0d6efd");
|
|
assert.ok(r.includes("--bs-btn-color:#0d6efd;"));
|
|
assert.ok(r.includes("--bs-btn-hover-bg:#0d6efd;"));
|
|
assert.ok(r.includes("--bs-btn-disabled-bg:transparent;"));
|
|
});
|
|
|
|
|
|
test("a recolored primary produces a recolored button (the whole point)", () => {
|
|
const css = emitButtonRules({ primary: "#e83e8c" });
|
|
assert.match(css, /\.btn-primary\{[^}]*--bs-btn-bg:#e83e8c;/);
|
|
// #e83e8c gets BLACK text via color-contrast -> tint mode -> hover LIGHTENS:
|
|
assert.match(css, /--bs-btn-hover-bg:#eb5b9d;/); // tint(#e83e8c,15%)
|
|
assert.match(css, /--bs-btn-color:#000000;/); // contrast picks dark text
|
|
});
|
|
|
|
|
|
test("non-hex variant colors are skipped (no throw)", () => {
|
|
const css = emitButtonRules({ primary: "var(--x)", success: "#198754" });
|
|
assert.doesNotMatch(css, /\.btn-primary\{/);
|
|
assert.match(css, /\.btn-success\{/);
|
|
});
|