import { beforeAll, describe, expect, it, vi } from 'vitest'; import { ladeSitzung, saveSession } from '@/services/storage'; /** * Befund 9 zur Fassung 5.9.0. * * Der Sitzungsbefund unterscheidet ausdruecklich, ob ein beschaedigter Satz * beiseitegelegt werden konnte. Scheitert das - etwa weil das Kontingent durch * ein 20-MB-Luftbild und fuenf Wiederherstellungspunkte erschoepft ist -, steht * der beschaedigte Satz weiterhin unter dem Sitzungsschluessel, und der * Quelltext sagt daneben zu: "Dann bleibt er eben liegen und wird beim * naechsten Start erneut geprueft." * * Genau das hielt das Programm nicht ein. `restoreSession` reichte * `beiseitegelegt` nur in den Meldungstext, nicht in den Rueckgabewert, und * `boot()` sperrte das Schreiben ausschliesslich nach 'nicht-lesbar'. Der erste * Sichtwechsel - Minimieren oder Schliessen, also genau der Weg, zu dem die * Meldung auffordert - schrieb das leere Startprojekt ueber den beschaedigten * Satz; die anschliessende Grossdatenaufraeumung nahm das Luftbild mit, sobald * kein Wiederherstellungspunkt mehr darauf zeigte. * * Fuer 'nicht-lesbar' ist dieselbe Sperre in 5.9.0 eingefuehrt worden; der * gleich gelagerte zweite Fall wurde dabei uebersehen. * * 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)); } 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; } beforeAll(async () => { vi.mocked(ladeSitzung).mockResolvedValue({ art: 'beschaedigt', beiseitegelegt: false }); 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('Beschädigter Sitzungssatz, der nicht beiseitegelegt werden konnte', () => { it('schreibt beim Wechsel in den Hintergrund nichts darüber', async () => { Object.defineProperty(document, 'visibilityState', { value: 'hidden', configurable: true }); document.dispatchEvent(new Event('visibilitychange')); await warte(10); expect( saveSession, 'Das leere Startprojekt wurde ueber den beschaedigten Satz geschrieben', ).not.toHaveBeenCalled(); Object.defineProperty(document, 'visibilityState', { value: 'visible', configurable: true }); }); it('schreibt wieder, sobald der Anwender über "Neu" bewusst ein Projekt setzt', async () => { schaltflaeche('Neu').click(); await warte(10); schaltflaeche('Leeres Projekt').click(); await warte(10); // Erst diese ausdrueckliche Entscheidung gibt den Sitzungsspeicher wieder // frei - und belegt zugleich, dass der Schreibweg oben nicht aus einem // anderen Grund still war. expect(saveSession).toHaveBeenCalledTimes(1); }); });