// Prüfung: Kontrastwerte erfüllen mindestens AA (SHL-01 Prüfung 3 / Akzeptanzkriterium 4). import { describe, expect, it } from "vitest"; import { colorTokens } from "../tokens/tokens"; // WCAG-2.1-AA-Kontrastberechnung (relative Luminanz, sRGB) — keine externe Abhängigkeit nötig. function relLuminance(hex: string): number { const rgb = [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16) / 255); const [r, g, b] = rgb.map((c) => (c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4)); return 0.2126 * r + 0.7152 * g + 0.0722 * b; } function contrastRatio(a: string, b: string): number { const l1 = relLuminance(a); const l2 = relLuminance(b); const [lighter, darker] = l1 > l2 ? [l1, l2] : [l2, l1]; return (lighter + 0.05) / (darker + 0.05); } describe("Design-Tokens: WCAG 2.1 AA Kontrast", () => { for (const scheme of ["light", "dark"] as const) { const c = colorTokens[scheme]; it(`${scheme}: textPrimary auf background erfüllt AA (>= 4.5:1)`, () => { expect(contrastRatio(c.textPrimary, c.background)).toBeGreaterThanOrEqual(4.5); }); it(`${scheme}: textSecondary auf surface erfüllt AA (>= 4.5:1)`, () => { expect(contrastRatio(c.textSecondary, c.surface)).toBeGreaterThanOrEqual(4.5); }); it(`${scheme}: accentContrast auf accent erfüllt AA (>= 4.5:1)`, () => { expect(contrastRatio(c.accentContrast, c.accent)).toBeGreaterThanOrEqual(4.5); }); it(`${scheme}: dangerContrast auf danger erfüllt AA (>= 4.5:1)`, () => { expect(contrastRatio(c.dangerContrast, c.danger)).toBeGreaterThanOrEqual(4.5); }); } });