import { afterEach, describe, expect, it } from 'vitest'; import { ProjectStore } from '@/app/store'; import { createStandardIntersectionProject } from '@/domain/model/factory'; import type { Project } from '@/domain/model/project'; import { meldungsverlauf } from '@/ui/feedback'; import { signalGroupsView } from '@/ui/views/signalGroupsView'; /** * Eine auf den bereits eingetragenen Wert begrenzte Eingabe aendert nichts * (Befund 59). * * Was der Anwender sonst erlebt: In der Signalgruppenansicht steht im Feld * "Fahrstreifen" die 1 - der Werkwert und zugleich die Untergrenze. Er traegt * eine 0 ein und tabbt weiter. Die Eingabe wird auf 1 begrenzt, im Feld steht * wieder 1 - und trotzdem meldet die Kopfzeile "ungespeicherte Änderungen", * "Rueckgaengig" wird mit dem Schritt "Fahrstreifenzahl geändert" aktiv, und * das Aenderungsdatum des Projekts ist neu. Letzteres wird als "Zuletzt * geändert" in die Planunterlage gedruckt. * * Geprueft wird ueber den Bedienweg: die echte Ansicht, das echte Zahlenfeld, * das echte `change`-Ereignis. Der Vergleich, der es abfaengt, sitzt in * `ProjectStore.update` - siehe tests/app/wertgleicheAenderung.test.ts. * * GEGEN DEN ALTSTAND schlaegt der erste Fall fehl. Der zweite haelt fest, dass * die Rueckmeldung an den Anwender bleibt - sie ist die einzige Auskunft * darueber, dass die Eingabe abgelehnt wurde -, der dritte ist die Gegenprobe * mit einer Zahl, die wirklich etwas aendert. */ const FESTES_DATUM = new Date('2026-01-01T00:00:00Z'); let aufraeumen: (() => void) | null = null; afterEach(() => { aufraeumen?.(); aufraeumen = null; }); function zeichne(project: Project): { wurzel: HTMLElement; store: ProjectStore } { const wurzel = document.createElement('div'); document.body.append(wurzel); const store = new ProjectStore(project); const abmelden = signalGroupsView.render(wurzel, { store, refresh: () => {}, navigate: () => {}, target: null, }); aufraeumen = () => { abmelden(); wurzel.remove(); }; return { wurzel, store }; } function fahrstreifenfeld(wurzel: HTMLElement, gruppe: string): HTMLInputElement { const feld = wurzel.querySelector( `input[aria-label="Anzahl der Fahrstreifen, ${gruppe}"]`, ); if (!feld) throw new Error(`Feld "Fahrstreifen" der Gruppe ${gruppe} fehlt.`); return feld; } function trageEin(feld: HTMLInputElement, text: string): void { feld.value = text; feld.dispatchEvent(new Event('change', { bubbles: true })); } describe('Auf den vorhandenen Wert begrenzte Eingabe', () => { it('laesst Aenderungsmerker, Rueckgaengig und Aenderungsdatum unberuehrt', () => { const { wurzel, store } = zeichne(createStandardIntersectionProject('Prueffall', FESTES_DATUM)); const feld = fahrstreifenfeld(wurzel, 'K1'); expect(feld.value).toBe('1'); const geaendertAm = store.getProject().meta.modifiedAt; trageEin(feld, '0'); // Die Begrenzung wirkt weiter - im Feld steht wieder der alte Wert. expect(feld.value).toBe('1'); expect(store.getState().dirty).toBe(false); expect(store.getState().canUndo).toBe(false); // Diese Zahl steht als "Zuletzt geändert" in der Planunterlage. expect(store.getProject().meta.modifiedAt).toBe(geaendertAm); }); it('meldet dem Anwender trotzdem, was mit seiner Eingabe geschehen ist', () => { const { wurzel } = zeichne(createStandardIntersectionProject('Prueffall', FESTES_DATUM)); trageEin(fahrstreifenfeld(wurzel, 'K1'), '0'); const meldung = meldungsverlauf()[0]!; expect(meldung.art).toBe('warnung'); expect(meldung.text).toContain('außerhalb des zulässigen Bereichs'); expect(meldung.text).toContain('Eingetragen wurde 1'); }); it('nimmt eine Eingabe an, die den Wert wirklich aendert', () => { const { wurzel, store } = zeichne(createStandardIntersectionProject('Prueffall', FESTES_DATUM)); trageEin(fahrstreifenfeld(wurzel, 'K1'), '2'); expect(store.getState().dirty).toBe(true); expect(store.getState().undoLabel).toBe('Fahrstreifenzahl geändert'); expect(store.getProject().signalGroups[0]!.lanes).toBe(2); }); });