// @vitest-environment node /** * Der Wächter über die laufende Prüfung. * * Er entscheidet, ob das Fenster beim Schließen nachfragt. Bis Fassung 0.24.1 * hatte er **keinen einzigen Test** – weder hier noch in Playwright –, obwohl * an ihm zwei gegenläufige Fehler hängen: Vergisst er zu früh, geht ein * Prüfungsbogen ohne Rückfrage verloren; vergisst er zu spät, hängt das * Fenster für immer an einer Frage zu einer Prüfung, die es nicht mehr gibt. * * Geprüft wird gegen Attrappen von `WebContents` und `BrowserWindow`: Der * Wächter benutzt von beiden nur `id` und `isDestroyed()`, und ein echtes * Electron-Fenster für diese Rechnung zu starten wäre teuer ohne Gewinn. */ import { beforeEach, describe, expect, it } from 'vitest'; import type { BrowserWindow, WebContents } from 'electron'; import { laeuftPruefung, laufMelden, laufVergessen, laufwaechterLeeren, } from '../src/main/laufwaechter'; /** Nur die beiden Felder, die der Wächter anfasst. */ function inhalt(id: number, zerstoert = false): WebContents { return { id, isDestroyed: () => zerstoert } as unknown as WebContents; } function fenster(webContents: WebContents): BrowserWindow { return { webContents } as unknown as BrowserWindow; } beforeEach(() => { laufwaechterLeeren(); }); describe('Laufwächter', () => { it('meldet ohne jede Meldung keine laufende Prüfung', () => { expect(laeuftPruefung(fenster(inhalt(1)))).toBe(false); }); it('merkt sich eine laufende Prüfung', () => { const eins = inhalt(1); laufMelden(eins, true); expect(laeuftPruefung(fenster(eins))).toBe(true); }); /* Der Renderer schickt seinen Zustand auch beim Aufbau – also `false` nach einem Neuladen. Ein Wächter, der nur Kanten meldete, bliebe hängen. */ it('nimmt den Merker auf eine Meldung „läuft nicht“ zurück', () => { const eins = inhalt(1); laufMelden(eins, true); laufMelden(eins, false); expect(laeuftPruefung(fenster(eins))).toBe(false); }); it('verträgt dieselbe Meldung mehrfach', () => { const eins = inhalt(1); laufMelden(eins, true); laufMelden(eins, true); laufMelden(eins, false); expect(laeuftPruefung(fenster(eins))).toBe(false); }); it('hält die Fenster auseinander', () => { /* Zwei Fenster sind erreichbar – die Hilfe ist zwar ein Dialog, aber ein zweiter Programmstart legt ein eigenes an. Der Merker des einen darf das andere nicht betreffen. */ const eins = inhalt(1); const zwei = inhalt(2); laufMelden(eins, true); expect(laeuftPruefung(fenster(eins))).toBe(true); expect(laeuftPruefung(fenster(zwei))).toBe(false); }); it('vergisst den Merker bei neuem Dokument oder Absturz', () => { const eins = inhalt(1); laufMelden(eins, true); laufVergessen(eins); expect(laeuftPruefung(fenster(eins))).toBe(false); }); /* Die zweite, unabhängige Sperre: Ein zerstörtes `webContents` liefert niemals „es läuft eine Prüfung“. Ohne sie könnte ein abgestürzter Renderer das Fenster unschließbar machen – und der Nutzer säße vor einem Fenster, das weder arbeitet noch zugeht. */ it('meldet für ein zerstörtes Fenster nie eine laufende Prüfung', () => { const eins = inhalt(1); laufMelden(eins, true); expect(laeuftPruefung(fenster(inhalt(1, true)))).toBe(false); }); it('räumt mit „leeren“ alles weg', () => { laufMelden(inhalt(1), true); laufMelden(inhalt(2), true); laufwaechterLeeren(); expect(laeuftPruefung(fenster(inhalt(1)))).toBe(false); expect(laeuftPruefung(fenster(inhalt(2)))).toBe(false); }); });