lsa-planer

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

/ tests ui einenUmlauf.test.ts

3,2 KB Rohdatei
tests/ui/einenUmlauf.test.ts — 91 Zeilen
1 import { afterEach, describe, expect, it } from 'vitest';
2 import { ProjectStore } from '@/app/store';
3 import { buildSignalPlan } from '@/domain/plan/signalPlan';
4 import { createStandardIntersectionProject } from '@/domain/model/factory';
5 import type { Project } from '@/domain/model/project';
6 import { simulationView } from '@/ui/views/simulationView';
7
8 /**
9 * "Einen Umlauf" muss genau einen Umlauf weiterrechnen (Befund 55 zur
10 * Fassung 5.8.0).
11 *
12 * Was der Anwender sonst erlebt: Bei der Regelumlaufzeit 90 s springt die
13 * Laufmarke je Druck nur um 60 s weiter. "Position im Umlauf" steht danach auf
14 * 60,0 s statt auf 0,0 s, "Simulationszeit" auf 60 s statt 90 s, und "Umläufe"
15 * bleibt bei 0 - obwohl die Schaltflaeche "Rechnet genau einen Umlauf weiter"
16 * zusagt. Ursache ist die Kappung bei 60 s in `advance`, die den langen
17 * Zeitsprung des Animationspfads abfangen soll.
18 */
19
20 const FESTES_DATUM = new Date('2026-01-01T00:00:00Z');
21
22 function zeichne(project: Project): { wurzel: HTMLElement; aufraeumen: () => void } {
23 const wurzel = document.createElement('div');
24 document.body.append(wurzel);
25 const store = new ProjectStore(project);
26 const abmelden = simulationView.render(wurzel, {
27 store,
28 refresh: () => {},
29 navigate: () => {},
30 target: null,
31 });
32 return {
33 wurzel,
34 aufraeumen: () => {
35 abmelden();
36 wurzel.remove();
37 },
38 };
39 }
40
41 function kennzahl(wurzel: ParentNode, beschriftung: string): string {
42 const feld = [...wurzel.querySelectorAll('.kennzahl')].find(
43 (k) => k.querySelector('dt')?.textContent === beschriftung,
44 );
45 if (!feld) throw new Error(`Keine Kennzahl "${beschriftung}"`);
46 return feld.querySelector('dd')?.textContent ?? '';
47 }
48
49 function knopf(wurzel: ParentNode, beschriftung: string): HTMLButtonElement {
50 const gefunden = [...wurzel.querySelectorAll('button')].find(
51 (b) => b.textContent?.trim() === beschriftung,
52 );
53 if (!gefunden) throw new Error(`Keine Schaltfläche "${beschriftung}"`);
54 return gefunden;
55 }
56
57 afterEach(() => {
58 document.body.replaceChildren();
59 });
60
61 describe('Simulation: Schaltflaeche "Einen Umlauf"', () => {
62 it('rechnet bei Umlaufzeit 90 s einen vollen Umlauf weiter', () => {
63 const project = createStandardIntersectionProject('Einen Umlauf', FESTES_DATUM);
64 expect(buildSignalPlan(project).cycleTime).toBe(90);
65 const { wurzel, aufraeumen } = zeichne(project);
66 try {
67 knopf(wurzel, 'Einen Umlauf').click();
68 expect(kennzahl(wurzel, 'Simulationszeit')).toBe('90 s');
69 expect(kennzahl(wurzel, 'Position im Umlauf')).toBe('0,0 s');
70 expect(kennzahl(wurzel, 'Umläufe')).toBe('1');
71 } finally {
72 aufraeumen();
73 }
74 });
75
76 it('zaehlt bei jedem Druck einen weiteren Umlauf', () => {
77 const project = createStandardIntersectionProject('Einen Umlauf', FESTES_DATUM);
78 const { wurzel, aufraeumen } = zeichne(project);
79 try {
80 const schalter = knopf(wurzel, 'Einen Umlauf');
81 schalter.click();
82 schalter.click();
83 schalter.click();
84 expect(kennzahl(wurzel, 'Umläufe')).toBe('3');
85 expect(kennzahl(wurzel, 'Position im Umlauf')).toBe('0,0 s');
86 expect(kennzahl(wurzel, 'Simulationszeit')).toBe('270 s');
87 } finally {
88 aufraeumen();
89 }
90 });
91 });