epic(legibility): pre-flight — make tests trustworthy (#402) #430

Merged
marcel merged 11 commits from worktree-test-issue-402-legibility-preflight into main 2026-05-05 20:36:15 +02:00
Showing only changes of commit fcd91c2e81 - Show all commits

View File

@@ -563,41 +563,69 @@ test.describe('PDF annotations — read-only user', () => {
// ── J3: Edit document — add an existing tag ────────────────────────────────
//
// Verifies that a user can open a document's edit page and assign a tag using
// the TagInput component, then save and see the tag chip on the detail page.
// the TagInput component, then save and see the tag link on the detail page.
// Seeds a unique tag via a throwaway document so the test never depends on the
// seeded "Familie" tag (which admin tests rename during their lifecycle).
test.describe('Document editing — tags (J3)', () => {
const baseURL = process.env.E2E_BASE_URL ?? 'http://localhost:3000';
let tagDocHref: string;
let tagDocId: string;
let seedDocId: string;
let seededTagName: string;
test.beforeAll(async ({ request }) => {
const stamp = Date.now().toString(36);
seededTagName = `E2E-J3-Tag-${stamp}`;
// Create a throwaway document and associate the unique tag with it so it
// exists in the system for the TagInput suggestion list.
const seederRes = await request.post('/api/documents', {
multipart: { title: `E2E J3 Tag Seeder ${stamp}` }
});
if (!seederRes.ok()) throw new Error(`Create seeder failed: ${seederRes.status()}`);
const seeder = await seederRes.json();
seedDocId = seeder.id;
const seedTagRes = await request.put(`/api/documents/${seedDocId}`, {
multipart: { title: seeder.title, tags: seededTagName }
});
if (!seedTagRes.ok()) throw new Error(`Seed tag failed: ${seedTagRes.status()}`);
// Create the test document without the tag — the test will add it.
const createRes = await request.post('/api/documents', {
multipart: { title: 'E2E Tag Edit Test' }
multipart: { title: `E2E Tag Edit Test ${stamp}` }
});
if (!createRes.ok()) throw new Error(`Create document failed: ${createRes.status()}`);
const doc = await createRes.json();
tagDocHref = `${baseURL}/documents/${doc.id}`;
tagDocId = doc.id;
});
test.afterAll(async ({ request }) => {
if (tagDocId) await request.delete(`/api/documents/${tagDocId}`);
if (seedDocId) await request.delete(`/api/documents/${seedDocId}`);
});
test('user adds an existing tag and sees it on the detail page', async ({ page }) => {
await page.goto(`${tagDocHref}/edit`);
await page.goto(`/documents/${tagDocId}/edit`);
await page.waitForSelector('[data-hydrated]');
// TagInput has placeholder "Schlagworte hinzufügen..." when empty.
const tagInput = page.getByPlaceholder('Schlagworte hinzufügen...');
await expect(tagInput).toBeVisible();
// Type the beginning of the seeded "Familie" tag and wait for the suggestion.
await tagInput.fill('Fami');
const suggestion = page.getByRole('option', { name: /Familie/i }).first();
// Type the seeded tag name and wait for the suggestion.
await tagInput.fill(seededTagName);
const suggestion = page.getByRole('option', { name: seededTagName }).first();
await expect(suggestion).toBeVisible({ timeout: 5_000 });
await suggestion.click();
// Save the document.
await page.getByRole('button', { name: 'Speichern', exact: true }).click();
// Redirected to detail page — the tag chip must be visible.
// Redirected to detail page — the tag link must be visible in the metadata section.
await expect(page).toHaveURL(/\/documents\/[^/]+$/);
await expect(page.getByText(/Familie/)).toBeVisible({ timeout: 5_000 });
await expect(page.locator('a[href*="?tag="]', { hasText: seededTagName })).toBeVisible({
timeout: 5_000
});
await page.screenshot({ path: 'test-results/e2e/document-edit-tag.png' });
});
});