diff --git a/frontend/e2e/back-button.spec.ts b/frontend/e2e/back-button.spec.ts new file mode 100644 index 00000000..4bfa0f66 --- /dev/null +++ b/frontend/e2e/back-button.spec.ts @@ -0,0 +1,58 @@ +import AxeBuilder from '@axe-core/playwright'; +import { test, expect } from '@playwright/test'; + +test.describe('BackButton — navigation', () => { + test('returns to previous page via history when clicked', async ({ page }) => { + // Navigate to persons list, then to a person detail + await page.goto('/persons'); + await page.waitForSelector('[data-hydrated]'); + + const firstPersonLink = page.locator('a[href^="/persons/"]').first(); + const personHref = await firstPersonLink.getAttribute('href'); + await firstPersonLink.click(); + await page.waitForURL(/\/persons\/.+/); + + // Now navigate to the edit page from the detail page + const editLink = page.locator('a[href$="/edit"]').first(); + await editLink.click(); + await page.waitForURL(/\/persons\/.+\/edit/); + + // Click the BackButton — should return to person detail, not /persons list + const backBtn = page.getByRole('button', { name: /zurück/i }); + await expect(backBtn).toBeVisible(); + await backBtn.click(); + + // Should return to the person detail URL (history.back()), not the static /persons + await expect(page).toHaveURL(new RegExp(personHref!.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))); + }); +}); + +test.describe('BackButton — accessibility', () => { + test('touch target is at least 44px tall on /persons/new', async ({ page }) => { + await page.goto('/persons/new'); + await page.waitForSelector('[data-hydrated]'); + + const backBtn = page.getByRole('button', { name: /zurück/i }); + await expect(backBtn).toBeVisible(); + + const box = await backBtn.boundingBox(); + expect(box).not.toBeNull(); + expect(box!.height).toBeGreaterThanOrEqual(44); + }); + + test('passes axe-core wcag2a/wcag2aa scan on /persons/new', async ({ page }) => { + await page.goto('/persons/new'); + await page.waitForSelector('[data-hydrated]'); + + const results = await new AxeBuilder({ page }).withTags(['wcag2a', 'wcag2aa']).analyze(); + + if (results.violations.length > 0) { + const summary = results.violations + .map((v) => `[${v.impact}] ${v.id}: ${v.description}`) + .join('\n'); + console.log(`\nAxe violations on /persons/new:\n${summary}`); + } + + expect(results.violations).toEqual([]); + }); +});