lsa-planer

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

/ tests ui stilblattZusagen.test.ts

4,5 KB Rohdatei
tests/ui/stilblattZusagen.test.ts — 104 Zeilen
1 import { readFileSync, readdirSync, statSync } from 'node:fs';
2 import path from 'node:path';
3 import { describe, expect, it } from 'vitest';
4
5 /**
6 * Zusagen, die im Stilblatt stehen und die jsdom nicht nachrechnet.
7 *
8 * `getComputedStyle` liefert unter jsdom keine Kaskade: Weder die Stapelfolge
9 * noch der Vorrang zweier Regeln laesst sich dort messen. Beide Aussagen sind
10 * aber Zusagen der Barrierefreiheit, und beide sind still zerfallen, als
11 * jemand an einer der beiden Regeln arbeitete. Deshalb werden sie hier am
12 * Quelltext des Stilblatts festgehalten - grob, aber genau an der Stelle, an
13 * der sie brechen.
14 */
15
16 const WURZEL = path.resolve(__dirname, '..', '..');
17 const STILBLATT = path.join(WURZEL, 'src', 'styles', 'app.css');
18
19 function stilblatt(): string {
20 return readFileSync(STILBLATT, 'utf8');
21 }
22
23 /** Wert von `z-index` im Block der genannten Auswahlregel. */
24 function stapelwert(css: string, auswahl: string): number {
25 const start = css.indexOf(`\n${auswahl} {`);
26 expect(start, `Regel "${auswahl}" fehlt`).toBeGreaterThanOrEqual(0);
27 const block = css.slice(start, css.indexOf('\n}', start));
28 const treffer = /z-index:\s*(\d+)/.exec(block);
29 expect(treffer, `"${auswahl}" ohne z-index`).not.toBeNull();
30 return Number(treffer![1]);
31 }
32
33 describe('Meldungsstapel liegt über dem Fensterhintergrund (Befunde M4, L7)', () => {
34 it('gibt ihm eine höhere Stapelfolge als dem Fensterhintergrund', () => {
35 /*
36 * Der Meldungsstapel ist der einzige Teil des Hintergrunds, den ein
37 * geoeffnetes Fenster NICHT stilllegt: Seine Live-Bereiche sollen weiter
38 * ansagen, und eine stehengebliebene Warnung soll schliessbar bleiben
39 * (legeHintergrundStill in src/ui/feedback.ts).
40 *
41 * Bei z-index 200 gegen 300 traf beides nicht zu: Der halb deckende
42 * Fensterhintergrund lag darueber, die Meldung war abgedunkelt, und ein
43 * Klick auf ihren Schliessen-Knopf landete auf dem Hintergrund - der
44 * schliesst das FENSTER. Wer im Zwischenzeitenfenster eine Zahl vertippt,
45 * bekam so eine Warnung, die er nicht wegbekommt, ohne das Fenster zu
46 * verlieren.
47 */
48 const css = stilblatt();
49 expect(stapelwert(css, '.meldungen')).toBeGreaterThan(stapelwert(css, '.dialog-hintergrund'));
50 });
51 });
52
53 describe('Zeilenzustände schlagen die Überfahr-Einfärbung', () => {
54 it('gibt den Zustandsregeln denselben Aufbau wie der Hover-Regel und stellt sie dahinter', () => {
55 /*
56 * `tbody tr:hover td` hat drei Typen und eine Pseudoklasse, also (0,1,3);
57 * `.lageplan-aktiv td` kam auf (0,1,1) und verlor. Sobald der Zeiger auf
58 * der Zeile stand, verschwand damit genau die Auskunft, die sie traegt -
59 * welche Haltlinie hervorgehoben ist und welcher Weg vom gemessenen Wert
60 * abweicht.
61 *
62 * Gleicher Aufbau UND spaeter im Blatt: Bei gleichem Gewicht entscheidet
63 * die Reihenfolge.
64 */
65 const css = stilblatt();
66 const hover = css.indexOf('tbody tr:hover td {');
67 expect(hover, 'Hover-Regel fehlt').toBeGreaterThanOrEqual(0);
68
69 for (const klasse of ['lageplan-aktiv', 'lageplan-abweichung']) {
70 const zustand = css.indexOf(`tbody tr.${klasse} td {`);
71 expect(zustand, `Zustandsregel "${klasse}" ohne tbody-tr-Aufbau`).toBeGreaterThanOrEqual(0);
72 expect(zustand, `"${klasse}" steht vor der Hover-Regel`).toBeGreaterThan(hover);
73 }
74 });
75 });
76
77 describe('prefers-reduced-motion: der Kommentar beschreibt keinen Code, den es nicht gibt', () => {
78 it('wird ausschließlich im Stilblatt ausgewertet', () => {
79 /*
80 * Im Stilblatt stand: "Die Simulation laeuft weiter, aber sie startet dann
81 * nicht von selbst; das steuert die Ansicht". Die Simulationsansicht wertet
82 * die Einstellung nicht aus - sie muss es auch nicht, ihre Bildschleife
83 * laeuft nur nach einem Druck auf "Starten".
84 *
85 * Sollte je eine zweite Stelle hinzukommen, faellt dieser Fall und der
86 * Kommentar ist nachzuziehen. Das ist sein Zweck: Ein Kommentar, der eine
87 * erfundene Steuerung beschreibt, verleitet dazu, sie vorauszusetzen.
88 */
89 const treffer: string[] = [];
90 const durchlaufe = (ordner: string): void => {
91 for (const eintrag of readdirSync(ordner)) {
92 const voll = path.join(ordner, eintrag);
93 if (statSync(voll).isDirectory()) {
94 durchlaufe(voll);
95 } else if (/\.(ts|css|html)$/.test(eintrag)) {
96 if (readFileSync(voll, 'utf8').includes('prefers-reduced-motion')) treffer.push(voll);
97 }
98 }
99 };
100 durchlaufe(path.join(WURZEL, 'src'));
101
102 expect(treffer).toEqual([STILBLATT]);
103 });
104 });