lsa-planer
LSA-Planer Professional – Planungssoftware für Lichtsignalanlagen nach RiLSA 2015 und § 45 StVO. EUPL-1.2.
/ vitest.config.ts
| 1 | import { coverageConfigDefaults, defineConfig } from 'vitest/config'; |
| 2 | import { fileURLToPath, URL } from 'node:url'; |
| 3 | |
| 4 | /* |
| 5 | * DIE ABDECKUNGSMESSUNG - Umfang, Ausnahme, Schwellen. |
| 6 | * |
| 7 | * Bis 5.13.0 mass sie nur `src/domain/**` und `src/services/**`, und Schwellen |
| 8 | * gab es keine. Beides ist geaendert; die Begruendung steht hier, weil sie an |
| 9 | * keiner anderen Stelle sinnvoll steht. |
| 10 | * `tests/tools/abdeckungsmessung.test.ts` haelt die Zusagen dieses |
| 11 | * Kommentars fest - es faehrt keine Messung, sondern prueft Datei fuer Datei, |
| 12 | * dass der Umfang jede Quelldatei des Baumes erfasst, dass jeder Bereich eine |
| 13 | * Schwelle hat, dass keine gesenkt wurde und dass die Schnellstufe die Messung |
| 14 | * ueberhaupt faehrt. |
| 15 | * |
| 16 | * WAS GEMESSEN WIRD. Alles, was ausgeliefert wird oder ein versioniertes |
| 17 | * Erzeugnis herstellt: `src/**` (Renderer samt Oberflaeche, Ausdruck und |
| 18 | * Einstiegspunkt), `shared/**` (die IPC-Kanaele), `electron/**` (Hauptprozess) |
| 19 | * und `tools/**` (erzeugt `beispiele/*.svg`). |
| 20 | * |
| 21 | * WAS NICHT GEMESSEN WIRD - und warum das keine Beschoenigung ist: |
| 22 | * |
| 23 | * - `scripts/*.mjs` (clean, lizenztexte, pruefsummen) laufen als EIGENER |
| 24 | * Prozess. `tests/tools/` startet sie mit `spawnSync` und misst ihre |
| 25 | * Wirkung; die v8-Messung dieses Prozesses sieht davon nichts und wuerde |
| 26 | * sie mit 0 % fuehren. Eine Null, die nur sagt "hier misst das Werkzeug |
| 27 | * nicht", verwaessert jede Zahl daneben. |
| 28 | * |
| 29 | * - `electron/preload.ts` ist die einzige namentliche Ausnahme. Die Datei |
| 30 | * laeuft ausschliesslich im Preload-Zusammenhang von Electron unter |
| 31 | * `sandbox: true` und ruft beim Laden `contextBridge.exposeInMainWorld` auf; |
| 32 | * unter Vitest ist sie nicht einbindbar. Ihre 0 % waeren keine Messung, |
| 33 | * sondern eine Eigenschaft des Messgeraets - mitgezaehlt druecken sie |
| 34 | * `electron/**` von 83,58 auf 79,02 % und setzten die Schwelle fuer die |
| 35 | * sechs messbaren Dateien um viereinhalb Punkte zu tief. Geprueft ist sie |
| 36 | * trotzdem, an zwei Stellen: `tests/electron/brueckeVersion.test.ts` liest |
| 37 | * ihren Quelltext, und `e2e/rauchtest.spec.ts` prueft am GEBAUTEN Stand, |
| 38 | * dass die Bruecke vollstaendig freigegeben ist. Der Test zur |
| 39 | * Abdeckungsmessung laesst die Ausnahme nur gelten, solange diese beiden |
| 40 | * Wachen stehen. |
| 41 | * |
| 42 | * WAS DIE MESSUNG VERZERRT - benannt, nicht weggerechnet: |
| 43 | * |
| 44 | * - `electron/main.ts` steht bei 74,59 %. Die Luecke ist fast vollstaendig |
| 45 | * `createWindow` samt seinen Ereignisbehandlungen (`render-process-gone`, |
| 46 | * `zoom-changed`, `unresponsive`). Sie brauchen ein laufendes Fenster. |
| 47 | * |
| 48 | * HIER STANDEN AUCH `will-navigate` UND `setWindowOpenHandler`, mit dem |
| 49 | * Zusatz "genau das prueft `e2e/rauchtest.spec.ts` am gebauten Stand". |
| 50 | * GEMESSEN: Der Rauchtest hatte sechs Faelle, und das Wort "navigate" kam |
| 51 | * darin nicht vor. Eine Abdeckungsausnahme, gedeckt von einem Test, den es |
| 52 | * nicht gab - und das an den beiden Wachen, die verhindern, dass das |
| 53 | * Programm verlassen wird. |
| 54 | * |
| 55 | * Beide sind seither anders gebaut: Die Entscheidung steht als reine |
| 56 | * Funktion in `electron/navigation.ts`, wird von |
| 57 | * `tests/tools/navigationGrenze.test.ts` erschoepfend geprueft und faellt |
| 58 | * damit IN die Abdeckung; in `main.ts` blieb nur die Verdrahtung. Dass sie |
| 59 | * greift, prueft der Rauchtest jetzt wirklich - mit einer `http:`-Adresse, |
| 60 | * weil eine `https:`-Adresse bei jedem Lauf einen Browser oeffnen wuerde. |
| 61 | * |
| 62 | * - `src/main.ts` steht bei 81,38 %. Ungemessen sind die Verdrahtungen der |
| 63 | * Dateibefehle (Oeffnen, Speichern, Speichern unter); sie brauchen die |
| 64 | * Desktop-Bruecke und einen Dateidialog. |
| 65 | * |
| 66 | * - `src/platform/**` sind sechs ausfuehrbare Zeilen und zwei Funktionen in |
| 67 | * einer sonst reinen Typdatei. Die 66,66 % entstehen daraus, dass |
| 68 | * `hasDesktopBridge` von niemandem aufgerufen wird. Die Zahl ist richtig, |
| 69 | * aber sie sagt ueber die Pruefdichte nichts - eine einzige Zeile |
| 70 | * verschiebt sie um 16 Punkte. |
| 71 | * |
| 72 | * WIE DIE SCHWELLEN ENTSTANDEN SIND. Eine Schwelle hat eine Aufgabe: fallen, |
| 73 | * wenn die Abdeckung SINKT. Sie steht deshalb nicht auf einer runden Zahl, |
| 74 | * sondern knapp unter dem gemessenen Stand - abgerundet auf eine |
| 75 | * Nachkommastelle, davon noch ein Zehntelpunkt Luft. Je Bereich eine eigene |
| 76 | * Schwelle, sonst deckt `src/domain/**` die Oberflaeche zu. Die Werte unten |
| 77 | * sind am Stand 5.13.0 gemessen. |
| 78 | * |
| 79 | * WARUM UEBERHAUPT LUFT. Gar keine waere unzuverlaessig: Vier Laeufe ueber |
| 80 | * denselben Baum lieferten fuer Zeilen und Funktionen jedes Mal dieselben |
| 81 | * Zahlen, bei den ZWEIGEN aber wechselnde - `src/app/**` zaehlte zweimal 219 |
| 82 | * von 238 und zweimal 218 von 237, also 92,01 gegen 91,98 %. Die Luft deckt |
| 83 | * diese Streuung ab und sonst wenig: Sie betraegt einen bis zwei |
| 84 | * Zehntelpunkte, in `src/domain/**` achtzehn Zeilen von 9803, in `src/ui/**` |
| 85 | * zwanzig von 11544. Mehr waere die Erlaubnis, Pruefung abzubauen. |
| 86 | * |
| 87 | * WELCHE SCHWELLENARTEN. `lines` und `statements` liefern unter dem |
| 88 | * v8-Anbieter in JEDEM Bereich denselben Wert (nachgemessen; v8-to-istanbul |
| 89 | * bildet je Anweisung genau einen Zeilenbereich). Deshalb steht hier nur |
| 90 | * `lines` - eine zweite Zahl daneben bewachte dasselbe zweimal. `branches` und |
| 91 | * `functions` sagen etwas anderes und stehen einzeln. |
| 92 | * |
| 93 | * NEU MESSEN: Wert im Zweifel auf 100 setzen, `npm run test:coverage` fahren |
| 94 | * und die Zeile "ERROR: Coverage for ... does not meet ..." lesen - sie nennt |
| 95 | * den gemessenen Wert je Bereich. Kein `thresholds.autoUpdate`: Das schriebe |
| 96 | * waehrend des pre-commit-Hakens in diese Datei und veraenderte die Wache |
| 97 | * unbemerkt. |
| 98 | */ |
| 99 | export default defineConfig({ |
| 100 | resolve: { |
| 101 | alias: { |
| 102 | '@': fileURLToPath(new URL('./src', import.meta.url)), |
| 103 | '@shared': fileURLToPath(new URL('./shared', import.meta.url)), |
| 104 | }, |
| 105 | }, |
| 106 | test: { |
| 107 | globals: true, |
| 108 | environment: 'node', |
| 109 | include: ['tests/**/*.test.ts'], |
| 110 | environmentMatchGlobs: [ |
| 111 | ['tests/ui/**', 'jsdom'], |
| 112 | ['tests/export/**', 'jsdom'], |
| 113 | ], |
| 114 | coverage: { |
| 115 | provider: 'v8', |
| 116 | include: ['src/**', 'shared/**', 'electron/**', 'tools/**'], |
| 117 | exclude: [...coverageConfigDefaults.exclude, 'electron/preload.ts'], |
| 118 | reporter: ['text', 'html'], |
| 119 | /* |
| 120 | * Auch bei rotem Lauf messen. |
| 121 | * |
| 122 | * Ohne diese Zeile bricht vitest nach einem gefallenen Fall ab, ohne |
| 123 | * Bericht und ohne Vergleich mit den Schwellen (nachgefahren am |
| 124 | * 07.09.2026). Ein roter Lauf faellt ohnehin - aber solange ein FREMDER |
| 125 | * Fall rot ist, liesse sich nicht mehr belegen, dass die Schwellen halten, |
| 126 | * und genau das braucht man waehrend einer Behebung. |
| 127 | */ |
| 128 | reportOnFailure: true, |
| 129 | thresholds: { |
| 130 | // Auffangnetz fuer alles, was unten keinen eigenen Eintrag hat - etwa |
| 131 | // eine neue Datei unmittelbar unter src/. |
| 132 | lines: 93.4, |
| 133 | branches: 89.0, |
| 134 | functions: 90.4, |
| 135 | |
| 136 | 'src/domain/**': { lines: 96.3, branches: 91.4, functions: 97.1 }, |
| 137 | 'src/services/**': { lines: 95.7, branches: 89.8, functions: 97.6 }, |
| 138 | 'src/app/**': { lines: 94.4, branches: 91.8, functions: 93.7 }, |
| 139 | 'src/render/**': { lines: 99.1, branches: 92.5, functions: 99.9 }, |
| 140 | 'src/ui/**': { lines: 91.3, branches: 86.0, functions: 84.1 }, |
| 141 | |
| 142 | // Sechs Zeilen, zwei Funktionen - siehe "Was die Messung verzerrt". |
| 143 | // Der Eintrag steht trotzdem hier: unter dem Auffangnetz waere der |
| 144 | // schwaechste Bereich des Baumes unsichtbar. |
| 145 | 'src/platform/**': { lines: 66.5, branches: 49.9, functions: 49.9 }, |
| 146 | |
| 147 | // Der Einstiegspunkt des Renderers, als einzelne Datei. |
| 148 | 'src/main.ts': { lines: 81.2, branches: 75.6, functions: 74.9 }, |
| 149 | |
| 150 | // shared/ipc.ts hat keine Zweige und keine Funktionen; 0 von 0 zaehlt |
| 151 | // istanbul als 100 %. Die Schwelle greift, sobald dort ein |
| 152 | // ungeprueftes Stueck Ablauflogik entsteht. |
| 153 | 'shared/**': { lines: 99.9, branches: 99.9, functions: 99.9 }, |
| 154 | |
| 155 | // Ohne preload.ts, siehe oben. |
| 156 | 'electron/**': { lines: 83.4, branches: 84.6, functions: 79.3 }, |
| 157 | |
| 158 | /* |
| 159 | * MIT 5.43.0 GESENKT, und zwar durch eine Behebung: Das Werkzeug gibt |
| 160 | * die Hinweise der Ableitung aus, und der Hinweis "einfahrweg-null" |
| 161 | * entstand an jeder Furt, solange der Einfahrweg einer Querung an der |
| 162 | * Zeichenrichtung hing. Seit die Vermessung die unguenstigere |
| 163 | * Gehrichtung nimmt, gibt es ihn dort nicht mehr; die Ausgabeschleife |
| 164 | * und der Zweig "keine Beziehung" werden vom Lauf des Werkzeugs nicht |
| 165 | * mehr genommen. Gemessen am 18.09.2026: 99,0 % Zeilen und 88,67 % |
| 166 | * Zweige statt 99,3 % und 89,5 %. Der Kode bleibt, denn ein Hinweis |
| 167 | * kann wiederkommen; die Schwelle folgt der Messung. |
| 168 | */ |
| 169 | 'tools/**': { lines: 98.9, branches: 88.5, functions: 99.9 }, |
| 170 | }, |
| 171 | }, |
| 172 | }, |
| 173 | }); |