diff --git a/frontend/src/routes/documents/[id]/edit/SaveBar.svelte b/frontend/src/routes/documents/[id]/edit/SaveBar.svelte
index 17195ce5..477f3582 100644
--- a/frontend/src/routes/documents/[id]/edit/SaveBar.svelte
+++ b/frontend/src/routes/documents/[id]/edit/SaveBar.svelte
@@ -1,9 +1,20 @@
-
+
- {#if confirmDelete}
-
{m.doc_delete_confirm()}
-
-
-
-
- {:else}
-
+
+ {m.btn_cancel()}
+
diff --git a/frontend/src/routes/documents/[id]/edit/SaveBar.svelte.spec.ts b/frontend/src/routes/documents/[id]/edit/SaveBar.svelte.spec.ts
new file mode 100644
index 00000000..d1ad0d97
--- /dev/null
+++ b/frontend/src/routes/documents/[id]/edit/SaveBar.svelte.spec.ts
@@ -0,0 +1,92 @@
+import { describe, it, expect, vi, afterEach } from 'vitest';
+import { cleanup, render } from 'vitest-browser-svelte';
+import { page } from 'vitest/browser';
+import SaveBar from './SaveBar.svelte';
+import { createConfirmService, CONFIRM_KEY } from '$lib/services/confirm.svelte.js';
+
+let appendedForms: HTMLFormElement[] = [];
+
+afterEach(() => {
+ cleanup();
+ appendedForms.forEach((f) => f.remove());
+ appendedForms = [];
+});
+
+function renderSaveBar(docId = 'doc-1') {
+ const service = createConfirmService();
+
+ // Mount a dummy delete form so SaveBar can find it via document.getElementById
+ const deleteForm = document.createElement('form');
+ deleteForm.id = 'delete-form';
+ document.body.appendChild(deleteForm);
+ appendedForms.push(deleteForm);
+
+ const result = render(SaveBar, {
+ props: { docId },
+ context: new Map([[CONFIRM_KEY, service]])
+ });
+
+ return { ...result, service, deleteForm };
+}
+
+// ─── Rendering ────────────────────────────────────────────────────────────────
+
+describe('SaveBar — rendering', () => {
+ it('renders save button', async () => {
+ renderSaveBar();
+ await expect.element(page.getByRole('button', { name: /Speichern/i })).toBeInTheDocument();
+ });
+
+ it('renders delete button', async () => {
+ renderSaveBar();
+ // The delete button should be type="button" (async confirm flow)
+ const deleteBtn = document.querySelector('button[type="button"]');
+ expect(deleteBtn).not.toBeNull();
+ });
+
+ it('renders cancel link pointing to /documents/doc-1', async () => {
+ renderSaveBar();
+ await expect
+ .element(page.getByRole('link', { name: /Abbrechen/i }))
+ .toHaveAttribute('href', '/documents/doc-1');
+ });
+});
+
+// ─── Delete confirmation ──────────────────────────────────────────────────────
+
+describe('SaveBar — delete confirmation', () => {
+ it('opens confirm dialog when delete button is clicked', async () => {
+ const { service } = renderSaveBar();
+ const deleteBtn = document.querySelectorAll('button[type="button"]')[0];
+ deleteBtn.click();
+ await vi.waitFor(() => expect(service.options).not.toBeNull());
+ expect(service.options?.destructive).toBe(true);
+ service.settle(false);
+ });
+
+ it('submits delete form when user confirms', async () => {
+ const { service, deleteForm } = renderSaveBar();
+ const requestSubmit = vi.spyOn(deleteForm, 'requestSubmit').mockImplementation(() => {});
+
+ const deleteBtn = document.querySelectorAll('button[type="button"]')[0];
+ deleteBtn.click();
+ await vi.waitFor(() => expect(service.options).not.toBeNull());
+ service.settle(true);
+ await vi.waitFor(() => expect(service.options).toBeNull());
+
+ expect(requestSubmit).toHaveBeenCalledOnce();
+ });
+
+ it('does not submit delete form when user cancels', async () => {
+ const { service, deleteForm } = renderSaveBar();
+ const requestSubmit = vi.spyOn(deleteForm, 'requestSubmit').mockImplementation(() => {});
+
+ const deleteBtn = document.querySelectorAll('button[type="button"]')[0];
+ deleteBtn.click();
+ await vi.waitFor(() => expect(service.options).not.toBeNull());
+ service.settle(false);
+ await vi.waitFor(() => expect(service.options).toBeNull());
+
+ expect(requestSubmit).not.toHaveBeenCalled();
+ });
+});