import { describe, expect, it } from 'vitest'; import * as actions from '@/app/actions'; import type { AppState } from '@/app/store'; import type { Project } from '@/domain/model/project'; import { buildSignalPlan } from '@/domain/plan/signalPlan'; import { validateProject } from '@/domain/validation'; import { ASSISTENT_VORGABE, projektAusAngaben } from '@/ui/assistent'; import { naechsterSchritt } from '@/ui/naechsterSchritt'; /** * Befund 48 zur Fassung 5.8.0. * * Der Fuehrungshinweis ueber jeder Ansicht zaehlte fuer den Arbeitsschritt * "Verkehrsstaerken eintragen" die EINTRAEGE in `project.demands`, nicht die * Eintraege mit einer wirksamen Zahl. `setDemand` legt bei fehlendem Eintrag * aber `volume: 0` an - wer nur den SV-Anteil oder den Lastzuganteil ausfuellt * oder in das Verkehrsstaerkefeld ausdruecklich 0 tippt, hat danach einen * Eintrag ohne Verkehrsstaerke. Der Schritt galt damit als erledigt, waehrend * derselbe Programmlauf im Pruefbericht "Es liegen keine Verkehrsstaerken vor" * meldet und die Freigabezeiten gleichmaessig verteilt. * * Der Fachkern behandelt `volume <= 0` durchgaengig als "keine Angabe" * (rules.ts, greenSplit.ts); die Fuehrung tut es jetzt auch. */ const FESTES_DATUM = new Date('2026-01-01T00:00:00Z'); function grundprojekt(name: string): Project { const p = projektAusAngaben( { ...ASSISTENT_VORGABE, fussgaenger: true, rad: true }, name, FESTES_DATUM, ); return { ...p, meta: { ...p.meta, name: 'x', projectNumber: '1', client: 'c', planner: 'p', location: 'l' }, }; } function zustand(project: Project): AppState { const plan = buildSignalPlan(project); return { project, plan, report: validateProject(project, plan, FESTES_DATUM), dirty: false, filePath: null, canUndo: false, canRedo: false, undoLabel: null, redoLabel: null, }; } function ersteKfzGruppe(project: Project): string { const gruppe = project.signalGroups.find((g) => g.mode === 'kfz'); expect(gruppe, 'Vorbedingung: das Vorgabeprojekt hat eine Kfz-Gruppe').toBeDefined(); return gruppe!.id; } describe('Fuehrungshinweis: Verkehrsstaerke 0 ist keine Verkehrsstaerke', () => { it('Vorbedingung: das Vorgabeprojekt des Assistenten hat keine Verkehrsstaerken und verlangt sie', () => { const p = grundprojekt('Ohne Zaehlung'); expect(p.demands).toEqual([]); const state = zustand(p); expect(state.report.errorCount, 'Vorbedingung: kein Fehler im Pruefbericht').toBe(0); expect(naechsterSchritt(state).text).toContain( 'Verkehrsstärken der Kfz- und ÖPNV-Signalgruppen', ); }); /* * Ausloeser 1: Spalte "SV-Anteil" in der Ansicht "Signalgruppen". Sie ruft * `setDemand` mit nur `heavyVehicleShare`; der dabei angelegte Eintrag traegt * `volume: 0`. */ it('verlangt weiterhin Verkehrsstaerken, wenn nur der SV-Anteil einer Kfz-Gruppe ausgefuellt ist', () => { const p = grundprojekt('Nur SV-Anteil'); const kfz = ersteKfzGruppe(p); const mitAnteil = actions.setDemand(p, kfz, { heavyVehicleShare: 0.05 }); expect(mitAnteil.demands.length, 'Vorbedingung: setDemand hat einen Eintrag angelegt').toBe(1); expect(mitAnteil.demands[0]?.volume, 'Vorbedingung: der Eintrag traegt volume 0').toBe(0); const state = zustand(mitAnteil); expect(state.report.errorCount, 'Vorbedingung: kein Fehler im Pruefbericht').toBe(0); const schritt = naechsterSchritt(state); expect(schritt.text).toContain('Verkehrsstärken der Kfz- und ÖPNV-Signalgruppen'); expect(schritt.ansicht).toBe('signalgruppen'); }); /* * Ausloeser 2: eine ausdruecklich getippte 0 im Feld "Verkehrsstaerke". Das * Feld gibt sie unveraendert weiter. * * Ein LEERES Feld entfernt den Eintrag seit der Behebung von Befund 58 nur * noch dann, wenn ausser der Verkehrsstaerke nichts an dem Strom erfasst ist; * steht daneben ein Schwerverkehrs- oder Lastzuganteil, bleibt der Datensatz * mit `volume: 0` stehen - also in genau dem Zustand, den dieser Fall prueft * (tests/ui/verkehrsstaerkeLeeren.test.ts). Der Assistent nennt * beide Wege "noch unbekannt". */ it('verlangt weiterhin Verkehrsstaerken, wenn in das Verkehrsstaerkefeld einer Kfz-Gruppe 0 eingetragen ist', () => { const p = grundprojekt('Getippte Null'); const kfz = ersteKfzGruppe(p); const mitNull = actions.setDemand(p, kfz, { volume: 0 }); expect(mitNull.demands.length).toBe(1); expect(mitNull.demands[0]?.volume).toBe(0); const state = zustand(mitNull); expect(state.report.errorCount, 'Vorbedingung: kein Fehler im Pruefbericht').toBe(0); const schritt = naechsterSchritt(state); expect(schritt.text).toContain('Verkehrsstärken der Kfz- und ÖPNV-Signalgruppen'); expect(schritt.ansicht).toBe('signalgruppen'); }); /* * Ausloeser 3: Spalte "Lastzuege am SV". `setLastzugAnteil` legt bei * fehlendem Eintrag ebenfalls einen mit `volume: 0` an. */ it('verlangt weiterhin Verkehrsstaerken, wenn nur der Lastzuganteil einer Kfz-Gruppe eingetragen ist', () => { const p = grundprojekt('Nur Lastzuege'); const kfz = ersteKfzGruppe(p); const mitLastzug = actions.setLastzugAnteil(p, kfz, 0.2); expect(mitLastzug.demands.length).toBe(1); expect(mitLastzug.demands[0]?.volume).toBe(0); const state = zustand(mitLastzug); expect(state.report.errorCount, 'Vorbedingung: kein Fehler im Pruefbericht').toBe(0); const schritt = naechsterSchritt(state); expect(schritt.text).toContain('Verkehrsstärken der Kfz- und ÖPNV-Signalgruppen'); expect(schritt.ansicht).toBe('signalgruppen'); }); /* * Gegenprobe: Eine wirksame Zahl an EINER Kfz-Gruppe erledigt den Schritt * weiterhin - die Behebung darf ihn nicht dauerhaft stehen lassen. */ it('erledigt den Schritt, sobald eine Kfz-Gruppe eine Verkehrsstaerke groesser 0 hat', () => { const p = grundprojekt('Eine Zahl'); const kfz = ersteKfzGruppe(p); const mitZahl = actions.setDemand(p, kfz, { volume: 400, heavyVehicleShare: 0.05 }); const state = zustand(mitZahl); expect(state.report.errorCount, 'Vorbedingung: kein Fehler im Pruefbericht').toBe(0); const schritt = naechsterSchritt(state); expect(schritt.text).not.toContain('Verkehrsstärken der Kfz- und ÖPNV-Signalgruppen'); }); });