One critical create journey (fill form with precision RANGE → HTTP 200 on /zeitstrahl; the card assertion depends on #7), one security counterpart (logged-out → 403), and one 320px no-overflow guarantee. Intentionally thin — ci.yml does not run test:e2e today, so regression coverage lives in the component + server specs that DO run in CI. Written, not executed locally. Refs #781 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
66 lines
2.6 KiB
TypeScript
66 lines
2.6 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
/**
|
|
* Curator timeline event editor (#781) — intentionally thin. The component +
|
|
* server specs carry the real regression coverage (they run in CI's "Unit &
|
|
* Component Tests" job); ci.yml does NOT invoke test:e2e today, so this file
|
|
* runs only locally/manually against the full Docker Compose stack.
|
|
*
|
|
* Three checks: one critical create journey (→ HTTP 200 on /zeitstrahl; the full
|
|
* "sees the event card" assertion depends on #7), one security counterpart
|
|
* (logged-out → 403), and one 320px no-overflow guarantee for the 60+ author
|
|
* audience.
|
|
*/
|
|
|
|
const stamp = () => new Date().toISOString().replace(/[^0-9]/g, '');
|
|
|
|
test.describe('Curator creates a timeline event', () => {
|
|
test('fills the create form with precision RANGE and lands on /zeitstrahl (HTTP 200)', async ({
|
|
page
|
|
}) => {
|
|
await page.goto('/zeitstrahl/events/new');
|
|
|
|
await page.getByLabel(/Titel/i).fill(`E2E Ereignis ${stamp()}`);
|
|
await page.getByRole('radio', { name: /Historisch/i }).click();
|
|
|
|
// Date + RANGE end date via the shared German dd.mm.yyyy inputs.
|
|
await page.locator('#eventDate').fill('01.04.1925');
|
|
await page.locator('#eventDatePrecision').selectOption('RANGE');
|
|
await expect(page.getByLabel('Enddatum')).toBeVisible();
|
|
await page.locator('#eventDateEnd').fill('01.05.1925');
|
|
|
|
// Submitting redirects to the resolved nav target (/zeitstrahl) — assert the
|
|
// route responds 200, not a DOM card (card rendering is #7's concern).
|
|
await Promise.all([
|
|
page.waitForURL(/\/zeitstrahl$/),
|
|
page.getByRole('button', { name: 'Speichern' }).click()
|
|
]);
|
|
const response = await page.goto('/zeitstrahl');
|
|
expect(response?.status()).toBe(200);
|
|
});
|
|
});
|
|
|
|
test.describe('Logged-out user is blocked from the curator route', () => {
|
|
test.use({ storageState: { cookies: [], origins: [] } });
|
|
|
|
test('navigating to /zeitstrahl/events/new is blocked with 403', async ({ page }) => {
|
|
await page.goto('/zeitstrahl/events/new');
|
|
// The load guard throws 403 before any form renders.
|
|
await expect(page.getByLabel(/Titel/i)).not.toBeVisible({ timeout: 5000 });
|
|
await expect(page.getByText(/403|Zugriff verweigert|Forbidden/i)).toBeVisible({
|
|
timeout: 5000
|
|
});
|
|
});
|
|
});
|
|
|
|
test.describe('Responsive — 60+ author audience', () => {
|
|
test('no horizontal overflow on the create form at 320px', async ({ page }) => {
|
|
await page.setViewportSize({ width: 320, height: 900 });
|
|
await page.goto('/zeitstrahl/events/new');
|
|
await expect(page.getByLabel(/Titel/i)).toBeVisible();
|
|
|
|
const scrollWidth = await page.evaluate(() => document.body.scrollWidth);
|
|
expect(scrollWidth).toBe(320);
|
|
});
|
|
});
|