- AuthHeader: remove duplicated locale logic, use <LanguageSwitcher inverted /> - Fix text-white/55 → text-white/70 in AppNav and LanguageSwitcher (WCAG AA) - E2E: add axe accessibility checks, replace [data-hydrated] with role selectors, add 768px hamburger test and BRAND_NAVY comment Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
97 lines
3.3 KiB
TypeScript
97 lines
3.3 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import AxeBuilder from '@axe-core/playwright';
|
|
|
|
// #012851 — brand-navy, defined as --c-primary in layout.css
|
|
const BRAND_NAVY = 'rgb(1, 40, 81)';
|
|
|
|
test.describe('Header — brand-navy background', () => {
|
|
test('header background is brand-navy in light mode', async ({ page }) => {
|
|
await page.goto('/');
|
|
await expect(page.getByRole('navigation')).toBeVisible();
|
|
|
|
const bg = await page.locator('header').evaluate((el) => getComputedStyle(el).backgroundColor);
|
|
expect(bg).toBe(BRAND_NAVY);
|
|
});
|
|
|
|
test('header passes accessibility audit in light mode', async ({ page }) => {
|
|
await page.goto('/');
|
|
await expect(page.getByRole('navigation')).toBeVisible();
|
|
|
|
const results = await new AxeBuilder({ page }).include('header').analyze();
|
|
expect(results.violations).toEqual([]);
|
|
});
|
|
|
|
test('header background stays brand-navy after switching to dark mode', async ({ page }) => {
|
|
await page.goto('/');
|
|
await expect(page.getByRole('navigation')).toBeVisible();
|
|
|
|
await page
|
|
.getByRole('banner')
|
|
.getByRole('button', { name: /dark mode/i })
|
|
.click();
|
|
await expect(page.locator('html')).toHaveAttribute('data-theme', 'dark');
|
|
|
|
const bg = await page.locator('header').evaluate((el) => getComputedStyle(el).backgroundColor);
|
|
expect(bg).toBe(BRAND_NAVY);
|
|
});
|
|
|
|
test('header passes accessibility audit in dark mode', async ({ page }) => {
|
|
await page.goto('/');
|
|
await expect(page.getByRole('navigation')).toBeVisible();
|
|
|
|
await page
|
|
.getByRole('banner')
|
|
.getByRole('button', { name: /dark mode/i })
|
|
.click();
|
|
await expect(page.locator('html')).toHaveAttribute('data-theme', 'dark');
|
|
|
|
const results = await new AxeBuilder({ page }).include('header').analyze();
|
|
expect(results.violations).toEqual([]);
|
|
});
|
|
|
|
test('logo text is visible at 375px viewport', async ({ page }) => {
|
|
await page.setViewportSize({ width: 375, height: 812 });
|
|
await page.goto('/');
|
|
|
|
await expect(page.getByRole('banner').getByText('Familienarchiv')).toBeVisible();
|
|
});
|
|
|
|
test('hamburger menu opens on tablet viewport (768px)', async ({ page }) => {
|
|
await page.setViewportSize({ width: 768, height: 1024 });
|
|
await page.goto('/');
|
|
await expect(page.getByRole('navigation')).toBeVisible();
|
|
|
|
const hamburger = page.getByRole('button', { name: /menü öffnen/i });
|
|
await expect(hamburger).toBeVisible();
|
|
await hamburger.click();
|
|
|
|
await expect(
|
|
page.getByRole('navigation', { name: /mobile/i }).or(page.locator('#mobile-nav'))
|
|
).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test.describe('Login page — AuthHeader', () => {
|
|
test.use({ storageState: { cookies: [], origins: [] } });
|
|
|
|
test('login page has brand-navy header with language switcher', async ({ page }) => {
|
|
await page.goto('/login');
|
|
|
|
const header = page.locator('header');
|
|
await expect(header).toBeVisible();
|
|
|
|
const bg = await header.evaluate((el) => getComputedStyle(el).backgroundColor);
|
|
expect(bg).toBe(BRAND_NAVY);
|
|
|
|
await expect(header.getByRole('button', { name: 'DE' })).toBeVisible();
|
|
});
|
|
|
|
test('login page header passes accessibility audit', async ({ page }) => {
|
|
await page.goto('/login');
|
|
await expect(page.locator('header')).toBeVisible();
|
|
|
|
const results = await new AxeBuilder({ page }).include('header').analyze();
|
|
expect(results.violations).toEqual([]);
|
|
});
|
|
});
|