dorfteich/apps/web/e2e/legal.spec.ts
Claude Opus 5 942f7b13d3
Some checks failed
CI / Lint, typecheck, test (pull_request) Successful in 6m31s
CI / Build container images (pull_request) Successful in 1m15s
CI / Auth e2e pack (pull_request) Successful in 8m57s
CI / Import/export fidelity gate (pull_request) Successful in 53s
CD / Build and push images (push) Successful in 36s
CD / Deploy to Test (push) Successful in 11s
CD / Smoke tests against Test (push) Successful in 1m24s
CD / Promote to Int (push) Successful in 12s
CI / Lint, typecheck, test (push) Failing after 7m12s
CI / Auth e2e pack (push) Has been skipped
CI / Import/export fidelity gate (push) Has been skipped
CI / Build container images (push) Has been skipped
#304: scope the legal spec's status locator to its own form
The font manager's upload live regions made `getByRole('status')` ambiguous
on /admin, and legal.spec.ts — which asserts the legal form's success message
— started failing in the e2e pack. That is the documented trap in CLAUDE.md:
a new label or region makes an existing page-wide locator ambiguous, and the
fix is to scope the SPEC, not to drop the region a screen reader needs.

The section gets a named class for exactly that purpose.

Verified locally against the running stack: legal, fonts, admin-users,
admin-quotas and the a11y pack all pass.
2026-08-01 19:05:18 +02:00

79 lines
3.5 KiB
TypeScript

import { expect, test } from '@playwright/test';
import { contextForUser } from './helpers';
const BASE_URL = process.env.E2E_BASE_URL ?? 'http://localhost:5173';
const IMPRINT_TEXT = 'E2E Legal Operator, Example Lane 1';
/**
* Instance legal pages (issue #82): a Site Admin's Markdown renders publicly,
* footer links reach it from everywhere (including auth screens), and an
* unconfigured page shows a notice — plus a warning banner for Site Admins.
* The state is set explicitly up front, so the pack is repeatable.
*/
test.beforeAll(async ({ browser }) => {
const admin = await contextForUser(browser, BASE_URL, 'fixture-admin');
const response = await admin.request.patch('/api/v1/admin/settings', {
data: { 'legal.imprint': `## Operator\n\n${IMPRINT_TEXT}`, 'legal.privacyPolicy': '' },
});
expect(response.ok()).toBe(true);
await admin.close();
});
test('footer links lead anonymous visitors to the configured imprint', async ({ page }) => {
// The auth screen carries the footer too (AC: links appear everywhere).
await page.goto('/login');
await page
.locator('.app-footer')
.getByRole('link', { name: /imprint|impressum/i })
.click();
await expect(page).toHaveURL(/\/legal\/imprint$/);
await expect(page.getByRole('heading', { name: /imprint|impressum/i }).first()).toBeVisible();
await expect(page.getByText(IMPRINT_TEXT)).toBeVisible();
});
test('an unconfigured page shows a notice to visitors, not a 404', async ({ page }) => {
await page.goto('/legal/privacy');
await expect(page.getByText(/not provided this text yet|noch nicht hinterlegt/i)).toBeVisible();
// Anonymous visitors get the neutral notice only — no admin warning.
await expect(page.getByRole('alert')).toHaveCount(0);
});
test('site admins see a warning banner on unconfigured pages', async ({ browser }) => {
const admin = await contextForUser(browser, BASE_URL, 'fixture-admin');
const page = await admin.newPage();
await page.goto('/legal/privacy');
const banner = page.getByRole('alert');
await expect(banner).toBeVisible();
await banner.getByRole('link').click();
await expect(page).toHaveURL(/\/admin$/);
await admin.close();
});
test('the admin form previews and publishes the privacy policy', async ({ browser }) => {
const admin = await contextForUser(browser, BASE_URL, 'fixture-admin');
const page = await admin.newPage();
await page.goto('/admin');
// Second legal editor = the privacy policy (imprint comes first).
const editor = page.locator('.legal-editor').nth(1);
await editor.locator('textarea').fill('We process **only what is needed**.');
await editor.getByRole('button', { name: /preview|vorschau/i }).click();
await expect(editor.locator('.legal-editor__preview strong')).toHaveText('only what is needed');
await page.getByRole('button', { name: /save legal pages|rechtsseiten speichern/i }).click();
// Auf den Abschnitt gescopet: seit der Schriftverwaltung (#304) hat /admin
// weitere Live-Regionen (Upload-Fortschritt), und ein seitenweites
// getByRole('status') wäre mehrdeutig. Gemeint war immer die
// Erfolgsmeldung DIESES Formulars.
await expect(page.locator('.legal-settings').getByRole('status')).toBeVisible();
await admin.close();
const anonymous = await browser.newContext({ baseURL: BASE_URL });
const anonymousPage = await anonymous.newPage();
await anonymousPage.goto('/legal/privacy');
await expect(anonymousPage.getByText('only what is needed')).toBeVisible();
await anonymous.close();
});