lsa-planer
LSA-Planer Professional – Planungssoftware für Lichtsignalanlagen nach RiLSA 2015 und § 45 StVO. EUPL-1.2.
/ tests ui legendeGegenRegel.test.ts
| 1 | import { afterEach, describe, expect, it } from 'vitest'; |
| 2 | import { ProjectStore } from '@/app/store'; |
| 3 | import { validateProject } from '@/domain/validation/engine'; |
| 4 | import { buildSignalPlan } from '@/domain/plan/signalPlan'; |
| 5 | import { createStandardIntersectionProject } from '@/domain/model/factory'; |
| 6 | import { conflictsView } from '@/ui/views/conflictsView'; |
| 7 | import type { Project } from '@/domain/model/project'; |
| 8 | |
| 9 | /* |
| 10 | * Die Legende der Zwischenzeitenansicht erklaerte die rot unterstrichene 0 s |
| 11 | * fuer "nicht zulaessig". Die Pruefregel zwischenzeiten.null meldet denselben |
| 12 | * Wert als WARNUNG und haelt fest, unter welcher Bedingung er zulaessig ist. |
| 13 | * Zwei Ansichten desselben Programms sagten damit Gegenteiliges ueber dieselbe |
| 14 | * Zahl. (Bis 5.42.1 nannte die Regel den Wert "bei langen Furten" den |
| 15 | * Regelfall; seit 5.43.0 nennt sie die Bedingung - Gruppe Furt.) |
| 16 | */ |
| 17 | |
| 18 | const STICHTAG = new Date('2026-01-01T00:00:00Z'); |
| 19 | |
| 20 | let aufraeumen: (() => void) | null = null; |
| 21 | afterEach(() => { |
| 22 | aufraeumen?.(); |
| 23 | aufraeumen = null; |
| 24 | document.body.replaceChildren(); |
| 25 | }); |
| 26 | |
| 27 | function legendentext(project: Project): string { |
| 28 | const wurzel = document.createElement('div'); |
| 29 | document.body.append(wurzel); |
| 30 | const schliesse = conflictsView.render(wurzel, { |
| 31 | store: new ProjectStore(project), |
| 32 | refresh: () => {}, |
| 33 | navigate: () => {}, |
| 34 | target: null, |
| 35 | }); |
| 36 | aufraeumen = () => { |
| 37 | schliesse(); |
| 38 | wurzel.remove(); |
| 39 | }; |
| 40 | return wurzel.querySelector('.plan-legende')?.textContent ?? ''; |
| 41 | } |
| 42 | |
| 43 | /** Projekt, in dem jede Beziehung rechnerisch 0 s ergibt. */ |
| 44 | function nullzwischenzeiten(): Project { |
| 45 | const roh = createStandardIntersectionProject('Legende', STICHTAG); |
| 46 | return { |
| 47 | ...roh, |
| 48 | conflicts: roh.conflicts.map((c) => ({ ...c, clearingDistance: 3, enteringDistance: 60 })), |
| 49 | }; |
| 50 | } |
| 51 | |
| 52 | describe('Legende und Pruefregel sagen dasselbe ueber eine Zwischenzeit von 0 s', () => { |
| 53 | it('erklaert den Wert nicht fuer unzulaessig', () => { |
| 54 | const text = legendentext(createStandardIntersectionProject('Legende', STICHTAG)); |
| 55 | |
| 56 | expect(text).toContain('Zwischenzeit 0 s'); |
| 57 | expect(text, 'die Regel nennt den Wert unter einer Bedingung zulässig').not.toContain( |
| 58 | 'nicht zulässig', |
| 59 | ); |
| 60 | }); |
| 61 | |
| 62 | it('die Regel dazu ist eine Warnung und sperrt den Export nicht', () => { |
| 63 | const projekt = nullzwischenzeiten(); |
| 64 | const bericht = validateProject(projekt, buildSignalPlan(projekt), STICHTAG); |
| 65 | |
| 66 | const befunde = bericht.findings.filter((f) => f.rule === 'zwischenzeiten.null'); |
| 67 | expect(befunde.length, 'Der Aufbau muss die Regel auslösen').toBeGreaterThan(0); |
| 68 | expect(befunde.every((f) => f.severity === 'warnung')).toBe(true); |
| 69 | expect(befunde[0]!.message).toContain('zulässig'); |
| 70 | |
| 71 | // Gegenprobe: Die 0 s allein darf den Export nicht sperren. |
| 72 | expect( |
| 73 | bericht.findings.some((f) => f.severity === 'fehler' && f.category === 'zwischenzeiten'), |
| 74 | ).toBe(false); |
| 75 | }); |
| 76 | }); |