lsa-planer
LSA-Planer Professional – Planungssoftware für Lichtsignalanlagen nach RiLSA 2015 und § 45 StVO. EUPL-1.2.
/ tests electron brueckeVersion.test.ts
| 1 | import { describe, expect, it } from 'vitest'; |
| 2 | import { readFileSync } from 'node:fs'; |
| 3 | import path from 'node:path'; |
| 4 | |
| 5 | /** |
| 6 | * Befund B5: die Bruecke meldete eine erfundene Version. |
| 7 | * |
| 8 | * In electron/preload.ts stand acht Fassungen lang |
| 9 | * |
| 10 | * appVersion: process.env['LSA_APP_VERSION'] ?? '5.0.0', |
| 11 | * |
| 12 | * Die Umgebungsvariable wird nirgends gesetzt - nicht im Hauptprozess, nicht in |
| 13 | * einem npm-Skript, nicht bei electron-builder. Der Rueckfall griff also immer, |
| 14 | * und die Bruecke gab noch in 5.7.0 "5.0.0" heraus. Aufgefallen ist das nicht, |
| 15 | * weil den Wert kein Aufrufer las: Die Versionsangabe der Statusleiste kommt aus |
| 16 | * `__APP_VERSION__`, das vite.config.ts aus package.json einsetzt. |
| 17 | * |
| 18 | * Deshalb wurde das Feld ENTFERNT und nicht aus `app.getVersion()` gespeist: Ein |
| 19 | * zweiter Weg zur selben Angabe ist eine zweite Gelegenheit, eine andere Zahl zu |
| 20 | * melden - genau das, was vite.config.ts unter "Programmversion - eine Quelle, |
| 21 | * nicht zwei" schon einmal abgestellt hat. |
| 22 | * |
| 23 | * Diese Pruefung faellt gegen den Stand von 5.7.0: Dort steht die |
| 24 | * Umgebungsvariable samt fester Zahl noch in der Datei. |
| 25 | * |
| 26 | * OFFEN und ausserhalb dieser Datei: src/platform/bridge.ts erklaert in |
| 27 | * `DesktopBridge` weiterhin ein `readonly appVersion: string`, und |
| 28 | * tests/ui/luftbildKacheln.test.ts fuellt es in seinem Ersatzobjekt. Solange |
| 29 | * beides steht, verspricht der Typ ein Feld, das die Bruecke nicht mehr liefert. |
| 30 | * Beide Zeilen gehoeren mit weg; hier wird das nicht geprueft, weil diese |
| 31 | * Pruefung sonst gegen den heutigen Stand faellt, ohne dass etwas kaputt waere. |
| 32 | */ |
| 33 | |
| 34 | const WURZEL = process.cwd(); |
| 35 | |
| 36 | function lies(...teile: readonly string[]): string { |
| 37 | return readFileSync(path.join(WURZEL, ...teile), 'utf8'); |
| 38 | } |
| 39 | |
| 40 | /** |
| 41 | * Kommentare heraus, bevor gesucht wird. |
| 42 | * |
| 43 | * Der Kopf von preload.ts erklaert in Worten, warum es `appVersion` nicht mehr |
| 44 | * gibt - eine Suche ueber den rohen Text fiele genau darueber und meldete das |
| 45 | * entfernte Feld als vorhanden. |
| 46 | */ |
| 47 | function ohneKommentare(quelltext: string): string { |
| 48 | return quelltext.replace(/\/\*[\s\S]*?\*\//g, '').replace(/(^|[^:])\/\/.*$/gm, '$1'); |
| 49 | } |
| 50 | |
| 51 | const PRELOAD = lies('electron', 'preload.ts'); |
| 52 | const PRELOAD_CODE = ohneKommentare(PRELOAD); |
| 53 | |
| 54 | describe('Bruecke: Programmversion', () => { |
| 55 | it('bietet dem Renderer kein appVersion-Feld an', () => { |
| 56 | expect(PRELOAD_CODE).not.toMatch(/\bappVersion\b/); |
| 57 | }); |
| 58 | |
| 59 | it('liest keine Umgebungsvariable LSA_APP_VERSION', () => { |
| 60 | expect(PRELOAD_CODE).not.toMatch(/LSA_APP_VERSION/); |
| 61 | }); |
| 62 | |
| 63 | it('trägt überhaupt keine fest eingetragene Versionsnummer', () => { |
| 64 | // Auch nicht als Rueckfall: Eine feste Zahl im Quelltext wird still falsch, |
| 65 | // sobald package.json weiterzaehlt - und niemand merkt es. |
| 66 | expect(PRELOAD_CODE).not.toMatch(/['"]\d+\.\d+\.\d+/); |
| 67 | }); |
| 68 | |
| 69 | it('setzt die Umgebungsvariable auch sonst nirgends im Quellstand', () => { |
| 70 | // Sie war nie gesetzt - das war der Kern des Befundes. Wer sie wieder |
| 71 | // einfuehrt, soll hier stolpern und stattdessen app.getVersion() nehmen. |
| 72 | for (const datei of [ |
| 73 | ['package.json'], |
| 74 | ['vite.config.ts'], |
| 75 | ['electron', 'main.ts'], |
| 76 | ['electron', 'preload.ts'], |
| 77 | ['src', 'main.ts'], |
| 78 | ]) { |
| 79 | // Ohne Kommentare: preload.ts nennt den Namen im Kopf, um zu erklaeren, |
| 80 | // warum es ihn nicht mehr auswertet. Gesucht ist Quelltext, nicht Prosa. |
| 81 | expect( |
| 82 | ohneKommentare(lies(...datei)), |
| 83 | `${datei.join('/')} nennt LSA_APP_VERSION`, |
| 84 | ).not.toMatch(/LSA_APP_VERSION/); |
| 85 | } |
| 86 | }); |
| 87 | }); |
| 88 | |
| 89 | describe('Programmversion: eine Quelle', () => { |
| 90 | it('kommt aus package.json und wird von vite als __APP_VERSION__ eingesetzt', () => { |
| 91 | const vite = lies('vite.config.ts'); |
| 92 | expect(vite).toMatch(/readFileSync\([^)]*package\.json/); |
| 93 | expect(vite).toMatch(/__APP_VERSION__:\s*JSON\.stringify\(VERSION\)/); |
| 94 | }); |
| 95 | |
| 96 | it('wird im Renderer aus genau dieser Konstanten genommen', () => { |
| 97 | /* |
| 98 | * NACHGEZOGEN AM 10.09.2026 (Fassung 5.26.0): Die Aufloesung stand bis |
| 99 | * dahin in src/main.ts, weil allein das "Ueber"-Fenster sie brauchte. Seit |
| 100 | * die gedruckte Planunterlage die Fassung nennt, braucht sie ein zweiter |
| 101 | * Aufrufer, und zwei Aufloesungen waeren zwei Stellen fuer dieselbe Zahl. |
| 102 | * Sie steht jetzt in src/fassung.ts; main.ts holt sie von dort. |
| 103 | */ |
| 104 | const fassung = ohneKommentare(lies('src', 'fassung.ts')); |
| 105 | expect(fassung).toMatch(/APP_VERSION =[^;]*__APP_VERSION__/); |
| 106 | |
| 107 | const rendererCode = ohneKommentare(lies('src', 'main.ts')); |
| 108 | expect(rendererCode, 'main.ts loest die Nummer nicht mehr selbst auf').not.toMatch( |
| 109 | /const APP_VERSION = [^\n]*__APP_VERSION__/, |
| 110 | ); |
| 111 | expect(rendererCode).toMatch(/import \{ APP_VERSION \} from '\.\/fassung'/); |
| 112 | // Die Statusleiste bekommt sie ueber die Shell - nicht ueber die Bruecke. |
| 113 | expect(rendererCode).toMatch(/new Shell\([^)]*APP_VERSION/); |
| 114 | }); |
| 115 | |
| 116 | it('nimmt die Planunterlage sie aus derselben Stelle', () => { |
| 117 | /* |
| 118 | * Die eigentliche Zusage dieser Aenderung: Die gedruckte Unterlage nennt die |
| 119 | * Fassung, und zwar dieselbe, die im "Ueber"-Fenster steht. Ein zweiter |
| 120 | * Rueckfallwert im Ausdruck waere genau der Widerspruch, den diese Datei |
| 121 | * verhindern soll. |
| 122 | */ |
| 123 | const ausdruck = ohneKommentare(lies('src', 'services', 'export', 'pdf.ts')); |
| 124 | expect(ausdruck).toMatch(/import \{ FASSUNGSANGABE \} from '@\/fassung'/); |
| 125 | expect(ausdruck, 'die Zeile auf dem Deckblatt').toMatch(/'Programmfassung', FASSUNGSANGABE/); |
| 126 | expect(ausdruck, 'kein eigener Rueckfall im Ausdruck').not.toMatch(/__APP_VERSION__/); |
| 127 | }); |
| 128 | |
| 129 | it('steht in package.json als vollständige Versionsnummer', () => { |
| 130 | const paket = JSON.parse(lies('package.json')) as { version?: unknown }; |
| 131 | expect(typeof paket.version).toBe('string'); |
| 132 | expect(paket.version).toMatch(/^\d+\.\d+\.\d+/); |
| 133 | }); |
| 134 | }); |