Timeline: curator event create/edit forms (#781) #832
65
frontend/e2e/zeitstrahl-event-editor.spec.ts
Normal file
65
frontend/e2e/zeitstrahl-event-editor.spec.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user