commit 907cfd4aa9b93d024c88d144bbfcc10e6f3860a2
parent 4de4d9514a17e357c35384783cae2bc14121f953
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Fri, 25 Sep 2026 23:11:55 -0400
common: brand tests pin the 4.5:1 bar as a literal, the sRGB curve at its boundary pair, and all 21 accent values (brand S3)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Diffstat:
2 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/common/lib/accent.test.ts b/common/lib/accent.test.ts
@@ -65,6 +65,8 @@ const CUSTOMS = [
];
test("resolveAccent: a custom hex is fitted to 4.5:1 on every ground and with its ink", () => {
+ // A literal bar, so an edit to MIN_ACCENT_CONTRAST cannot move fit and test together.
+ assert.equal(MIN_ACCENT_CONTRAST, 4.5);
for (const hex of CUSTOMS) {
const r = resolveAccent(hex);
assert.equal(r.id, "custom");
@@ -73,8 +75,8 @@ test("resolveAccent: a custom hex is fitted to 4.5:1 on every ground and with it
assert.match(v, /^#[0-9a-f]{6}$/);
const ground = contrastRatio(v, BASE_GROUNDS[base]);
const ink = contrastRatio(v, ACCENT_INK[base]);
- assert.ok(ground >= MIN_ACCENT_CONTRAST, `${hex} on ${base} → ${v}: ${ground.toFixed(2)} vs ground`);
- assert.ok(ink >= MIN_ACCENT_CONTRAST, `${hex} on ${base} → ${v}: ${ink.toFixed(2)} vs ink`);
+ assert.ok(ground >= 4.5, `${hex} on ${base} → ${v}: ${ground.toFixed(2)} vs ground`);
+ assert.ok(ink >= 4.5, `${hex} on ${base} → ${v}: ${ink.toFixed(2)} vs ink`);
}
}
});
diff --git a/common/lib/brand.test.ts b/common/lib/brand.test.ts
@@ -34,15 +34,17 @@ test("accents: the table is the plan's, keyed and ordered by ACCENT_IDS", () =>
}
}
assert.equal(DEFAULT_ACCENT, "signal");
- // Spot-check the table against plans/brand-and-themes.md "Accents".
- assert.deepEqual(ACCENTS.signal, {
- id: "signal",
- name: "Signal",
- onDark: "#5fa8a0",
- onLight: "#2e7b73",
- onSepia: "#2b756e",
+ // The whole table, literally, against plans/brand-and-themes.md "Accents":
+ // a typo that still clears 4.5:1 would pass the contrast test below.
+ assert.deepEqual(ACCENTS, {
+ signal: { id: "signal", name: "Signal", onDark: "#5fa8a0", onLight: "#2e7b73", onSepia: "#2b756e" },
+ brass: { id: "brass", name: "Brass", onDark: "#e3b15c", onLight: "#95661a", onSepia: "#8e6119" },
+ vermilion: { id: "vermilion", name: "Vermilion", onDark: "#ec7a52", onLight: "#b3431f", onSepia: "#b3431f" },
+ violet: { id: "violet", name: "Violet", onDark: "#b49cf2", onLight: "#6a4bc4", onSepia: "#6a4bc4" },
+ sakura: { id: "sakura", name: "Sakura", onDark: "#ee8fb5", onLight: "#a83a6a", onSepia: "#a83a6a" },
+ blue: { id: "blue", name: "Blue", onDark: "#74a9f2", onLight: "#2d5fb8", onSepia: "#2d5fb8" },
+ green: { id: "green", name: "Green", onDark: "#7cc46a", onLight: "#3f7a2c", onSepia: "#3d772b" },
});
- assert.equal(ACCENTS.green.onSepia, "#3d772b");
assert.equal(isAccentId("brass"), true);
assert.equal(isAccentId("Brass"), false);
assert.equal(isAccentId("#e3b15c"), false);
@@ -52,14 +54,18 @@ test("accents: the table is the plan's, keyed and ordered by ACCENT_IDS", () =>
// that base's ground AND against the ink set on it (white on light/sepia, the
// dark ground on dark). 7 accents × 3 bases × 2 = 42 checks.
test("accents: every value reaches 4.5:1 on its ground and with its ink", () => {
+ // The bar itself is pinned as a literal: comparing only against the
+ // imported constant would let an edit to brand.ts lower rule and test
+ // together.
+ assert.equal(MIN_ACCENT_CONTRAST, 4.5);
let checks = 0;
for (const id of ACCENT_IDS) {
for (const base of Object.keys(BASE_GROUNDS) as BaseGround[]) {
const hex = ACCENTS[id][ON[base]];
const ground = contrastRatio(hex, BASE_GROUNDS[base]);
const ink = contrastRatio(hex, ACCENT_INK[base]);
- assert.ok(ground >= MIN_ACCENT_CONTRAST, `${id} on ${base}: ${ground.toFixed(2)} vs ground`);
- assert.ok(ink >= MIN_ACCENT_CONTRAST, `${id} on ${base}: ${ink.toFixed(2)} vs ink`);
+ assert.ok(ground >= 4.5, `${id} on ${base}: ${ground.toFixed(2)} vs ground`);
+ assert.ok(ink >= 4.5, `${id} on ${base}: ${ink.toFixed(2)} vs ink`);
checks += 2;
}
}
@@ -75,6 +81,16 @@ test("contrastRatio: the WCAG endpoints", () => {
assert.equal(contrastRatio("#ffffff", "#000000"), contrastRatio("#000000", "#ffffff"));
});
+// The endpoints hold for any monotone curve, a naive gamma 2.2 included. The
+// sRGB boundary pair pins the real one: #767676 is the lightest grey that
+// passes 4.5:1 on white, and #777777 the first that does not.
+test("contrastRatio: the sRGB curve, at the 4.5:1 boundary on white", () => {
+ assert.equal(contrastRatio("#767676", "#ffffff").toFixed(2), "4.54");
+ assert.equal(contrastRatio("#777777", "#ffffff").toFixed(2), "4.48");
+ assert.ok(contrastRatio("#767676", "#ffffff") >= 4.5);
+ assert.ok(contrastRatio("#777777", "#ffffff") < 4.5);
+});
+
test("bases and icon palettes are the plan's", () => {
assert.deepEqual(BASE_GROUNDS, { light: "#f3f6f7", sepia: "#f4ecd8", dark: "#0c0a08" });
assert.deepEqual(ICON_PALETTES.archilyzer, { ground: "#151b20", dim: "#3f4c56", lit: "#e7edf1" });