test(briefwechsel): axe sweep at 3 viewports x 2 themes

Adds a dedicated axe-core sweep for /briefwechsel so contrast or
semantic regressions on the new row layout fail independently of
the catch-all accessibility suite. Scoped to the main landmark so
shared chrome violations (if any) aren't double-reported.

Refs #305

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-23 14:52:38 +02:00
committed by marcel
parent 30e301830a
commit c16a9ca602

View File

@@ -0,0 +1,44 @@
import AxeBuilder from '@axe-core/playwright';
import { test, expect } from '@playwright/test';
// Accessibility coverage specifically for the briefwechsel thumbnail-row
// layout. Runs axe-core (wcag2a + wcag2aa) across three viewports and two
// color schemes so color-contrast regressions on the meta text or the
// distribution bar are caught independently of the site-wide sweep.
const VIEWPORTS = [
{ name: 'mobile', width: 375, height: 812 },
{ name: 'tablet', width: 768, height: 1024 },
{ name: 'desktop', width: 1280, height: 800 }
] as const;
const THEMES = ['light', 'dark'] as const;
test.describe('Accessibility — /briefwechsel row layout', () => {
for (const vp of VIEWPORTS) {
for (const theme of THEMES) {
test(`${vp.name} / ${theme} has no wcag2a/wcag2aa violations`, async ({ page }) => {
await page.setViewportSize({ width: vp.width, height: vp.height });
await page.emulateMedia({ colorScheme: theme });
await page.goto('/briefwechsel');
await page.waitForSelector('[data-hydrated]');
const results = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa'])
.include('main')
.analyze();
if (results.violations.length > 0) {
const summary = results.violations
.map((v) => `[${v.impact}] ${v.id}: ${v.description} (${v.nodes.length} node(s))`)
.join('\n');
console.log(
`\nAccessibility violations on briefwechsel (${vp.name}/${theme}):\n${summary}`
);
}
expect(results.violations).toEqual([]);
});
}
}
});