lsa-planer
LSA-Planer Professional – Planungssoftware für Lichtsignalanlagen nach RiLSA 2015 und § 45 StVO. EUPL-1.2.
/ tests domain projektUnberuehrt.test.ts
| 1 | import { describe, expect, it } from 'vitest'; |
| 2 | import { |
| 3 | createEmptyProject, |
| 4 | createStandardIntersectionProject, |
| 5 | istUnberuehrt, |
| 6 | } from '@/domain/model/factory'; |
| 7 | import { parseProject } from '@/domain/model/schema'; |
| 8 | |
| 9 | const DATUM = new Date('2026-01-01T00:00:00Z'); |
| 10 | |
| 11 | /* |
| 12 | * `istUnberuehrt` entscheidet, ob ein wiederhergestellter Sitzungsstand als |
| 13 | * ungespeicherte Arbeit gilt (Befund 20, siehe src/main.ts). Faellt die Antwort |
| 14 | * faelschlich auf "unberuehrt", verschwindet der Schutz vor dem Verwerfen; faellt |
| 15 | * sie faelschlich auf "beruehrt", kommt bei jedem zweiten Start eine Rueckfrage |
| 16 | * ueber eine Arbeit, die es nie gab. |
| 17 | * |
| 18 | * Der gefaehrliche der beiden Irrtuemer ist der erste. Die Faelle unten pruefen |
| 19 | * ihn deshalb Feld fuer Feld: Jede einzelne Eingabe muss reichen. |
| 20 | */ |
| 21 | |
| 22 | describe('Ist ein Projekt unberuehrt', () => { |
| 23 | it('sagt ja zu einem frisch angelegten Projekt', () => { |
| 24 | expect(istUnberuehrt(createEmptyProject())).toBe(true); |
| 25 | }); |
| 26 | |
| 27 | it('stoert sich nicht an Kennung und Zeitstempeln', () => { |
| 28 | // Sie fallen bei jedem Anlegen anders aus und sind keine Eingabe. |
| 29 | const frueher = createEmptyProject('Neues Projekt', DATUM); |
| 30 | const jetzt = createEmptyProject(); |
| 31 | expect(frueher.id).not.toBe(jetzt.id); |
| 32 | expect(istUnberuehrt(frueher)).toBe(true); |
| 33 | }); |
| 34 | |
| 35 | it('sagt nein zu einem Projekt mit Signalgruppen', () => { |
| 36 | expect(istUnberuehrt(createStandardIntersectionProject('Knoten', DATUM))).toBe(false); |
| 37 | }); |
| 38 | |
| 39 | it.each([ |
| 40 | [ |
| 41 | 'Projektbezeichnung', |
| 42 | (p: ReturnType<typeof createEmptyProject>) => ({ |
| 43 | ...p, |
| 44 | meta: { ...p.meta, name: 'Bahnhofstrasse' }, |
| 45 | }), |
| 46 | ], |
| 47 | [ |
| 48 | 'Auftraggeber', |
| 49 | (p: ReturnType<typeof createEmptyProject>) => ({ |
| 50 | ...p, |
| 51 | meta: { ...p.meta, client: 'Stadt Musterhausen' }, |
| 52 | }), |
| 53 | ], |
| 54 | [ |
| 55 | 'Knotenpunktbezeichnung', |
| 56 | (p: ReturnType<typeof createEmptyProject>) => ({ |
| 57 | ...p, |
| 58 | intersection: { ...p.intersection, name: 'Hauptstrasse / Bahnhofstrasse' }, |
| 59 | }), |
| 60 | ], |
| 61 | [ |
| 62 | 'zulaessige Hoechstgeschwindigkeit', |
| 63 | (p: ReturnType<typeof createEmptyProject>) => ({ |
| 64 | ...p, |
| 65 | intersection: { ...p.intersection, vZul: 30 }, |
| 66 | }), |
| 67 | ], |
| 68 | [ |
| 69 | 'Anlagenart', |
| 70 | (p: ReturnType<typeof createEmptyProject>) => ({ |
| 71 | ...p, |
| 72 | anlagenart: 'fussgaengerschutzanlage' as const, |
| 73 | }), |
| 74 | ], |
| 75 | [ |
| 76 | 'Umlaufzeit von Hand', |
| 77 | (p: ReturnType<typeof createEmptyProject>) => ({ |
| 78 | ...p, |
| 79 | program: { ...p.program, manualCycleTime: 60 }, |
| 80 | }), |
| 81 | ], |
| 82 | [ |
| 83 | 'Bewertungsverfahren', |
| 84 | (p: ReturnType<typeof createEmptyProject>) => ({ |
| 85 | ...p, |
| 86 | settings: { ...p.settings, serviceLevelScale: 'HCM' as const }, |
| 87 | }), |
| 88 | ], |
| 89 | ])('sagt nein, sobald nur die %s eingetragen ist', (_was, aendere) => { |
| 90 | expect(istUnberuehrt(aendere(createEmptyProject()))).toBe(false); |
| 91 | }); |
| 92 | |
| 93 | it('sagt ja zu einem leeren Projekt, das durch das Einlesen gegangen ist', () => { |
| 94 | /* |
| 95 | * Der eigentliche Weg: Der Sitzungsspeicher gibt das Projekt nicht als |
| 96 | * dasselbe Objekt zurueck, sondern als eingelesene Fassung. Baut |
| 97 | * `parseProject` die Felder in anderer Reihenfolge auf als |
| 98 | * `createEmptyProject`, muss der Vergleich das aushalten - sonst gaelte |
| 99 | * jeder Wiederanlauf als beruehrt, und die Antwort waere zufaellig richtig. |
| 100 | */ |
| 101 | const eingelesen = parseProject( |
| 102 | JSON.parse(JSON.stringify(createEmptyProject('Neues Projekt', DATUM))), |
| 103 | DATUM, |
| 104 | ); |
| 105 | expect(eingelesen.issues.filter((i) => i.severity === 'fehler')).toEqual([]); |
| 106 | expect(istUnberuehrt(eingelesen.project)).toBe(true); |
| 107 | }); |
| 108 | }); |