diff --git a/tests/ui/a11y/accessibility.spec.js b/tests/ui/a11y/accessibility.spec.js index eb6d89c..399c295 100644 --- a/tests/ui/a11y/accessibility.spec.js +++ b/tests/ui/a11y/accessibility.spec.js @@ -136,3 +136,30 @@ axeScan('AX2', '/trips/italy-2026-demo'); axeScan('AX3', '/trips/italy-2026-demo/dailies'); axeScan('AX4', '/trips/italy-2026-demo/dailies/2026-09-01-0700-setting-off-from-campiglia.entry'); axeScan('AX5', '/trips'); + +// ── AX6: /gpx-manager passes axe (mocked file list) ────────────────────────── +test('AX6: /gpx-manager passes axe WCAG 2.1 AA (critical/serious)', async ({ page }) => { + await page.route('**/api/v1/pages**/media', async route => { + await route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ + data: [{ filename: 'day1.gpx', size: 51200, modified: '2026-06-01T10:00:00Z' }] + }) + }); + }); + await page.goto('/gpx-manager'); + // Wait for file list to render before scanning (multiple trips → multiple tables; first() avoids strict-mode violation) + await expect(page.locator('.gpx-table').first()).toBeVisible({ timeout: 10000 }); + const results = await new AxeBuilder({ page }).withTags(WCAG_TAGS).analyze(); + const violations = results.violations.filter(v => BLOCKING.includes(v.impact)); + expect( + violations, + violations.map(v => + `[${v.impact}] ${v.id}: ${v.description}\n ` + + v.nodes.map(n => n.html).join('\n ') + ).join('\n\n') + ).toHaveLength(0); +}); + +axeScan('AX7', '/trips/italy-2026-demo/stories/val-dorcia-at-dawn');