waffensachkunde
Waffensachkunde – Lernsoftware für die Sachkundeprüfung nach § 7 WaffG. Barrierefrei, offline, EUPL-1.2.
| 1 | // @vitest-environment node |
| 2 | /** |
| 3 | * Prüfhilfen an der IPC-Grenze. |
| 4 | * |
| 5 | * `entschaerft` bereinigt alles, was aus dem Renderer in eine Fehlermeldung, |
| 6 | * ins Protokoll oder in einen Profilnamen gelangt. Die Funktion war bis zur |
| 7 | * Abnahme von keinem Test abgedeckt – und stand zugleich in zwei Fassungen im |
| 8 | * Baum, sodass eine Verschärfung nur an einer Stelle gegriffen hätte. |
| 9 | */ |
| 10 | |
| 11 | import { describe, expect, it } from 'vitest'; |
| 12 | |
| 13 | import { entschaerft } from '../src/main/eingaben'; |
| 14 | |
| 15 | describe('entschaerft', () => { |
| 16 | it('lässt harmlosen Text unangetastet', () => { |
| 17 | expect(entschaerft('Olaf Willerding')).toBe('Olaf Willerding'); |
| 18 | expect(entschaerft('Frage I.1-04 – Schusswaffen?')).toBe('Frage I.1-04 – Schusswaffen?'); |
| 19 | }); |
| 20 | |
| 21 | it('ersetzt klassische Steuerzeichen', () => { |
| 22 | expect(entschaerft('a\nb')).toBe('a?b'); |
| 23 | expect(entschaerft('a\rb')).toBe('a?b'); |
| 24 | expect(entschaerft('a\tb')).toBe('a?b'); |
| 25 | /* Als Escape-Sequenz und nicht als rohes Byte: Ein Nullzeichen in der |
| 26 | Datei macht sie für Git zur Binärdatei – kein Diff, keine |
| 27 | Zeilenenden-Normalisierung, keine Anzeige im Verlauf. Genau das war |
| 28 | hier bis Fassung 0.24.1 der Fall, und der Modulkopf von |
| 29 | `main/schema.ts` warnt an anderer Stelle ausdrücklich davor. */ |
| 30 | expect(entschaerft('a\u0000b')).toBe('a?b'); |
| 31 | expect(entschaerft('ab')).toBe('a?b'); |
| 32 | }); |
| 33 | |
| 34 | it('ersetzt Escape-Sequenzen, mit denen sich ein Terminal steuern lässt', () => { |
| 35 | // „[2J" löscht in vielen Terminals den Bildschirm. |
| 36 | expect(entschaerft('[2Jharmlos')).toBe('?[2Jharmlos'); |
| 37 | }); |
| 38 | |
| 39 | it('ersetzt bidirektionale Steuerzeichen', () => { |
| 40 | /* U+202E kehrt die Anzeigerichtung um. Ohne diese Reinigung könnte eine |
| 41 | Meldung etwas völlig anderes zeigen, als sie enthält. */ |
| 42 | expect(entschaerft('Dateignp.exe')).toBe('Datei?gnp.exe'); |
| 43 | expect(entschaerft('abc')).toBe('a?b?c'); |
| 44 | expect(entschaerft('abc')).toBe('a?b?c'); |
| 45 | }); |
| 46 | |
| 47 | it('ersetzt Zeilen- und Absatztrenner, die keine sind', () => { |
| 48 | // U+2028/U+2029 brechen eine Logzeile auf, ohne wie ein Umbruch auszusehen. |
| 49 | expect(entschaerft('a b')).toBe('a?b'); |
| 50 | expect(entschaerft('a b')).toBe('a?b'); |
| 51 | }); |
| 52 | |
| 53 | it('ersetzt den C1-Bereich und die Bytereihenfolge-Marke', () => { |
| 54 | expect(entschaerft('a b')).toBe('a?b'); |
| 55 | expect(entschaerft('ab')).toBe('a?b'); |
| 56 | }); |
| 57 | |
| 58 | it('kürzt auf 80 Zeichen', () => { |
| 59 | expect(entschaerft('x'.repeat(200))).toHaveLength(80); |
| 60 | }); |
| 61 | |
| 62 | it('zerteilt beim Kürzen kein Emoji', () => { |
| 63 | /* Nach UTF-16-Einheiten gekürzt bliebe ein halbes Surrogatpaar übrig – |
| 64 | eine ungültige Zeichenkette, die je nach Ausgabe als Fragezeichen oder |
| 65 | als Fehler erscheint. */ |
| 66 | expect(entschaerft('🔫'.repeat(100))).toBe('🔫'.repeat(80)); |
| 67 | }); |
| 68 | |
| 69 | it('zerlegt auch zusammengesetzte Zeichen nicht', () => { |
| 70 | /* Eine Flagge besteht aus zwei Regionalindikatoren, ein Buchstabe mit |
| 71 | Akzent aus Grundzeichen und Kombinationszeichen. Nach Codepoints |
| 72 | gekürzt zerfielen sie in ihre Bestandteile und zeigten etwas anderes |
| 73 | an als vorher. */ |
| 74 | expect(entschaerft('🇩🇪'.repeat(100))).toBe('🇩🇪'.repeat(80)); |
| 75 | expect(entschaerft('é'.repeat(100))).toBe('é'.repeat(80)); |
| 76 | }); |
| 77 | |
| 78 | it('nimmt ein eigenes Ersatzzeichen entgegen', () => { |
| 79 | expect(entschaerft('a\nb', '_')).toBe('a_b'); |
| 80 | expect(entschaerft('a\nb', '')).toBe('ab'); |
| 81 | }); |
| 82 | |
| 83 | it('macht aus Nicht-Zeichenketten eine lesbare Angabe', () => { |
| 84 | expect(entschaerft(42)).toBe('42'); |
| 85 | expect(entschaerft(null)).toBe('null'); |
| 86 | expect(entschaerft(undefined)).toBe('undefined'); |
| 87 | expect(entschaerft({ a: 1 })).toBe('[object Object]'); |
| 88 | }); |
| 89 | }); |