lsa-planer

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

/ tests ui tastenkuerzelHinterFenster.test.ts

3,8 KB Rohdatei
tests/ui/tastenkuerzelHinterFenster.test.ts — 124 Zeilen
1 import { beforeAll, describe, expect, it, vi } from 'vitest';
2 import {
3 ladeSitzung,
4 openProjectFromFile,
5 saveProjectToFile,
6 saveSession,
7 } from '@/services/storage';
8
9 /**
10 * Globale Tastenkuerzel hinter einem offenen modalen Fenster (Befund 47).
11 *
12 * Was der Anwender sonst erlebt: Er drueckt Strg+N, die Vorlagenauswahl geht
13 * auf - und drueckt, weil er sie nicht sieht oder ungeduldig ist, noch einmal.
14 * Eine zweite, wortgleiche Auswahl liegt jetzt auf der ersten; wer mit
15 * Sprachausgabe arbeitet, merkt von der verdeckten nichts und muss jede
16 * einzeln schliessen. Schlimmer in der Mischung: Strg+N oeffnet die Auswahl,
17 * Strg+O darueber laedt ein Projekt aus einer Datei - und die darunter
18 * vergessene Auswahl ersetzt es beim naechsten Klick wieder durch eine Vorlage,
19 * samt Dateipfad und Rueckgaengig-Kette.
20 *
21 * Fuer F1 ist derselbe Mangel als Befund M1 laengst behoben (`kurzhilfe` in
22 * src/main.ts); der Stapelempfaenger in src/ui/feedback.ts faengt nur Escape
23 * und Tab ab, jede andere Taste erreicht den Empfaenger am Fenster.
24 *
25 * Geprueft wird am echten Einstiegspunkt: `src/main.ts` wird eingelesen und
26 * startet die ganze Anwendung; ersetzt sind nur Sitzungsspeicher und
27 * Dateizugriff.
28 */
29
30 vi.mock('@/services/storage', async (importOriginal) => {
31 const echt = await importOriginal<typeof import('@/services/storage')>();
32 return {
33 ...echt,
34 ladeSitzung: vi.fn(),
35 saveSession: vi.fn(),
36 addRecoveryPoint: vi.fn(),
37 openProjectFromFile: vi.fn(),
38 saveProjectToFile: vi.fn(),
39 };
40 });
41
42 async function warte(ms = 0): Promise<void> {
43 await new Promise((fertig) => setTimeout(fertig, ms));
44 }
45
46 function offeneFenster(): string[] {
47 return [...document.querySelectorAll('.dialog-hintergrund h2')].map(
48 (h) => h.textContent?.trim() ?? '',
49 );
50 }
51
52 function schaltflaeche(text: string): HTMLButtonElement {
53 const treffer = [...document.querySelectorAll('button')].find(
54 (b) => b.textContent?.trim() === text || b.getAttribute('aria-label') === text,
55 );
56 if (!treffer) throw new Error(`Schaltflaeche "${text}" nicht gefunden.`);
57 return treffer;
58 }
59
60 function druecke(taste: string): void {
61 window.dispatchEvent(
62 new KeyboardEvent('keydown', { key: taste, ctrlKey: true, bubbles: true, cancelable: true }),
63 );
64 }
65
66 beforeAll(async () => {
67 vi.mocked(ladeSitzung).mockResolvedValue({ art: 'leer' });
68 vi.mocked(saveSession).mockResolvedValue({ ok: true, message: '' });
69 vi.mocked(openProjectFromFile).mockResolvedValue({
70 ok: false,
71 canceled: true,
72 filePath: null,
73 message: '',
74 result: null,
75 });
76 vi.mocked(saveProjectToFile).mockResolvedValue({
77 ok: false,
78 canceled: true,
79 filePath: null,
80 message: '',
81 });
82
83 document.body.replaceChildren();
84 const wurzel = document.createElement('div');
85 wurzel.id = 'anwendung';
86 document.body.append(wurzel);
87
88 await import('@/main');
89 await warte(20);
90 });
91
92 describe('Tastenkuerzel bei offenem modalem Fenster', () => {
93 it('stapelt bei einem zweiten Strg+N kein zweites, wortgleiches Fenster', async () => {
94 druecke('n');
95 await warte(10);
96 expect(offeneFenster()).toEqual(['Neues Projekt']);
97
98 druecke('n');
99 await warte(10);
100 expect(offeneFenster()).toEqual(['Neues Projekt']);
101 });
102
103 it('wertet Strg+O und Strg+S hinter dem offenen Fenster nicht aus', async () => {
104 druecke('o');
105 druecke('s');
106 await warte(10);
107
108 expect(openProjectFromFile).not.toHaveBeenCalled();
109 expect(saveProjectToFile).not.toHaveBeenCalled();
110 expect(offeneFenster()).toEqual(['Neues Projekt']);
111 });
112
113 it('wirkt wieder, sobald das Fenster geschlossen ist', async () => {
114 schaltflaeche('Abbrechen').click();
115 await warte(10);
116 expect(offeneFenster()).toEqual([]);
117
118 druecke('n');
119 await warte(10);
120 expect(offeneFenster()).toEqual(['Neues Projekt']);
121 schaltflaeche('Abbrechen').click();
122 await warte(10);
123 });
124 });