import { test, expect } from '@playwright/test'; import AxeBuilder from '@axe-core/playwright'; function buildAxe(page: Parameters[0]['page']) { return new AxeBuilder({ page }).withTags(['wcag2a', 'wcag2aa']); } test.describe('Korrespondenz – empty state', () => { test('shows the search heading when no person is selected', async ({ page }) => { await page.goto('/korrespondenz'); await expect(page.getByText(/Korrespondenz durchsuchen/i)).toBeVisible(); const a11y = await buildAxe(page).analyze(); expect(a11y.violations, JSON.stringify(a11y.violations, null, 2)).toHaveLength(0); await page.screenshot({ path: 'test-results/e2e/korrespondenz-empty.png' }); }); test('nav link goes to /korrespondenz', async ({ page }) => { await page.goto('/'); // Click the nav link (desktop text or mobile icon) const navLink = page.getByRole('link', { name: /Korrespondenz/i }).first(); await navLink.click(); await expect(page).toHaveURL(/\/korrespondenz/); }); }); test.describe('Korrespondenz – single-person mode', () => { test('shows hint bar and documents when navigated with senderId', async ({ page }) => { // Get a real person ID from the persons list await page.goto('/persons'); const firstPersonLink = page.locator('a[href^="/persons/"]').first(); await firstPersonLink.click(); await page.waitForURL(/\/persons\/.+/); // Extract the person ID from the URL const personId = page.url().split('/persons/')[1].split('?')[0]; // Navigate to korrespondenz in single-person mode await page.goto(`/korrespondenz?senderId=${personId}`); // Hint bar should be visible await expect(page.getByText(/Alle Briefe von/i)).toBeVisible(); // Filter controls should be active (not dimmed) const filterStrip = page.locator('[aria-disabled="false"]').first(); await expect(filterStrip).toBeAttached(); const a11y = await buildAxe(page).analyze(); expect(a11y.violations, JSON.stringify(a11y.violations, null, 2)).toHaveLength(0); await page.screenshot({ path: 'test-results/e2e/korrespondenz-single-person.png' }); }); test('sort toggle changes URL direction param', async ({ page }) => { await page.goto('/persons'); const firstPersonLink = page.locator('a[href^="/persons/"]').first(); await firstPersonLink.click(); await page.waitForURL(/\/persons\/.+/); const personId = page.url().split('/persons/')[1].split('?')[0]; await page.goto(`/korrespondenz?senderId=${personId}&dir=DESC`); await page.getByTestId('conv-sort-btn').click(); await expect(page).toHaveURL(/dir=ASC/); await page.screenshot({ path: 'test-results/e2e/korrespondenz-sort-asc.png' }); }); }); test.describe('Korrespondenz – bilateral mode', () => { test('shows asymmetry bar when both persons have shared documents', async ({ page }) => { // Navigate to a person then follow a co-correspondent suggestion if available await page.goto('/persons'); const firstPersonLink = page.locator('a[href^="/persons/"]').first(); await firstPersonLink.click(); await page.waitForURL(/\/persons\/.+/); const senderId = page.url().split('/persons/')[1].split('?')[0]; // Try to find a co-correspondent link from the person detail page const corrLink = page .locator('a[href*="/korrespondenz?senderId="][href*="receiverId="]') .first(); if (await corrLink.isVisible({ timeout: 2000 }).catch(() => false)) { await corrLink.click(); await page.waitForURL(/\/korrespondenz\?.*receiverId=/); // Hint bar should NOT be shown in bilateral mode await expect(page.getByText(/Alle Briefe von/i)).not.toBeVisible(); const a11y = await buildAxe(page).analyze(); expect(a11y.violations, JSON.stringify(a11y.violations, null, 2)).toHaveLength(0); await page.screenshot({ path: 'test-results/e2e/korrespondenz-bilateral.png' }); } else { // E2E seed must include bilateral correspondents — a missing link is a test failure. throw new Error( `No bilateral correspondent links found for person ${senderId}. Ensure the E2E seed contains at least one bilateral correspondence pair.` ); } }); test('swap button swaps sender and receiver in URL', async ({ page }) => { await page.goto('/persons'); const firstPersonLink = page.locator('a[href^="/persons/"]').first(); await firstPersonLink.click(); await page.waitForURL(/\/persons\/.+/); const senderId = page.url().split('/persons/')[1].split('?')[0]; const corrLink = page .locator('a[href*="/korrespondenz?senderId="][href*="receiverId="]') .first(); if (await corrLink.isVisible({ timeout: 2000 }).catch(() => false)) { const href = await corrLink.getAttribute('href'); await corrLink.click(); await page.waitForURL(/\/korrespondenz\?.*receiverId=/); // Extract original receiverId from the href const url = new URL(href!, 'http://x'); const originalReceiverId = url.searchParams.get('receiverId')!; // Click swap await page.getByTestId('conv-swap-btn').click(); // After swap the former receiver is now senderId await expect(page).toHaveURL(new RegExp(`senderId=${originalReceiverId}`)); await page.screenshot({ path: 'test-results/e2e/korrespondenz-swapped.png' }); } else { test.skip(true, `No bilateral correspondent links found for person ${senderId}`); } }); });