/** * Der Prüfmaßstab für Barrierefreiheit – an einer einzigen Stelle. * * ## Warum eine gemeinsame Konstante * * Der Regelsatz stand vorher an elf Stellen einzeln im Quelltext, und genau * deshalb war er auseinandergelaufen: acht Stellen prüften gegen WCAG 2.1, * zwei gegen 2.2, eine benutzte bereits eine Konstante. Der Anspruch dieses * Projekts ist aber überall derselbe – **WCAG 2.2 AA**, siehe `PLAN.md` § 6.3. * Eine Kopie, die man vergisst mitzuziehen, ist keine Nachlässigkeit im * Kleinen: Sie senkt den Maßstab an einer Stelle, an der niemand hinsieht. * * ## Was der Regelsatz allein NICHT leistet * * Nachgemessen an axe-core 4.13.0: Am Tag `wcag22aa` hängt **genau eine** * Regel – `target-size` (SC 2.5.8) –, und die steht auf `enabled: false`. * Ein Tag in `runOnly` schaltet eine abgeschaltete Regel **nicht** ein. Wer * die Tagliste erweitert und das als „wir prüfen jetzt 2.2 AA" verbucht, * verbucht eine Null als Erfolg. * * Scharf wird die Regel erst über {@link FENSTER_REGELN}, und zwar * ausschließlich im echten Fenster – siehe dort. */ export const WCAG_TAGS = ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa'] as const; /** * Regelabweichungen für Läufe in **jsdom** (Vitest, `app/tests`). * * ## Das ist kein Schlupfloch * * Beide Regeln gelten unverändert. Sie sind hier nur deshalb abgeschaltet, * weil jsdom kein Layout rechnet und sie dort nichts messen **können** – sie * würden nicht bestehen, sie würden schweigen oder, schlimmer, falsch * bestehen. Geprüft werden sie im echten Fenster, siehe * {@link FENSTER_REGELN}. * * - `color-contrast` braucht gerechnete Farben. Unter jsdom landet die Regel * mangels CSS in `incomplete` statt in `violations` – ein stilles Nichts. * - `target-size` ist noch heikler: Nachgemessen meldet sie unter jsdom für * einen 8×8-Pixel-Knopf **„bestanden"**, weil jedes * `getBoundingClientRect()` dort `0×0` liefert und die Nachbarschafts- * rechnung degeneriert. Ein grünes Signal, das nichts gemessen hat, ist * schlechter als gar keins. */ export const JSDOM_REGELN = Object.freeze({ 'color-contrast': { enabled: false }, 'target-size': { enabled: false }, }); /** * Regelabweichungen für Läufe im **echten Fenster** (Playwright, `app/e2e`). * * Hier rechnet Chromium Layout und Farben – erst hier lässt sich WCAG 2.2 AA * tatsächlich messen. `target-size` muss ausdrücklich eingeschaltet werden, * weil axe-core sie standardmäßig abgeschaltet ausliefert und der Tag sie * nicht aktiviert. */ export const FENSTER_REGELN = Object.freeze({ 'target-size': { enabled: true }, }); /** Optionen für einen axe-Lauf unter jsdom. */ export function jsdomOptionen(): { runOnly: { type: 'tag'; values: string[] }; rules: Record; } { return { runOnly: { type: 'tag', values: [...WCAG_TAGS] }, rules: { ...JSDOM_REGELN }, }; } /** Optionen für einen axe-Lauf im echten Fenster. */ export function fensterOptionen(): { runOnly: { type: 'tag'; values: string[] }; rules: Record; } { return { runOnly: { type: 'tag', values: [...WCAG_TAGS] }, rules: { ...FENSTER_REGELN }, }; }