waffensachkunde

Waffensachkunde – Lernsoftware für die Sachkundeprüfung nach § 7 WaffG. Barrierefrei, offline, EUPL-1.2.

/ app tests fensterlage.test.ts

5,4 KB Rohdatei
app/tests/fensterlage.test.ts — 142 Zeilen
1 // @vitest-environment node
2 /**
3 * Größe und Lage des Hauptfensters.
4 *
5 * **Der Anlass.** Das Fenster startete bis 0.22.0 immer mit 1180 × 820 an der
6 * Systemposition. Wer maximiert arbeitet oder es – wie der Kommentar in
7 * `main/fenster.ts` selbst als Anwendungsfall nennt – schmal neben eine
8 * Bildschirmlupe oder ein zweites Programm stellt, richtete das bei jedem
9 * Start neu ein. Das ist Standard-Erwartung an jede Windows-Anwendung und
10 * trifft besonders die Lupen- und Split-Screen-Nutzer, also genau die
11 * Zielgruppe des Barrierefreiheitsanspruchs.
12 *
13 * **Der gefährliche Fall** ist nicht die Größe, sondern die Lage: Ein Fenster,
14 * dessen gespeicherte Position auf einem inzwischen abgesteckten Monitor
15 * liegt, ginge außerhalb jeder sichtbaren Fläche auf – vorhanden, aber
16 * unerreichbar. Und ohne Fenster gibt es keinen Weg, die Einstellung
17 * zurückzusetzen. Deshalb ist die Prüfung eine reine Funktion: So lässt sie
18 * sich messen, ohne einen zweiten Monitor abzustecken.
19 */
20
21 import { describe, expect, it } from 'vitest';
22
23 import {
24 FENSTER_MINDESTBREITE,
25 FENSTER_MINDESTHOEHE,
26 FENSTER_VORGABE,
27 fensterlageBereinigen,
28 lageIstErreichbar,
29 startlage,
30 type Flaeche,
31 } from '../src/shared/fensterlage';
32
33 /** Ein gewöhnlicher Einzelbildschirm. */
34 const HAUPTSCHIRM: Flaeche = { x: 0, y: 0, width: 1920, height: 1040 };
35
36 /** Ein zweiter Schirm links daneben – negative Koordinaten sind normal. */
37 const ZWEITSCHIRM: Flaeche = { x: -1920, y: 0, width: 1920, height: 1040 };
38
39 describe('Gespeicherte Lage bereinigen', () => {
40 it('nimmt eine gewöhnliche Lage unverändert', () => {
41 expect(fensterlageBereinigen({ breite: 1400, hoehe: 900, x: 100, y: 50 })).toEqual({
42 breite: 1400,
43 hoehe: 900,
44 x: 100,
45 y: 50,
46 });
47 });
48
49 it('merkt sich den maximierten Zustand', () => {
50 expect(fensterlageBereinigen({ breite: 1400, hoehe: 900, maximiert: true })).toMatchObject({
51 maximiert: true,
52 });
53 });
54
55 it('verwirft, was keine Lage ist', () => {
56 expect(fensterlageBereinigen(null)).toBeNull();
57 expect(fensterlageBereinigen('groß')).toBeNull();
58 expect(fensterlageBereinigen({})).toBeNull();
59 expect(fensterlageBereinigen({ breite: 'viel', hoehe: 900 })).toBeNull();
60 });
61
62 it('hebt eine unbedienbar kleine Größe an', () => {
63 /* Nach unten gekappt, nicht nach oben: Ein zu großes Fenster schiebt das
64 Betriebssystem selbst zurecht, ein zu kleines wäre unbedienbar – und
65 niemand könnte es wieder vergrößern, wenn die Ränder fehlen. */
66 const lage = fensterlageBereinigen({ breite: 10, hoehe: 10 });
67
68 expect(lage?.breite).toBe(FENSTER_MINDESTBREITE);
69 expect(lage?.hoehe).toBe(FENSTER_MINDESTHOEHE);
70 });
71
72 it('lässt eine Position ohne Angabe einfach weg', () => {
73 const lage = fensterlageBereinigen({ breite: 1400, hoehe: 900 });
74
75 expect(lage).not.toBeNull();
76 expect(lage?.x).toBeUndefined();
77 });
78 });
79
80 describe('Erreichbarkeit auf den vorhandenen Bildschirmen', () => {
81 it('lässt eine Lage mitten auf dem Schirm zu', () => {
82 expect(lageIstErreichbar({ breite: 800, hoehe: 600, x: 200, y: 100 }, [HAUPTSCHIRM])).toBe(
83 true,
84 );
85 });
86
87 it('lässt ein Fenster zu, das ein Stück über den Rand ragt', () => {
88 /* Alltäglich und gewollt – verlangt wird nur, dass ein greifbarer Teil
89 sichtbar bleibt. */
90 expect(lageIstErreichbar({ breite: 800, hoehe: 600, x: 1600, y: 900 }, [HAUPTSCHIRM])).toBe(
91 true,
92 );
93 });
94
95 it('weist eine Lage auf einem abgesteckten Monitor ab', () => {
96 /* Der eigentliche Schadensfall: Das Fenster ginge auf und bliebe
97 unsichtbar – und ohne Fenster ließe sich die Einstellung nicht mehr
98 zurücksetzen. */
99 const aufZweitschirm = { breite: 800, hoehe: 600, x: -1500, y: 100 };
100
101 expect(lageIstErreichbar(aufZweitschirm, [HAUPTSCHIRM, ZWEITSCHIRM])).toBe(true);
102 expect(lageIstErreichbar(aufZweitschirm, [HAUPTSCHIRM])).toBe(false);
103 });
104
105 it('weist eine Lage ab, von der nur ein Zipfel sichtbar wäre', () => {
106 /* Ein Fenster, das mit zehn Pixeln in den Schirm ragt, lässt sich nicht
107 mehr anfassen, um es zurückzuholen. */
108 expect(lageIstErreichbar({ breite: 800, hoehe: 600, x: 1910, y: 100 }, [HAUPTSCHIRM])).toBe(
109 false,
110 );
111 });
112
113 it('lässt eine Lage ohne Position immer zu', () => {
114 /* Dann entscheidet das Betriebssystem – das ist nie falsch. */
115 expect(lageIstErreichbar({ breite: 800, hoehe: 600 }, [])).toBe(true);
116 });
117 });
118
119 describe('Startlage', () => {
120 it('nimmt die Vorgabe, wenn nichts gespeichert ist', () => {
121 expect(startlage(undefined, [HAUPTSCHIRM])).toEqual({ ...FENSTER_VORGABE });
122 });
123
124 it('nimmt die Vorgabe, wenn die gespeicherte Lage nicht mehr erreichbar ist', () => {
125 const verloren = { breite: 800, hoehe: 600, x: -1500, y: 100 };
126
127 expect(startlage(verloren, [HAUPTSCHIRM])).toEqual({ ...FENSTER_VORGABE });
128 });
129
130 it('nimmt die gespeicherte Lage, wenn sie trägt', () => {
131 const gespeichert = { breite: 1400, hoehe: 900, x: 100, y: 50, maximiert: true };
132
133 expect(startlage(gespeichert, [HAUPTSCHIRM])).toEqual(gespeichert);
134 });
135
136 it('kommt ohne jeden Bildschirm aus', () => {
137 /* Sollte nicht vorkommen – aber ein Absturz beim Fensterbau wäre die
138 schlechteste Antwort darauf. */
139 expect(() => startlage({ breite: 800, hoehe: 600, x: 0, y: 0 }, [])).not.toThrow();
140 expect(startlage({ breite: 800, hoehe: 600, x: 0, y: 0 }, [])).toEqual({ ...FENSTER_VORGABE });
141 });
142 });