import { describe, expect, it } from 'vitest'; import { createEmptyProject, createStandardIntersectionProject, istUnberuehrt, } from '@/domain/model/factory'; import { parseProject } from '@/domain/model/schema'; const DATUM = new Date('2026-01-01T00:00:00Z'); /* * `istUnberuehrt` entscheidet, ob ein wiederhergestellter Sitzungsstand als * ungespeicherte Arbeit gilt (Befund 20, siehe src/main.ts). Faellt die Antwort * faelschlich auf "unberuehrt", verschwindet der Schutz vor dem Verwerfen; faellt * sie faelschlich auf "beruehrt", kommt bei jedem zweiten Start eine Rueckfrage * ueber eine Arbeit, die es nie gab. * * Der gefaehrliche der beiden Irrtuemer ist der erste. Die Faelle unten pruefen * ihn deshalb Feld fuer Feld: Jede einzelne Eingabe muss reichen. */ describe('Ist ein Projekt unberuehrt', () => { it('sagt ja zu einem frisch angelegten Projekt', () => { expect(istUnberuehrt(createEmptyProject())).toBe(true); }); it('stoert sich nicht an Kennung und Zeitstempeln', () => { // Sie fallen bei jedem Anlegen anders aus und sind keine Eingabe. const frueher = createEmptyProject('Neues Projekt', DATUM); const jetzt = createEmptyProject(); expect(frueher.id).not.toBe(jetzt.id); expect(istUnberuehrt(frueher)).toBe(true); }); it('sagt nein zu einem Projekt mit Signalgruppen', () => { expect(istUnberuehrt(createStandardIntersectionProject('Knoten', DATUM))).toBe(false); }); it.each([ [ 'Projektbezeichnung', (p: ReturnType) => ({ ...p, meta: { ...p.meta, name: 'Bahnhofstrasse' }, }), ], [ 'Auftraggeber', (p: ReturnType) => ({ ...p, meta: { ...p.meta, client: 'Stadt Musterhausen' }, }), ], [ 'Knotenpunktbezeichnung', (p: ReturnType) => ({ ...p, intersection: { ...p.intersection, name: 'Hauptstrasse / Bahnhofstrasse' }, }), ], [ 'zulaessige Hoechstgeschwindigkeit', (p: ReturnType) => ({ ...p, intersection: { ...p.intersection, vZul: 30 }, }), ], [ 'Anlagenart', (p: ReturnType) => ({ ...p, anlagenart: 'fussgaengerschutzanlage' as const, }), ], [ 'Umlaufzeit von Hand', (p: ReturnType) => ({ ...p, program: { ...p.program, manualCycleTime: 60 }, }), ], [ 'Bewertungsverfahren', (p: ReturnType) => ({ ...p, settings: { ...p.settings, serviceLevelScale: 'HCM' as const }, }), ], ])('sagt nein, sobald nur die %s eingetragen ist', (_was, aendere) => { expect(istUnberuehrt(aendere(createEmptyProject()))).toBe(false); }); it('sagt ja zu einem leeren Projekt, das durch das Einlesen gegangen ist', () => { /* * Der eigentliche Weg: Der Sitzungsspeicher gibt das Projekt nicht als * dasselbe Objekt zurueck, sondern als eingelesene Fassung. Baut * `parseProject` die Felder in anderer Reihenfolge auf als * `createEmptyProject`, muss der Vergleich das aushalten - sonst gaelte * jeder Wiederanlauf als beruehrt, und die Antwort waere zufaellig richtig. */ const eingelesen = parseProject( JSON.parse(JSON.stringify(createEmptyProject('Neues Projekt', DATUM))), DATUM, ); expect(eingelesen.issues.filter((i) => i.severity === 'fehler')).toEqual([]); expect(istUnberuehrt(eingelesen.project)).toBe(true); }); });