List the relationships your interface actually uses. A token palette does not imply that every possible pair is meaningful.
Define the required relationships
Store each foreground, background, level, and large-text decision in the test data:
use PhpColor\Color\Contrast\ColorContrast;
use PhpColor\Color\Contrast\WcagLevel;
use PhpColor\Color\Palette\ColorPalette;
$tokens = ColorPalette::parse([
'canvas' => '#ffffff',
'surface' => '#f3f4f6',
'text' => '#111827',
'muted-text' => '#4b5563',
'primary' => '#1d4ed8',
]);
$checks = [
['text', 'canvas', WcagLevel::AA, false],
['muted-text', 'surface', WcagLevel::AA, false],
['primary', 'canvas', WcagLevel::AA, true],
];
use PhpColor\Color\Contrast\ColorContrast;
use PhpColor\Color\Contrast\WcagLevel;
use PhpColor\Color\Palette\ColorPalette;
$tokens = ColorPalette::parse([
'canvas' => '#ffffff',
'surface' => '#f3f4f6',
'text' => '#111827',
'muted-text' => '#4b5563',
'primary' => '#1d4ed8',
]);
$checks = [
['text', 'canvas', WcagLevel::AA, false],
['muted-text', 'surface', WcagLevel::AA, false],
['primary', 'canvas', WcagLevel::AA, true],
];
Fail the regression test
Collect only the pairs that fail their declared requirement:
$failures = [];
foreach ($checks as [$foreground, $background, $level, $largeText]) {
$ratio = ColorContrast::calculate(
$tokens->get($foreground),
$tokens->get($background),
);
if (!ColorContrast::meets($ratio, $level, $largeText)) {
$failures[] = compact('foreground', 'background', 'ratio');
}
}
assert([] === $failures);
$failures = [];
foreach ($checks as [$foreground, $background, $level, $largeText]) {
$ratio = ColorContrast::calculate(
$tokens->get($foreground),
$tokens->get($background),
);
if (!ColorContrast::meets($ratio, $level, $largeText)) {
$failures[] = compact('foreground', 'background', 'ratio');
}
}
assert([] === $failures);
Token checks cannot model compositing, typography, images, or component geometry. Test those conditions separately, and do not mark text as large merely to lower the requirement. Continue with measure WCAG contrast, check contrast after compositing, or find accessible foregrounds.