lsa-planer

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

/ tests app neuesProjektUngespeichert.test.ts

3,2 KB Rohdatei
tests/app/neuesProjektUngespeichert.test.ts — 77 Zeilen
1 import { describe, expect, it } from 'vitest';
2 import { ProjectStore } from '@/app/store';
3 import { createEmptyProject, createStandardIntersectionProject } from '@/domain/model/factory';
4
5 /**
6 * Ein neu gesetzter Stand ohne Datei ist nicht "gespeichert" (Befund 38).
7 *
8 * `replace()` loeschte den Aenderungsmerker bedingungslos - auch dort, wo kein
9 * Dateipfad mitkam. Nach "Neu" > "Gefuehrter Einstieg" steht das Ergebnis von
10 * drei bis vier beantworteten Fragen samt Signalgruppen, Konflikten und Phasen
11 * in keiner Datei, die Kopfzeile meldete trotzdem "gespeichert", und die
12 * Waechter vor dem Verwerfen ("Neu", "Öffnen", Fenster schliessen) haengen
13 * alle an diesem Merker. Ein zweites Strg+N lief deshalb ohne Rueckfrage
14 * durch, `replace` leerte die Rueckgaengig-Kette, und der anschliessende
15 * `flush()` schrieb ueber den einen Sitzungssatz.
16 *
17 * Dieselbe Lage war fuer den Wiederanlauf aus dem Sitzungsspeicher bereits
18 * behoben (src/main.ts, `store.markDirty()`); der zweite Weg zu einem Projekt
19 * ohne Datei hatte sie nicht.
20 *
21 * GEGEN DEN ALTSTAND schlagen der erste und der vierte Fall fehl (dirty war
22 * false; die Benachrichtigung trug false statt true). Der zweite und der dritte
23 * halten die Grenzen der Regel fest und bestehen auch dort - sie sind der
24 * Nachweis, dass die Behebung nicht ueber das Ziel hinausschiesst.
25 */
26
27 const FESTES_DATUM = new Date('2026-01-01T00:00:00Z');
28
29 describe('Neu gesetzter Stand ohne Datei', () => {
30 it('gilt als ungespeichert, sobald etwas darin steht', () => {
31 const store = new ProjectStore(createEmptyProject());
32
33 // Genau das, was "Neu" mit dem Ergebnis des gefuehrten Einstiegs tut:
34 // ersetzen ohne Dateipfad.
35 store.replace(createStandardIntersectionProject('Gefuehrter Einstieg', FESTES_DATUM));
36
37 expect(store.getState().dirty).toBe(true);
38 expect(store.getState().filePath).toBe(null);
39 });
40
41 it('gilt als gespeichert, wenn ein Dateipfad mitkommt', () => {
42 const store = new ProjectStore(createEmptyProject());
43
44 store.replace(
45 createStandardIntersectionProject('Geoeffnet', FESTES_DATUM),
46 'C:/tmp/knotenpunkt.lsap',
47 );
48
49 // Beim Oeffnen steht der Stand in einer Datei - da ist nichts ungesichert.
50 expect(store.getState().dirty).toBe(false);
51 expect(store.getState().filePath).toBe('C:/tmp/knotenpunkt.lsap');
52 });
53
54 it('laesst ein unberuehrtes Projekt sauber', () => {
55 const store = new ProjectStore(createStandardIntersectionProject('Vorher', FESTES_DATUM));
56
57 store.replace(createEmptyProject());
58
59 // "Neu" > "Leeres Projekt": Es gibt keine Arbeit, die verloren gehen
60 // koennte. Eine Rueckfrage, die immer kommt, schuetzt nichts.
61 expect(store.getState().dirty).toBe(false);
62 });
63
64 it('meldet den Merker in derselben Benachrichtigung wie den Stand', () => {
65 const store = new ProjectStore(createEmptyProject());
66 const gesehen: boolean[] = [];
67 store.subscribe((state) => {
68 gesehen.push(state.dirty);
69 });
70
71 store.replace(createStandardIntersectionProject('Assistent', FESTES_DATUM));
72
73 // Kopfzeile, Fenstertitel und Statusleiste lesen genau diesen Zustand;
74 // ein nachgereichter zweiter Merker liesse sie kurz etwas anderes sagen.
75 expect(gesehen).toEqual([true]);
76 });
77 });