Skip to content

Commit 534428d

Browse files
JohnMcLearclaude
andcommitted
test(7377): assert relative-contrast invariant, not absolute AA
Pure primaries like #ff0000 cannot clear WCAG AA (4.5:1) against either #222 or #fff — the best either can do is ~4.0:1. No text-colour choice alone fixes that; bg clamping would be a separate concern. The test should therefore verify the *real* invariant: the chosen text colour must produce the higher contrast of the two options, regardless of whether that contrast clears any absolute threshold. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ce0c5c2 commit 534428d

1 file changed

Lines changed: 19 additions & 9 deletions

File tree

src/tests/backend/specs/colorutils.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,28 @@ describe(__filename, function () {
6060
assert.strictEqual(onNavy, 'var(--super-light-color)');
6161
});
6262

63-
it('every primary picks a text colour clearing WCAG AA', function () {
64-
// The dead-zone regression: for every pure-ish primary, the returned
65-
// text colour must produce ≥4.5:1 contrast.
63+
it('always picks whichever of black/white gives the higher contrast', function () {
64+
// Regression invariant: the returned text colour must never produce
65+
// LOWER contrast than the alternative. Pre-fix, the `luminosity < 0.5`
66+
// cutoff violated this on e.g. #ff0000 — luminosity 0.30 picked white
67+
// (4.00:1) when black (5.25:1) was available. Note: this invariant is
68+
// about *relative* contrast between the two options, not about hitting
69+
// WCAG AA; pure primaries like #ff0000 can't clear 4.5:1 with either
70+
// black or white, and no text-colour choice alone can fix that — bg
71+
// tweaks would be a separate concern.
6672
const samples = ['#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff', '#00ffff',
67-
'#800000', '#008000', '#000080', '#808000', '#800080', '#008080'];
73+
'#800000', '#008000', '#000080', '#808000', '#800080', '#008080',
74+
'#888888', '#bbbbbb', '#333333'];
6875
for (const bg of samples) {
6976
const textHex = colorutils.textColorFromBackgroundColor(bg, 'something-else');
70-
const textTriple = textHex === '#222'
71-
? colorutils.css2triple('#222222')
72-
: colorutils.css2triple('#ffffff');
73-
const ratio = colorutils.contrastRatio(colorutils.css2triple(bg), textTriple);
74-
assert.ok(ratio >= 4.5, `${bg}${textHex} gave only ${ratio.toFixed(2)}:1`);
77+
const bgTriple = colorutils.css2triple(bg);
78+
const ratioBlack = colorutils.contrastRatio(bgTriple, colorutils.css2triple('#222222'));
79+
const ratioWhite = colorutils.contrastRatio(bgTriple, colorutils.css2triple('#ffffff'));
80+
const picked = textHex === '#222' ? ratioBlack : ratioWhite;
81+
const other = textHex === '#222' ? ratioWhite : ratioBlack;
82+
assert.ok(picked >= other,
83+
`${bg} picked ${textHex} (${picked.toFixed(2)}:1) when the other ` +
84+
`option would have been ${other.toFixed(2)}:1`);
7585
}
7686
});
7787
});

0 commit comments

Comments
 (0)