import { beforeAll, describe, expect, it, vi } from 'vitest'; import { createStandardIntersectionProject } from '@/domain/model/factory'; import { ladeSitzung, saveSession } from '@/services/storage'; /** * Ein wiederhergestellter Sitzungsstand ist nicht "gespeichert" (Befund 20). * * Was der Anwender sonst erlebt: Er legt ein Projekt an, erfasst Signalgruppen * und Konflikte und speichert es NICHT in eine Datei. Das Programm bricht ab * oder wird geschlossen. Beim naechsten Start ist der Stand wieder da - und * gilt sofort als gespeichert, weil `ProjectStore` mit `dirty = false` beginnt * und der Wiederanlauf daran nichts aendert. Strg+N laeuft daraufhin ohne * Rueckfrage durch `confirmDiscard`, `store.replace` leert die * Rueckgaengig-Kette und der anschliessende `flush()` ueberschreibt den einen * Sitzungssatz. Die Handarbeit eines ganzen Knotenpunkts ist damit weg; * Wiederherstellungspunkte werden in der Oberflaeche nirgends angeboten. * * Geprueft wird am echten Einstiegspunkt: `src/main.ts` wird eingelesen und * startet die ganze Anwendung; nur der Sitzungsspeicher ist ersetzt. */ vi.mock('@/services/storage', async (importOriginal) => { const echt = await importOriginal(); return { ...echt, ladeSitzung: vi.fn(), saveSession: vi.fn(), addRecoveryPoint: vi.fn(), }; }); async function warte(ms = 0): Promise { await new Promise((fertig) => setTimeout(fertig, ms)); } /** Die Ueberschriften aller gerade offenen Fenster. */ function offeneFenster(): string[] { return [...document.querySelectorAll('.dialog-hintergrund h2')].map( (h) => h.textContent?.trim() ?? '', ); } function schaltflaeche(text: string): HTMLButtonElement { const treffer = [...document.querySelectorAll('button')].find( (b) => b.textContent?.trim() === text || b.getAttribute('aria-label') === text, ); if (!treffer) throw new Error(`Schaltflaeche "${text}" nicht gefunden.`); return treffer; } function druecke(taste: string): void { window.dispatchEvent( new KeyboardEvent('keydown', { key: taste, ctrlKey: true, bubbles: true, cancelable: true }), ); } beforeAll(async () => { vi.mocked(ladeSitzung).mockResolvedValue({ art: 'geladen', stand: { project: createStandardIntersectionProject(), issues: [], repaired: false, migrated: false, sourceVersion: '13', intergreenComparison: [], }, }); vi.mocked(saveSession).mockResolvedValue({ ok: true, message: '' }); document.body.replaceChildren(); const wurzel = document.createElement('div'); wurzel.id = 'anwendung'; document.body.append(wurzel); await import('@/main'); await warte(20); }); describe('Wiederhergestellter Sitzungsstand', () => { it('fragt vor "Neu" zurueck, weil er in keiner Datei steht', async () => { druecke('n'); await warte(10); // Ohne die Rueckfrage stuende hier sofort die Vorlagenauswahl - und mit dem // ersten Klick darin waere der wiederhergestellte Stand fort. expect(offeneFenster()).toEqual(['Ungespeicherte Änderungen']); }); it('laesst den Stand nach "Abbrechen" unangetastet', async () => { schaltflaeche('Abbrechen').click(); await warte(10); expect(offeneFenster()).toEqual([]); expect(saveSession).not.toHaveBeenCalled(); }); });