lsa-planer

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

/ tests ui begrenzteEingabe.test.ts

4,1 KB Rohdatei
tests/ui/begrenzteEingabe.test.ts — 106 Zeilen
1 import { afterEach, describe, expect, it } from 'vitest';
2 import { ProjectStore } from '@/app/store';
3 import { createStandardIntersectionProject } from '@/domain/model/factory';
4 import type { Project } from '@/domain/model/project';
5 import { meldungsverlauf } from '@/ui/feedback';
6 import { signalGroupsView } from '@/ui/views/signalGroupsView';
7
8 /**
9 * Eine auf den bereits eingetragenen Wert begrenzte Eingabe aendert nichts
10 * (Befund 59).
11 *
12 * Was der Anwender sonst erlebt: In der Signalgruppenansicht steht im Feld
13 * "Fahrstreifen" die 1 - der Werkwert und zugleich die Untergrenze. Er traegt
14 * eine 0 ein und tabbt weiter. Die Eingabe wird auf 1 begrenzt, im Feld steht
15 * wieder 1 - und trotzdem meldet die Kopfzeile "ungespeicherte Änderungen",
16 * "Rueckgaengig" wird mit dem Schritt "Fahrstreifenzahl geändert" aktiv, und
17 * das Aenderungsdatum des Projekts ist neu. Letzteres wird als "Zuletzt
18 * geändert" in die Planunterlage gedruckt.
19 *
20 * Geprueft wird ueber den Bedienweg: die echte Ansicht, das echte Zahlenfeld,
21 * das echte `change`-Ereignis. Der Vergleich, der es abfaengt, sitzt in
22 * `ProjectStore.update` - siehe tests/app/wertgleicheAenderung.test.ts.
23 *
24 * GEGEN DEN ALTSTAND schlaegt der erste Fall fehl. Der zweite haelt fest, dass
25 * die Rueckmeldung an den Anwender bleibt - sie ist die einzige Auskunft
26 * darueber, dass die Eingabe abgelehnt wurde -, der dritte ist die Gegenprobe
27 * mit einer Zahl, die wirklich etwas aendert.
28 */
29
30 const FESTES_DATUM = new Date('2026-01-01T00:00:00Z');
31
32 let aufraeumen: (() => void) | null = null;
33
34 afterEach(() => {
35 aufraeumen?.();
36 aufraeumen = null;
37 });
38
39 function zeichne(project: Project): { wurzel: HTMLElement; store: ProjectStore } {
40 const wurzel = document.createElement('div');
41 document.body.append(wurzel);
42 const store = new ProjectStore(project);
43 const abmelden = signalGroupsView.render(wurzel, {
44 store,
45 refresh: () => {},
46 navigate: () => {},
47 target: null,
48 });
49 aufraeumen = () => {
50 abmelden();
51 wurzel.remove();
52 };
53 return { wurzel, store };
54 }
55
56 function fahrstreifenfeld(wurzel: HTMLElement, gruppe: string): HTMLInputElement {
57 const feld = wurzel.querySelector<HTMLInputElement>(
58 `input[aria-label="Anzahl der Fahrstreifen, ${gruppe}"]`,
59 );
60 if (!feld) throw new Error(`Feld "Fahrstreifen" der Gruppe ${gruppe} fehlt.`);
61 return feld;
62 }
63
64 function trageEin(feld: HTMLInputElement, text: string): void {
65 feld.value = text;
66 feld.dispatchEvent(new Event('change', { bubbles: true }));
67 }
68
69 describe('Auf den vorhandenen Wert begrenzte Eingabe', () => {
70 it('laesst Aenderungsmerker, Rueckgaengig und Aenderungsdatum unberuehrt', () => {
71 const { wurzel, store } = zeichne(createStandardIntersectionProject('Prueffall', FESTES_DATUM));
72 const feld = fahrstreifenfeld(wurzel, 'K1');
73 expect(feld.value).toBe('1');
74 const geaendertAm = store.getProject().meta.modifiedAt;
75
76 trageEin(feld, '0');
77
78 // Die Begrenzung wirkt weiter - im Feld steht wieder der alte Wert.
79 expect(feld.value).toBe('1');
80 expect(store.getState().dirty).toBe(false);
81 expect(store.getState().canUndo).toBe(false);
82 // Diese Zahl steht als "Zuletzt geändert" in der Planunterlage.
83 expect(store.getProject().meta.modifiedAt).toBe(geaendertAm);
84 });
85
86 it('meldet dem Anwender trotzdem, was mit seiner Eingabe geschehen ist', () => {
87 const { wurzel } = zeichne(createStandardIntersectionProject('Prueffall', FESTES_DATUM));
88
89 trageEin(fahrstreifenfeld(wurzel, 'K1'), '0');
90
91 const meldung = meldungsverlauf()[0]!;
92 expect(meldung.art).toBe('warnung');
93 expect(meldung.text).toContain('außerhalb des zulässigen Bereichs');
94 expect(meldung.text).toContain('Eingetragen wurde 1');
95 });
96
97 it('nimmt eine Eingabe an, die den Wert wirklich aendert', () => {
98 const { wurzel, store } = zeichne(createStandardIntersectionProject('Prueffall', FESTES_DATUM));
99
100 trageEin(fahrstreifenfeld(wurzel, 'K1'), '2');
101
102 expect(store.getState().dirty).toBe(true);
103 expect(store.getState().undoLabel).toBe('Fahrstreifenzahl geändert');
104 expect(store.getProject().signalGroups[0]!.lanes).toBe(2);
105 });
106 });