waffensachkunde
Waffensachkunde – Lernsoftware für die Sachkundeprüfung nach § 7 WaffG. Barrierefrei, offline, EUPL-1.2.
| 1 | import { describe, expect, it } from 'vitest'; |
| 2 | |
| 3 | import { |
| 4 | farbschemaFuer, |
| 5 | istThemeAuswahl, |
| 6 | startfarbeFuer, |
| 7 | themeAufloesen, |
| 8 | umschaltAnsage, |
| 9 | type SystemAnzeigeSignale, |
| 10 | } from '../src/shared/theme'; |
| 11 | |
| 12 | function signale(teil: Partial<SystemAnzeigeSignale> = {}): SystemAnzeigeSignale { |
| 13 | return { |
| 14 | bevorzugtDunkel: false, |
| 15 | erzwungeneFarben: false, |
| 16 | bevorzugtMehrKontrast: false, |
| 17 | ...teil, |
| 18 | }; |
| 19 | } |
| 20 | |
| 21 | describe('themeAufloesen', () => { |
| 22 | it('folgt bei "system" der hellen Systemvorgabe', () => { |
| 23 | expect(themeAufloesen('system', signale())).toBe('hell'); |
| 24 | }); |
| 25 | |
| 26 | it('folgt bei "system" der dunklen Systemvorgabe', () => { |
| 27 | expect(themeAufloesen('system', signale({ bevorzugtDunkel: true }))).toBe('dunkel'); |
| 28 | }); |
| 29 | |
| 30 | it('wählt bei "system" und prefers-contrast: more den hohen Kontrast', () => { |
| 31 | expect(themeAufloesen('system', signale({ bevorzugtMehrKontrast: true }))).toBe('hochkontrast'); |
| 32 | }); |
| 33 | |
| 34 | it('respektiert die manuelle Auswahl gegen die Systemvorgabe', () => { |
| 35 | expect(themeAufloesen('hell', signale({ bevorzugtDunkel: true }))).toBe('hell'); |
| 36 | expect(themeAufloesen('dunkel', signale())).toBe('dunkel'); |
| 37 | }); |
| 38 | |
| 39 | it('lässt erzwungene Farben jede Auswahl überstimmen', () => { |
| 40 | for (const auswahl of ['system', 'hell', 'dunkel', 'hochkontrast'] as const) { |
| 41 | expect(themeAufloesen(auswahl, signale({ erzwungeneFarben: true }))).toBe('hochkontrast'); |
| 42 | } |
| 43 | }); |
| 44 | }); |
| 45 | |
| 46 | describe('istThemeAuswahl', () => { |
| 47 | it('erkennt gültige Werte', () => { |
| 48 | expect(istThemeAuswahl('hochkontrast')).toBe(true); |
| 49 | }); |
| 50 | |
| 51 | it('weist unbekannte oder falsch typisierte Werte ab', () => { |
| 52 | expect(istThemeAuswahl('neon')).toBe(false); |
| 53 | expect(istThemeAuswahl(null)).toBe(false); |
| 54 | expect(istThemeAuswahl(42)).toBe(false); |
| 55 | expect(istThemeAuswahl(undefined)).toBe(false); |
| 56 | }); |
| 57 | }); |
| 58 | |
| 59 | describe('farbschemaFuer', () => { |
| 60 | it('stimmt mit den color-scheme-Angaben in tokens.css überein', () => { |
| 61 | expect(farbschemaFuer('hell')).toBe('light'); |
| 62 | expect(farbschemaFuer('dunkel')).toBe('dark'); |
| 63 | // Hoher Kontrast ist weiße Schrift auf Schwarz – also ebenfalls dark. |
| 64 | expect(farbschemaFuer('hochkontrast')).toBe('dark'); |
| 65 | }); |
| 66 | |
| 67 | /* |
| 68 | Beim Windows-Kontrastdesign sagt `hochkontrast` nur, dass die Farben von |
| 69 | aussen kommen. Es gibt auch helle Kontrastdesigns; bis 0.24.1 stellte die |
| 70 | Anwendung dort Scrollbalken und Formularelemente unbedingt auf dunkel. |
| 71 | `startfarbeFuer` macht es seit jeher richtig – hier fehlte die |
| 72 | Entsprechung. |
| 73 | */ |
| 74 | it('überlässt bei erzwungenen Farben dem System, ob hell oder dunkel', () => { |
| 75 | expect(farbschemaFuer('hochkontrast', signale({ erzwungeneFarben: true }))).toBe('light'); |
| 76 | expect( |
| 77 | farbschemaFuer('hochkontrast', signale({ erzwungeneFarben: true, bevorzugtDunkel: true })), |
| 78 | ).toBe('dark'); |
| 79 | }); |
| 80 | |
| 81 | it('bleibt dieselbe Aussage wie startfarbeFuer', () => { |
| 82 | /* Zwei Funktionen, eine Frage – sie dürfen nicht auseinanderlaufen. */ |
| 83 | for (const dunkel of [false, true]) { |
| 84 | const s = signale({ erzwungeneFarben: true, bevorzugtDunkel: dunkel }); |
| 85 | const hellSchema = farbschemaFuer('hochkontrast', s) === 'light'; |
| 86 | expect(startfarbeFuer('hochkontrast', s)).toBe(hellSchema ? '#ffffff' : '#000000'); |
| 87 | } |
| 88 | }); |
| 89 | }); |
| 90 | |
| 91 | describe('startfarbeFuer', () => { |
| 92 | /* |
| 93 | Die Farbe, die das Fenster zeigt, bevor der Renderer das erste Bild |
| 94 | liefert. Bis 0.21.0 fragte `fenster.ts` dafür nur `nativeTheme` – wer |
| 95 | „Dunkel“ eingestellt hatte, während Windows hell läuft, sah bei jedem |
| 96 | Start kurz eine helle Fläche. Seither entscheidet die gespeicherte Wahl. |
| 97 | */ |
| 98 | it('folgt der gespeicherten Wahl und nicht dem Systemdesign', () => { |
| 99 | expect(startfarbeFuer('dunkel', signale())).toBe('#14161a'); |
| 100 | expect(startfarbeFuer('hell', signale({ bevorzugtDunkel: true }))).toBe('#f7f7f5'); |
| 101 | expect(startfarbeFuer('hochkontrast', signale())).toBe('#000000'); |
| 102 | }); |
| 103 | |
| 104 | it('überlässt bei „system“ dem Betriebssystem die Entscheidung', () => { |
| 105 | expect(startfarbeFuer('system', signale())).toBe('#f7f7f5'); |
| 106 | expect(startfarbeFuer('system', signale({ bevorzugtDunkel: true }))).toBe('#14161a'); |
| 107 | }); |
| 108 | |
| 109 | it('nimmt bei erzwungenen Farben die Farben des Betriebssystems', () => { |
| 110 | /* Dort greift tokens.css auf `Canvas` zurück; ein helles Kontrastdesign |
| 111 | ist weiß. Eine eigene Farbe wäre hier falsch – auch dann, wenn jemand |
| 112 | „Dunkel“ eingestellt hat. */ |
| 113 | expect(startfarbeFuer('dunkel', signale({ erzwungeneFarben: true }))).toBe('#ffffff'); |
| 114 | expect(startfarbeFuer('hell', signale({ erzwungeneFarben: true, bevorzugtDunkel: true }))).toBe( |
| 115 | '#000000', |
| 116 | ); |
| 117 | }); |
| 118 | |
| 119 | /* Dass diese drei Farben mit `--farbe-grund` in tokens.css übereinstimmen, |
| 120 | prüft `tests/token-kontraste.test.ts` – dort liegt der Leser für die |
| 121 | CSS-Datei bereits. */ |
| 122 | }); |
| 123 | |
| 124 | describe('umschaltAnsage', () => { |
| 125 | it('nennt bei "system" das tatsächlich aktive Theme', () => { |
| 126 | expect(umschaltAnsage('system', 'dunkel')).toContain('Systemvorgabe'); |
| 127 | expect(umschaltAnsage('system', 'dunkel')).toContain('Dunkel'); |
| 128 | }); |
| 129 | |
| 130 | it('nennt bei manueller Wahl die gewählte Darstellung', () => { |
| 131 | expect(umschaltAnsage('hochkontrast', 'hochkontrast')).toBe( |
| 132 | 'Darstellung umgestellt auf Hoher Kontrast.', |
| 133 | ); |
| 134 | }); |
| 135 | |
| 136 | /* |
| 137 | Läuft das Windows-Kontrastdesign, hat `themeAufloesen` unbedingten |
| 138 | Vorrang: Die Wahl wird gespeichert, sichtbar wird sie nicht. Bis 0.24.1 |
| 139 | meldete die Ansage trotzdem „Darstellung umgestellt auf Dunkel“ – für |
| 140 | jemanden, der die Umstellung nicht sehen kann, die irreführendste |
| 141 | Auskunft, die dort stehen kann. |
| 142 | */ |
| 143 | it('behauptet bei erzwungenen Farben keine Umstellung, die nicht stattfindet', () => { |
| 144 | const ansage = umschaltAnsage('dunkel', 'hochkontrast', signale({ erzwungeneFarben: true })); |
| 145 | |
| 146 | expect(ansage).not.toContain('umgestellt'); |
| 147 | expect(ansage).toContain('gespeichert'); |
| 148 | expect(ansage).toContain('Kontrastdesign'); |
| 149 | expect(ansage).toContain('Dunkel'); |
| 150 | }); |
| 151 | }); |