import { describe, expect, it } from 'vitest'; import { parseProject } from '@/domain/model/schema'; import { defaultVehicleClass } from '@/domain/model/factory'; import { SAFETY_FLOORS } from '@/domain/rilsa/constants'; import type { TrafficMode } from '@/domain/rilsa/types'; /* * Fahrzeugart gegen die VERKEHRSART pruefen (Fassung 5.9.0). * * Das Schema prueft die Fahrzeugart bislang nur gegen die Werteliste. Eine * Datei mit `mode` 'kfz' und `vehicleClass` 'keine' kam ohne eine einzige * Meldung durch, der Raeumweg blieb ohne Fahrzeuglaenge, und die Zwischenzeit * fiel um rund eine Sekunde kuerzer aus - die gefaehrliche Richtung. * * `oneOf` ersetzt eine UNBEKANNTE Art bereits durch die Standardart und meldet * es. Eine bekannte, an dieser Verkehrsart aber unzulaessige Art ist derselbe * Mangel desselben Feldes und bekommt dieselbe Behandlung; zwei verschiedene * Wege fuer ein Feld waeren der Widerspruch, der behoben werden soll. */ /** Ein eingelesenes Projekt mit genau einer Signalgruppe. */ function einlesen(mode: TrafficMode, vehicleClass: unknown) { const roh = { schemaVersion: 13, signalGroups: [ { id: 'sg-1', name: 'K1', mode, movement: mode === 'fuss' ? 'querung' : 'geradeaus', armId: null, vZul: 50, lanes: 1, vehicleClass, minGreenOverride: null, maxGreenOverride: null, reducedMobility: false, color: '#2f6fd0', }, ], }; const { project, issues, repaired } = parseProject(roh); const meldungen = issues.filter((i) => i.path === 'signalGroups[0].vehicleClass'); return { art: project.signalGroups[0]?.vehicleClass, meldung: meldungen[0], meldungen, repaired, }; } describe('Unzulaessige Fahrzeugart wird beim Einlesen ersetzt und gemeldet', () => { it('ersetzt "keine" am Kfz-Strom durch die Standardart und meldet es', () => { const { art, meldung, repaired } = einlesen('kfz', 'keine'); expect(art).toBe(defaultVehicleClass('kfz')); expect(art).toBe('pkw'); expect(meldung).toBeDefined(); expect(meldung!.severity).toBe('warnung'); expect(meldung!.message).toContain('keine'); expect(meldung!.message).toContain(String(SAFETY_FLOORS.minVehicleLengthKfz)); // Die Ersetzung ist eine Reparatur: Der Einlesedialog muss erscheinen. expect(repaired).toBe(true); }); it('ersetzt "rad" am OePNV-Strom durch die Standardart dieser Verkehrsart', () => { const { art, meldung } = einlesen('oepnv', 'rad'); expect(art).toBe(defaultVehicleClass('oepnv')); expect(art).toBe('bus'); expect(meldung).toBeDefined(); }); it('laesst zulaessige Arten am Kfz-Strom unangetastet und schweigt', () => { for (const art of ['pkw', 'lkw', 'bus', 'lastzug', 'strassenbahn'] as const) { const ergebnis = einlesen('kfz', art); expect(ergebnis.art, art).toBe(art); expect(ergebnis.meldung, art).toBeUndefined(); } }); it('laesst Fussgaenger- und Radgruppen jede Art behalten', () => { // Nach oben ist derselbe Widerspruch nur unwirtschaftlich, nicht unsicher. expect(einlesen('fuss', 'keine').art).toBe('keine'); expect(einlesen('fuss', 'lastzug').art).toBe('lastzug'); expect(einlesen('rad', 'keine').art).toBe('keine'); expect(einlesen('fuss', 'keine').meldung).toBeUndefined(); expect(einlesen('rad', 'keine').meldung).toBeUndefined(); }); it('meldet eine unbekannte Art weiterhin genau einmal', () => { // GEZAEHLT, nicht nur gefunden: Der Name sagt "genau einmal", und genau das // ist die Zusicherung. Sie haengt daran, dass der zweite Zweig den von // `oneOf` bereits ERSETZTEN Wert prueft und nicht den rohen aus der Datei: // Der Rueckfall `defaultVehicleClass(mode)` genuegt der Schranke immer, der // Zweig greift deshalb nicht nach. Prueft er stattdessen den rohen Wert, // stehen zwei Meldungen zu einem Feld im Einlesedialog. const { art, meldung, meldungen } = einlesen('kfz', 'traktor'); expect(art).toBe('pkw'); expect(meldungen).toHaveLength(1); expect(meldung!.message).toContain('traktor'); }); it('nimmt die Standardart aus dem Fachkern - keine zweite Fassung derselben Zuordnung', () => { // Vor der Fassung 5.9.0 stand die Zuordnung hier ein zweites Mal als // Bedingungskette; fuer den OePNV wich sie von defaultVehicleClass ab. for (const mode of ['kfz', 'rad', 'fuss', 'oepnv'] as const) { expect(einlesen(mode, 'traktor').art, mode).toBe(defaultVehicleClass(mode)); } }); });