From 6e738913f4b96c59888d0d3f5696c88712150682 Mon Sep 17 00:00:00 2001 From: Marcel Date: Mon, 11 May 2026 17:07:35 +0200 Subject: [PATCH] test(documents): rewrite list page test with behavioral assertions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces 3 setTimeout sleeps with click + auto-wait / vi.waitFor on the bulk-edit-all flow, and converts 14 .not.toThrow smoke tests into behavioral assertions: - Advanced-filter labels (Schlagworte/Absender/Empfänger/Von/Bis) for every hasAdvancedFilters() branch (senderId, from, to, tags) - Collapsed advanced section when all filters are at falsy defaults - Search input value reflected via two-way binding - BulkSelectionBar surfaces count when store has entries - bulk-edit-all populates selection store on success Runtime: 48s → 3.8s. Addresses Sara's blockers on PR #505. Co-Authored-By: Claude Opus 4.7 --- .../src/routes/documents/page.svelte.test.ts | 292 +++++++++--------- 1 file changed, 148 insertions(+), 144 deletions(-) diff --git a/frontend/src/routes/documents/page.svelte.test.ts b/frontend/src/routes/documents/page.svelte.test.ts index 4b285f77..5731ea18 100644 --- a/frontend/src/routes/documents/page.svelte.test.ts +++ b/frontend/src/routes/documents/page.svelte.test.ts @@ -30,7 +30,10 @@ vi.mock('$app/state', () => ({ const { default: DocumentsListPage } = await import('./+page.svelte'); const { bulkSelectionStore } = await import('$lib/document/bulkSelection.svelte'); -afterEach(cleanup); +afterEach(() => { + cleanup(); + bulkSelectionStore.clear(); +}); const baseData = (overrides: Record = {}) => ({ items: [] as { id: string; title: string }[], @@ -128,7 +131,6 @@ describe('documents/+ page', () => { it('displays the no-results state when items is empty (via DocumentList)', async () => { render(DocumentsListPage, { props: { data: baseData({ items: [], totalElements: 0 }) } }); - // DocumentList renders the empty placeholder expect(document.body.textContent).toMatch(/keine|noch|empty/i); }); @@ -174,38 +176,44 @@ describe('documents/+ page', () => { expect(input?.value).toBe('kurrent'); }); - it('renders without throwing when from/to date filters are preselected', async () => { - expect(() => - render(DocumentsListPage, { - props: { data: baseData({ from: '1899-01-01', to: '1950-12-31' }) } - }) - ).not.toThrow(); + it('opens the advanced-filter section when from/to date filters are preselected', async () => { + render(DocumentsListPage, { + props: { data: baseData({ from: '1899-01-01', to: '1950-12-31' }) } + }); + + // hasAdvancedFilters() returns true when from/to is set, which forces showAdvanced=true onMount, + // revealing the advanced filter section. The "Von" / "Bis" date labels are part of it. + await expect.element(page.getByText('Von')).toBeVisible(); + await expect.element(page.getByText('Bis')).toBeVisible(); }); - it('renders without throwing when tag filters are preselected', async () => { - expect(() => - render(DocumentsListPage, { - props: { data: baseData({ tags: ['Kurrent', 'Familie'] }) } - }) - ).not.toThrow(); + it('opens the advanced-filter section when tag filters are preselected', async () => { + render(DocumentsListPage, { + props: { data: baseData({ tags: ['Kurrent', 'Familie'] }) } + }); + + // Tag filter pills are part of the advanced filter section. + await expect.element(page.getByText('Schlagworte')).toBeVisible(); }); - it('renders without throwing when sender/receiver filters are set', async () => { - expect(() => - render(DocumentsListPage, { - props: { - data: baseData({ - senderId: 'p-1', - initialSenderName: 'Anna Schmidt', - receiverId: 'p-2', - initialReceiverName: 'Bert Meier' - }) - } - }) - ).not.toThrow(); + it('opens the advanced-filter section when sender/receiver filters are set', async () => { + render(DocumentsListPage, { + props: { + data: baseData({ + senderId: 'p-1', + initialSenderName: 'Anna Schmidt', + receiverId: 'p-2', + initialReceiverName: 'Bert Meier' + }) + } + }); + + // PersonTypeahead's combobox input is labelled by the "Absender" / "Empfänger"