lsa-planer

LSA-Planer Professional – Planungssoftware für Lichtsignalanlagen nach RiLSA 2015 und § 45 StVO. EUPL-1.2.

/ tests ui wirksamerWertOhneEintrag.test.ts

5,4 KB Rohdatei
tests/ui/wirksamerWertOhneEintrag.test.ts — 142 Zeilen
1 import { afterEach, describe, expect, it } from 'vitest';
2 import { ProjectStore } from '@/app/store';
3 import { createStandardIntersectionProject } from '@/domain/model/factory';
4 import { RILSA_DEFAULTS } from '@/domain/rilsa/constants';
5 import type { Project } from '@/domain/model/project';
6 import { resolveRilsaSettings } from '@/domain/rilsa/settings';
7 import { settingsView } from '@/ui/views/settingsView';
8
9 /**
10 * Befund 56 zur Fassung 5.9.0 (Anzeige gegen Fachkern).
11 *
12 * WAS DER ANWENDER SONST ERLEBT
13 *
14 * Er senkt in der Ansicht "Vorgaben" die "Räumgeschwindigkeit Fußgänger" auf
15 * 0,8 m/s und laesst das Nachbarfeld "Räumgeschwindigkeit Fußgänger mit
16 * erhöhtem Zeitbedarf" leer. Der Fachkern koppelt beide: Angesetzt wird
17 * min(1,0; 0,8) = 0,8 m/s, und er fuehrt das als Abweichung mit einer
18 * Fehlermeldung. Die Zeile, in der die Zahl eingetragen wird, zeigt trotzdem
19 * Regelwert 1 und Platzhalter 1 - ohne den Vermerk "wirksam 0,8 m/s". Der
20 * Fehlerbalken darueber sagt dabei woertlich: "gerechnet wird mit dem
21 * zulässigen Wert, der neben dem Feld steht" - und neben dem Feld steht nichts.
22 *
23 * Ursache: `wirksamerWert` brach ab, sobald kein eigener Eintrag vorlag. Die
24 * Ansicht entschied damit selbst, wann eine Abweichung moeglich ist, statt den
25 * aufgeloesten Kennwertsatz zu fragen.
26 */
27
28 const FESTES_DATUM = new Date('2026-01-01T00:00:00Z');
29
30 afterEach(() => {
31 document.body.replaceChildren();
32 });
33
34 function mitVorgabe(rilsa: Project['settings']['rilsa']): Project {
35 const roh = createStandardIntersectionProject('Vorgaben', FESTES_DATUM);
36 return { ...roh, settings: { ...roh.settings, rilsa: { ...roh.settings.rilsa, ...rilsa } } };
37 }
38
39 interface Ansicht {
40 readonly wurzel: HTMLElement;
41 readonly aufraeumen: () => void;
42 }
43
44 function zeichne(project: Project): Ansicht {
45 const wurzel = document.createElement('div');
46 document.body.append(wurzel);
47 const schliessen = settingsView.render(wurzel, {
48 store: new ProjectStore(project),
49 refresh: () => {},
50 navigate: () => {},
51 target: null,
52 });
53 return {
54 wurzel,
55 aufraeumen: () => {
56 schliessen();
57 wurzel.remove();
58 },
59 };
60 }
61
62 /** Zeile der Vorgabentabelle zu einem Kennwert. */
63 function zeileZu(wurzel: ParentNode, label: string): HTMLTableRowElement {
64 const zeile = [...wurzel.querySelectorAll<HTMLTableRowElement>('tbody tr')].find(
65 (tr) => tr.children[0]?.textContent?.trim() === label,
66 );
67 if (!zeile) throw new Error(`Keine Zeile "${label}"`);
68 return zeile;
69 }
70
71 describe('Vorgaben: der Vermerk "wirksam N" steht auch am leeren Feld', () => {
72 it('nennt bei gesenkter Fussgaengergeschwindigkeit die gekappte Geschwindigkeit des erhoehten Zeitbedarfs', () => {
73 // Der Fachkern kappt hier - belegt am Fachkern selbst, damit die Ansicht
74 // gegen den gerechneten Wert geprueft wird und nicht gegen eine Annahme.
75 const aufgeloest = resolveRilsaSettings({ clearingSpeedFuss: 0.8 }, undefined, 'knotenpunkt');
76 expect(aufgeloest.defaults.clearingSpeed.fussReducedMobility).toBe(0.8);
77 expect(RILSA_DEFAULTS.clearingSpeed.fussReducedMobility).toBe(1.0);
78
79 const ansicht = zeichne(mitVorgabe({ clearingSpeedFuss: 0.8 }));
80 try {
81 const zeile = zeileZu(
82 ansicht.wurzel,
83 'Räumgeschwindigkeit Fußgänger mit erhöhtem Zeitbedarf',
84 );
85 // Das Feld bleibt leer, der Regelwert bleibt 1 - nur der Vermerk fehlte.
86 expect(zeile.querySelector('input')?.value).toBe('');
87 expect(zeile.textContent, 'die Zeile stellt 1 m/s als geltend dar').toContain(
88 'wirksam 0,8 m/s',
89 );
90 } finally {
91 ansicht.aufraeumen();
92 }
93 });
94
95 it('nennt beim engen Innenradius die Kappung durch die Geschwindigkeit des Abbiegers', () => {
96 const aufgeloest = resolveRilsaSettings(
97 { clearingSpeedKfzTurning: 4 },
98 undefined,
99 'knotenpunkt',
100 );
101 expect(aufgeloest.defaults.clearingSpeed.kfzTurningEngerRadius).toBe(4);
102
103 const ansicht = zeichne(mitVorgabe({ clearingSpeedKfzTurning: 4 }));
104 try {
105 const zeile = zeileZu(
106 ansicht.wurzel,
107 'Räumgeschwindigkeit Kfz abbiegend bei engem Innenradius',
108 );
109 expect(zeile.querySelector('input')?.value).toBe('');
110 expect(zeile.textContent).toContain('wirksam 4 m/s');
111 } finally {
112 ansicht.aufraeumen();
113 }
114 });
115
116 it('schweigt an Zeilen, an denen nichts abweicht', () => {
117 const ansicht = zeichne(mitVorgabe({ clearingSpeedFuss: 0.8 }));
118 try {
119 // Das eingetragene Feld selbst: 0,8 ist zulaessig, es wird nichts
120 // ersetzt - kein Vermerk.
121 expect(zeileZu(ansicht.wurzel, 'Räumgeschwindigkeit Fußgänger').textContent).not.toContain(
122 'wirksam',
123 );
124 // Ein voellig unbeteiligter Kennwert bleibt ebenfalls stumm.
125 expect(zeileZu(ansicht.wurzel, 'Kleinste Umlaufzeit').textContent).not.toContain('wirksam');
126 } finally {
127 ansicht.aufraeumen();
128 }
129 });
130
131 it('bleibt ohne jede Vorgabe an allen Zeilen stumm', () => {
132 const ansicht = zeichne(createStandardIntersectionProject('Vorgaben', FESTES_DATUM));
133 try {
134 const zeilen = [...ansicht.wurzel.querySelectorAll<HTMLTableRowElement>('tbody tr')];
135 expect(zeilen.length, 'Die Vorgabentabelle ist leer').toBeGreaterThan(0);
136 const mitVermerk = zeilen.filter((tr) => (tr.textContent ?? '').includes('wirksam'));
137 expect(mitVermerk.map((tr) => tr.children[0]?.textContent ?? '')).toEqual([]);
138 } finally {
139 ansicht.aufraeumen();
140 }
141 });
142 });