Compare commits

..

2 Commits

Author SHA1 Message Date
Marcel
53b482c5f2 fix(e2e): fix admin tag test (use existing tag) and annotation locator
Some checks failed
CI / Unit & Component Tests (push) Successful in 2m37s
CI / Backend Unit Tests (push) Successful in 2m18s
CI / E2E Tests (push) Failing after 30m45s
- Admin tag test: "Familie" never existed in the database; use "Fest"
  which is a real seeded tag, with a matching rename-back to restore state
- Annotation hash test: the broad `[data-testid^="annotation-"]` locator
  also matched `annotation-side-panel` (always in DOM, even when
  off-screen); extend the :not() exclusion list to cover it

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 11:34:42 +01:00
Marcel
fa9577052d fix(e2e): fix 4 failing e2e tests — strict mode locator and nested form
Some checks failed
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (push) Successful in 2m23s
CI / Backend Unit Tests (push) Successful in 2m11s
CI / E2E Tests (push) Failing after 29m1s
documents.spec.ts: replace getByText with getByRole('heading') to avoid
Svelte's #svelte-announcer matching the same text (strict mode violation).

SaveBar.svelte: move <form id="mark-for-review-form"> out of the component
and into +page.svelte as a sibling of delete-form. The form was previously
nested inside <form id="update-form">, which is invalid HTML. The browser
auto-repaired it, causing a Svelte hydration mismatch that broke the edit
form's use:enhance, preventing version snapshots from being recorded —
leaving history tests with 0 versions instead of the expected 2.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 10:04:21 +01:00
4 changed files with 17 additions and 17 deletions

View File

@@ -180,19 +180,19 @@ test.describe('Admin — tag management', () => {
// Wait for the tags list to render after the tab switch // Wait for the tags list to render after the tab switch
await page.waitForSelector('ul > li'); await page.waitForSelector('ul > li');
// Hover over the "Familie" row to reveal the opacity-0 action buttons // Hover over the "Fest" row to reveal the opacity-0 action buttons
const familieRow = page const festRow = page
.locator('ul > li') .locator('ul > li')
.filter({ has: page.locator('span', { hasText: /^Familie$/ }) }); .filter({ has: page.locator('span', { hasText: /^Fest$/ }) });
await familieRow.hover(); await festRow.hover();
await familieRow.getByRole('button', { name: 'Schlagwort bearbeiten' }).click(); await festRow.getByRole('button', { name: 'Schlagwort bearbeiten' }).click();
// After clicking edit, {#if editingTagId} replaces the span with a form — // After clicking edit, {#if editingTagId} replaces the span with a form —
// the familieRow filter no longer matches, so we find the input directly. // the festRow filter no longer matches, so we find the input directly.
await page.locator('input[name="name"]').fill('Familie (E2E)'); await page.locator('input[name="name"]').fill('Fest (E2E)');
await page.getByRole('button', { name: 'Speichern' }).click(); await page.getByRole('button', { name: 'Speichern' }).click();
await expect(page.getByText('Familie (E2E)')).toBeVisible(); await expect(page.getByText('Fest (E2E)')).toBeVisible();
await page.screenshot({ path: 'test-results/e2e/admin-tag-renamed.png' }); await page.screenshot({ path: 'test-results/e2e/admin-tag-renamed.png' });
}); });
@@ -205,14 +205,14 @@ test.describe('Admin — tag management', () => {
const renamedRow = page const renamedRow = page
.locator('ul > li') .locator('ul > li')
.filter({ has: page.locator('span', { hasText: /^Familie \(E2E\)$/ }) }); .filter({ has: page.locator('span', { hasText: /^Fest \(E2E\)$/ }) });
await renamedRow.hover(); await renamedRow.hover();
await renamedRow.getByRole('button', { name: 'Schlagwort bearbeiten' }).click(); await renamedRow.getByRole('button', { name: 'Schlagwort bearbeiten' }).click();
await page.locator('input[name="name"]').fill('Familie'); await page.locator('input[name="name"]').fill('Fest');
await page.getByRole('button', { name: 'Speichern' }).click(); await page.getByRole('button', { name: 'Speichern' }).click();
await expect(page.getByText('Familie')).toBeVisible(); await expect(page.getByText('Fest')).toBeVisible();
await page.screenshot({ path: 'test-results/e2e/admin-tag-restored.png' }); await page.screenshot({ path: 'test-results/e2e/admin-tag-restored.png' });
}); });
}); });

View File

@@ -167,7 +167,7 @@ test.describe('Document editing', () => {
await page.getByRole('button', { name: 'Speichern', exact: true }).click(); await page.getByRole('button', { name: 'Speichern', exact: true }).click();
await expect(page).toHaveURL(/\/documents\/[^/]+$/); await expect(page).toHaveURL(/\/documents\/[^/]+$/);
await expect(page.getByText('E2E Testbrief (überarbeitet)')).toBeVisible(); await expect(page.getByRole('heading', { name: 'E2E Testbrief (überarbeitet)' })).toBeVisible();
await page.screenshot({ path: 'test-results/e2e/document-edit-save.png' }); await page.screenshot({ path: 'test-results/e2e/document-edit-save.png' });
}); });
}); });
@@ -461,9 +461,11 @@ test.describe('PDF annotations — file hash versioning', () => {
await page.waitForSelector('[data-hydrated]'); await page.waitForSelector('[data-hydrated]');
await page.locator('canvas').first().waitFor({ state: 'visible', timeout: 20000 }); await page.locator('canvas').first().waitFor({ state: 'visible', timeout: 20000 });
// Use :not() to exclude the outdated-notice element whose testid also starts with "annotation-" // Use :not() to exclude the outdated-notice and side-panel elements whose testid also starts with "annotation-"
await expect( await expect(
page.locator('[data-testid^="annotation-"]:not([data-testid="annotation-outdated-notice"])') page.locator(
'[data-testid^="annotation-"]:not([data-testid="annotation-outdated-notice"]):not([data-testid="annotation-side-panel"])'
)
).toHaveCount(0, { timeout: 8000 }); ).toHaveCount(0, { timeout: 8000 });
await expect(page.locator('[data-testid="annotation-outdated-notice"]')).toBeVisible({ await expect(page.locator('[data-testid="annotation-outdated-notice"]')).toBeVisible({
timeout: 5000 timeout: 5000

View File

@@ -68,5 +68,6 @@ let selectedReceivers = $state(doc.receivers ?? []);
<SaveBar docId={doc.id} /> <SaveBar docId={doc.id} />
</form> </form>
<form id="mark-for-review-form" method="POST" action="?/markForReview" use:enhance></form>
<form id="delete-form" method="POST" action="?/delete" use:enhance></form> <form id="delete-form" method="POST" action="?/delete" use:enhance></form>
</div> </div>

View File

@@ -1,6 +1,5 @@
<script lang="ts"> <script lang="ts">
import { m } from '$lib/paraglide/messages.js'; import { m } from '$lib/paraglide/messages.js';
import { enhance } from '$app/forms';
let { docId }: { docId: string } = $props(); let { docId }: { docId: string } = $props();
@@ -78,5 +77,3 @@ let confirmDelete = $state(false);
</button> </button>
</div> </div>
</div> </div>
<form id="mark-for-review-form" method="POST" action="?/markForReview" use:enhance></form>