lsa-planer

LSA-Planer Professional – Planungssoftware für Lichtsignalanlagen nach RiLSA 2015 und § 45 StVO. EUPL-1.2.

/ tests ui sitzungNichtLesbar.test.ts

3,2 KB Rohdatei
tests/ui/sitzungNichtLesbar.test.ts — 87 Zeilen
1 import { beforeAll, describe, expect, it, vi } from 'vitest';
2 import { ladeSitzung, saveSession } from '@/services/storage';
3
4 /**
5 * Nach dem Befund "nicht-lesbar" darf kein Sitzungsstand geschrieben werden
6 * (Befund 3).
7 *
8 * Was der Anwender sonst erlebt: Die Lesetransaktion des Sitzungsspeichers
9 * scheitert einmal. Das Programm startet mit einem leeren Projekt und sagt
10 * woertlich "Er ist nicht verloren - ... Speichern Sie jetzt nichts, sondern
11 * starten Sie das Programm neu". Der Anwender befolgt das und minimiert oder
12 * schliesst das Fenster. Genau dabei loest `visibilitychange` auf `hidden` die
13 * Zwischenspeicherung aus, die das LEERE Projekt ueber den heilen Satz schreibt
14 * (`stand.put(satz, SCHLUESSEL_SITZUNG)`); die zugehoerigen Grossdaten - das
15 * Luftbild - werden anschliessend als unreferenziert weggeraeumt. Der Stand,
16 * den das Programm im selben Atemzug als "nicht verloren" bezeichnet, ist
17 * danach endgueltig weg; Wiederherstellungspunkte werden nirgends gelesen.
18 *
19 * Geprueft wird am echten Einstiegspunkt: `src/main.ts` wird eingelesen und
20 * startet damit die ganze Anwendung. Nur der Sitzungsspeicher ist ersetzt.
21 */
22
23 vi.mock('@/services/storage', async (importOriginal) => {
24 const echt = await importOriginal<typeof import('@/services/storage')>();
25 return {
26 ...echt,
27 ladeSitzung: vi.fn(),
28 saveSession: vi.fn(),
29 addRecoveryPoint: vi.fn(),
30 };
31 });
32
33 async function warte(ms = 0): Promise<void> {
34 await new Promise((fertig) => setTimeout(fertig, ms));
35 }
36
37 /** Sucht eine Schaltflaeche an ihrer Aufschrift oder ihrem Vorlesenamen. */
38 function schaltflaeche(text: string): HTMLButtonElement {
39 const treffer = [...document.querySelectorAll('button')].find(
40 (b) => b.textContent?.trim() === text || b.getAttribute('aria-label') === text,
41 );
42 if (!treffer) throw new Error(`Schaltflaeche "${text}" nicht gefunden.`);
43 return treffer;
44 }
45
46 beforeAll(async () => {
47 vi.mocked(ladeSitzung).mockResolvedValue({ art: 'nicht-lesbar' });
48 vi.mocked(saveSession).mockResolvedValue({ ok: true, message: '' });
49
50 document.body.replaceChildren();
51 const wurzel = document.createElement('div');
52 wurzel.id = 'anwendung';
53 document.body.append(wurzel);
54
55 await import('@/main');
56 await warte(20);
57 });
58
59 describe('Sitzungsstand nach dem Befund "nicht-lesbar"', () => {
60 it('schreibt beim Wechsel in den Hintergrund nichts ueber den heilen Satz', async () => {
61 Object.defineProperty(document, 'visibilityState', {
62 value: 'hidden',
63 configurable: true,
64 });
65 document.dispatchEvent(new Event('visibilitychange'));
66 await warte(10);
67
68 expect(saveSession).not.toHaveBeenCalled();
69
70 Object.defineProperty(document, 'visibilityState', {
71 value: 'visible',
72 configurable: true,
73 });
74 });
75
76 it('schreibt wieder, sobald der Anwender ueber "Neu" bewusst ein Projekt setzt', async () => {
77 schaltflaeche('Neu').click();
78 await warte(10);
79 schaltflaeche('Leeres Projekt').click();
80 await warte(10);
81
82 // Erst diese ausdrueckliche Entscheidung gibt den Sitzungsspeicher wieder
83 // frei - und belegt zugleich, dass der Schreibweg oben nicht aus einem
84 // anderen Grund still war.
85 expect(saveSession).toHaveBeenCalledTimes(1);
86 });
87 });