lsa-planer

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

/ tests ui einlesemeldungen.test.ts

4,8 KB Rohdatei
tests/ui/einlesemeldungen.test.ts — 124 Zeilen
1 import { readFileSync } from 'node:fs';
2 import path from 'node:path';
3 import { beforeAll, describe, expect, it, vi } from 'vitest';
4 import { createStandardIntersectionProject } from '@/domain/model/factory';
5 import { ladeSitzung, saveSession } from '@/services/storage';
6
7 /**
8 * Einlesemeldungen erreichen den Bearbeiter auch auf dem Sitzungsweg
9 * (zweiter Anteil von Befund 12).
10 *
11 * Beim Oeffnen einer Datei zeigt `showImportIssues` jede einzelne Meldung mit
12 * Art, Bereich und Wortlaut. Der Wiederanlauf aus dem Sitzungsspeicher nannte
13 * dagegen nur die ANZAHL - "(1 Hinweise beim Einlesen)". Gerade der Wortlaut
14 * ist aber die Auskunft: Wurde ein Raeumweg beim Einlesen auf den zulaessigen
15 * Hoechstwert der Anlagenart begrenzt, aendert das die Zwischenzeiten und damit
16 * den ganzen Signalzeitenplan. Wer nur eine Zahl liest, erfaehrt nie, welcher
17 * Wert angefasst wurde.
18 *
19 * Geprueft wird am echten Einstiegspunkt: `src/main.ts` wird eingelesen und
20 * startet die ganze Anwendung; nur der Sitzungsspeicher ist ersetzt.
21 */
22
23 const MELDUNG =
24 'Räumweg (Anlagenart Fußgängerschutzanlage) liegt mit 400 über dem zulässigen ' +
25 'Höchstwert 100; der Wert wurde begrenzt';
26
27 vi.mock('@/services/storage', async (importOriginal) => {
28 const echt = await importOriginal<typeof import('@/services/storage')>();
29 return {
30 ...echt,
31 ladeSitzung: vi.fn(),
32 saveSession: vi.fn(),
33 addRecoveryPoint: vi.fn(),
34 };
35 });
36
37 async function warte(ms = 0): Promise<void> {
38 await new Promise((fertig) => setTimeout(fertig, ms));
39 }
40
41 /** Die Ueberschriften aller gerade offenen Fenster. */
42 function offeneFenster(): string[] {
43 return [...document.querySelectorAll('.dialog-hintergrund h2')].map(
44 (h) => h.textContent?.trim() ?? '',
45 );
46 }
47
48 beforeAll(async () => {
49 vi.mocked(ladeSitzung).mockResolvedValue({
50 art: 'geladen',
51 stand: {
52 project: createStandardIntersectionProject(),
53 issues: [{ path: 'signalGroups[0].clearingPath', severity: 'warnung', message: MELDUNG }],
54 repaired: true,
55 migrated: false,
56 sourceVersion: '13',
57 intergreenComparison: [],
58 },
59 });
60 vi.mocked(saveSession).mockResolvedValue({ ok: true, message: '' });
61
62 localStorage.clear();
63 document.body.replaceChildren();
64 const wurzel = document.createElement('div');
65 wurzel.id = 'anwendung';
66 document.body.append(wurzel);
67
68 await import('@/main');
69 // Laenger als die 400 ms, mit denen der Wiederanlauf seine Kurzmeldungen
70 // nachreicht - sonst waere der alte Zaehlhinweis noch gar nicht da.
71 await warte(500);
72 });
73
74 describe('Einlesemeldungen beim Wiederanlauf', () => {
75 it('zeigt dieselbe Aufstellung wie der Öffnen-Weg', () => {
76 expect(offeneFenster()).toContain('Hinweise zum Import');
77 });
78
79 it('nennt den Wortlaut der Meldung, nicht nur ihre Anzahl', () => {
80 const fenster = document.querySelector('.dialog-hintergrund');
81 expect(fenster?.textContent).toContain(MELDUNG);
82 });
83 });
84
85 /**
86 * WANN die Aufstellung erscheint, wird an einer Stelle entschieden.
87 *
88 * Seit der Sitzungsweg dieselbe Aufstellung zeigt wie der Oeffnen-Weg, stand
89 * die Bedingung "Meldungen ODER Gegenueberstellung" wortgleich an beiden
90 * Aufrufstellen. Die Begruendung fuer ihren zweiten Teil - bei einem
91 * uebernommenen 4.x-Projekt ist die Gegenueberstellung die wichtigste Auskunft,
92 * auch wenn sonst nichts auffiel - stand nur an einer davon. Wer die Bedingung
93 * spaeter erweitert, findet die zweite Stelle nicht, und die beiden Wege zeigen
94 * wieder Unterschiedliches. Deshalb steht die Entscheidung an einer Stelle.
95 *
96 * Am Quelltext festgehalten und nicht am Verhalten: Beide Fassungen zeigen
97 * heute dasselbe Fenster - die Doppelung ist kein Unterschied im Ergebnis,
98 * sondern die Anlage dafuer, dass einer entsteht. Dieselbe Ueberlegung traegt
99 * `tests/ui/stilblattZusagen.test.ts`.
100 */
101 describe('Die Entscheidung über die Aufstellung "Hinweise zum Import"', () => {
102 const quelltext = (): string =>
103 readFileSync(path.resolve(__dirname, '..', '..', 'src', 'main.ts'), 'utf8');
104
105 it('steht an keiner Aufrufstelle mehr', () => {
106 const stellen = quelltext().split('intergreenComparison.length').length - 1;
107 expect(
108 stellen,
109 'Eine Aufrufstelle entscheidet wieder selbst, ob die Aufstellung erscheint.',
110 ).toBe(0);
111 });
112
113 it('steht in showImportIssues selbst', () => {
114 const text = quelltext();
115 const beginn = text.indexOf('function showImportIssues(');
116 expect(beginn, 'showImportIssues nicht gefunden').toBeGreaterThanOrEqual(0);
117 const bisFenster = text.slice(beginn, text.indexOf('new Panel(', beginn));
118 // Vor dem ersten Fenster steht der fruehe Ruecksprung, und er wiegt beides
119 // ab: die Meldungen und die Gegenueberstellung.
120 expect(bisFenster).toContain('issues.length');
121 expect(bisFenster).toContain('vergleich.length');
122 expect(bisFenster).toContain('return;');
123 });
124 });