From 208c1adc3e66415cb3830b7ecfb85a854ffd4fc9 Mon Sep 17 00:00:00 2001 From: Marcel Date: Sat, 18 Apr 2026 16:30:10 +0200 Subject: [PATCH] test(edit): add tests for handleDelete on the edit page Covers: button present, confirm dialog opens, form submitted on confirm, form not submitted on cancel. Co-Authored-By: Claude Sonnet 4.6 --- .../documents/[id]/edit/page.svelte.spec.ts | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 frontend/src/routes/documents/[id]/edit/page.svelte.spec.ts diff --git a/frontend/src/routes/documents/[id]/edit/page.svelte.spec.ts b/frontend/src/routes/documents/[id]/edit/page.svelte.spec.ts new file mode 100644 index 00000000..8ddb2614 --- /dev/null +++ b/frontend/src/routes/documents/[id]/edit/page.svelte.spec.ts @@ -0,0 +1,82 @@ +import { vi, describe, it, expect, afterEach } from 'vitest'; +import { cleanup, render } from 'vitest-browser-svelte'; +import { page } from 'vitest/browser'; +import { createConfirmService, CONFIRM_KEY } from '$lib/services/confirm.svelte.js'; +import EditPage from './+page.svelte'; + +afterEach(cleanup); + +function makeDocument(overrides: Record = {}) { + return { + id: 'doc-1', + title: 'Test Document', + originalFilename: 'test.pdf', + status: 'UPLOADED' as const, + createdAt: '2024-01-01T00:00:00Z', + updatedAt: '2024-01-01T00:00:00Z', + metadataComplete: false, + scriptType: 'UNKNOWN' as const, + // No filePath — avoids triggering the file loader fetch in tests + ...overrides + }; +} + +describe('Edit page — delete button', () => { + it('renders the delete button', async () => { + const service = createConfirmService(); + render(EditPage, { + props: { data: { document: makeDocument() }, form: null }, + context: new Map([[CONFIRM_KEY, service]]) + }); + await expect.element(page.getByRole('button', { name: /löschen/i })).toBeInTheDocument(); + }); + + it('opens a confirm dialog when the delete button is clicked', async () => { + const service = createConfirmService(); + render(EditPage, { + props: { data: { document: makeDocument() }, form: null }, + context: new Map([[CONFIRM_KEY, service]]) + }); + + await page.getByRole('button', { name: /löschen/i }).click(); + // The confirm service should have received an options object (dialog is open) + expect(service.options).not.toBeNull(); + expect(service.options?.destructive).toBe(true); + service.settle(false); + }); + + it('submits the delete form when the user confirms', async () => { + const service = createConfirmService(); + render(EditPage, { + props: { data: { document: makeDocument() }, form: null }, + context: new Map([[CONFIRM_KEY, service]]) + }); + + const deleteForm = document.getElementById('delete-form') as HTMLFormElement; + const submitSpy = vi.spyOn(deleteForm, 'requestSubmit').mockImplementation(() => {}); + + await page.getByRole('button', { name: /löschen/i }).click(); + // confirm() has been called synchronously — settle and flush the microtask queue + service.settle(true); + await Promise.resolve(); + + expect(submitSpy).toHaveBeenCalledOnce(); + }); + + it('does NOT submit the delete form when the user cancels', async () => { + const service = createConfirmService(); + render(EditPage, { + props: { data: { document: makeDocument() }, form: null }, + context: new Map([[CONFIRM_KEY, service]]) + }); + + const deleteForm = document.getElementById('delete-form') as HTMLFormElement; + const submitSpy = vi.spyOn(deleteForm, 'requestSubmit').mockImplementation(() => {}); + + await page.getByRole('button', { name: /löschen/i }).click(); + service.settle(false); + await Promise.resolve(); + + expect(submitSpy).not.toHaveBeenCalled(); + }); +});