import { describe, it, expect, vi, beforeEach } from 'vitest'; // Capture the beforeNavigate callback so tests can simulate navigation events let registeredBeforeNavigate: | ((nav: { cancel: () => void; to: { url: { href: string } } | null }) => void) | null = null; const mockGoto = vi.fn(); vi.mock('$app/navigation', () => ({ beforeNavigate: vi.fn((fn: typeof registeredBeforeNavigate) => { registeredBeforeNavigate = fn; }), goto: mockGoto })); const { createUnsavedWarning } = await import('./useUnsavedWarning.svelte'); function simulateNavigate(href: string | null = '/somewhere') { const cancel = vi.fn(); registeredBeforeNavigate?.({ cancel, to: href ? { url: { href } } : null }); return cancel; } beforeEach(() => { registeredBeforeNavigate = null; mockGoto.mockClear(); }); describe('createUnsavedWarning', () => { it('isDirty starts false', () => { const w = createUnsavedWarning(); expect(w.isDirty).toBe(false); }); it('markDirty sets isDirty to true', () => { const w = createUnsavedWarning(); w.markDirty(); expect(w.isDirty).toBe(true); }); it('markDirty hides any existing warning banner', () => { const w = createUnsavedWarning(); // Simulate a navigation event that showed the banner w.markDirty(); simulateNavigate(); expect(w.showUnsavedWarning).toBe(true); // Typing again should hide the banner (form input re-triggers markDirty) w.markDirty(); expect(w.showUnsavedWarning).toBe(false); }); it('beforeNavigate cancels and shows banner when dirty', () => { const w = createUnsavedWarning(); w.markDirty(); const cancel = simulateNavigate('/admin/users'); expect(cancel).toHaveBeenCalled(); expect(w.showUnsavedWarning).toBe(true); }); it('beforeNavigate stores the target URL', () => { const w = createUnsavedWarning(); w.markDirty(); simulateNavigate('/admin/users'); expect(w.discardTarget).toBe('/admin/users'); }); it('beforeNavigate does not cancel when not dirty', () => { createUnsavedWarning(); const cancel = simulateNavigate('/admin/users'); expect(cancel).not.toHaveBeenCalled(); }); it('discard resets state and navigates to target', () => { const w = createUnsavedWarning(); w.markDirty(); simulateNavigate('/admin/tags'); w.discard(); expect(w.isDirty).toBe(false); expect(w.showUnsavedWarning).toBe(false); expect(mockGoto).toHaveBeenCalledWith('/admin/tags'); }); it('clearOnSuccess resets isDirty and warning', () => { const w = createUnsavedWarning(); w.markDirty(); simulateNavigate('/somewhere'); w.clearOnSuccess(); expect(w.isDirty).toBe(false); expect(w.showUnsavedWarning).toBe(false); }); });