import { coverageConfigDefaults, defineConfig } from 'vitest/config'; import { fileURLToPath, URL } from 'node:url'; /* * DIE ABDECKUNGSMESSUNG - Umfang, Ausnahme, Schwellen. * * Bis 5.13.0 mass sie nur `src/domain/**` und `src/services/**`, und Schwellen * gab es keine. Beides ist geaendert; die Begruendung steht hier, weil sie an * keiner anderen Stelle sinnvoll steht. * `tests/tools/abdeckungsmessung.test.ts` haelt die Zusagen dieses * Kommentars fest - es faehrt keine Messung, sondern prueft Datei fuer Datei, * dass der Umfang jede Quelldatei des Baumes erfasst, dass jeder Bereich eine * Schwelle hat, dass keine gesenkt wurde und dass die Schnellstufe die Messung * ueberhaupt faehrt. * * WAS GEMESSEN WIRD. Alles, was ausgeliefert wird oder ein versioniertes * Erzeugnis herstellt: `src/**` (Renderer samt Oberflaeche, Ausdruck und * Einstiegspunkt), `shared/**` (die IPC-Kanaele), `electron/**` (Hauptprozess) * und `tools/**` (erzeugt `beispiele/*.svg`). * * WAS NICHT GEMESSEN WIRD - und warum das keine Beschoenigung ist: * * - `scripts/*.mjs` (clean, lizenztexte, pruefsummen) laufen als EIGENER * Prozess. `tests/tools/` startet sie mit `spawnSync` und misst ihre * Wirkung; die v8-Messung dieses Prozesses sieht davon nichts und wuerde * sie mit 0 % fuehren. Eine Null, die nur sagt "hier misst das Werkzeug * nicht", verwaessert jede Zahl daneben. * * - `electron/preload.ts` ist die einzige namentliche Ausnahme. Die Datei * laeuft ausschliesslich im Preload-Zusammenhang von Electron unter * `sandbox: true` und ruft beim Laden `contextBridge.exposeInMainWorld` auf; * unter Vitest ist sie nicht einbindbar. Ihre 0 % waeren keine Messung, * sondern eine Eigenschaft des Messgeraets - mitgezaehlt druecken sie * `electron/**` von 83,58 auf 79,02 % und setzten die Schwelle fuer die * sechs messbaren Dateien um viereinhalb Punkte zu tief. Geprueft ist sie * trotzdem, an zwei Stellen: `tests/electron/brueckeVersion.test.ts` liest * ihren Quelltext, und `e2e/rauchtest.spec.ts` prueft am GEBAUTEN Stand, * dass die Bruecke vollstaendig freigegeben ist. Der Test zur * Abdeckungsmessung laesst die Ausnahme nur gelten, solange diese beiden * Wachen stehen. * * WAS DIE MESSUNG VERZERRT - benannt, nicht weggerechnet: * * - `electron/main.ts` steht bei 74,59 %. Die Luecke ist fast vollstaendig * `createWindow` samt seinen Ereignisbehandlungen (`render-process-gone`, * `zoom-changed`, `unresponsive`). Sie brauchen ein laufendes Fenster. * * HIER STANDEN AUCH `will-navigate` UND `setWindowOpenHandler`, mit dem * Zusatz "genau das prueft `e2e/rauchtest.spec.ts` am gebauten Stand". * GEMESSEN: Der Rauchtest hatte sechs Faelle, und das Wort "navigate" kam * darin nicht vor. Eine Abdeckungsausnahme, gedeckt von einem Test, den es * nicht gab - und das an den beiden Wachen, die verhindern, dass das * Programm verlassen wird. * * Beide sind seither anders gebaut: Die Entscheidung steht als reine * Funktion in `electron/navigation.ts`, wird von * `tests/tools/navigationGrenze.test.ts` erschoepfend geprueft und faellt * damit IN die Abdeckung; in `main.ts` blieb nur die Verdrahtung. Dass sie * greift, prueft der Rauchtest jetzt wirklich - mit einer `http:`-Adresse, * weil eine `https:`-Adresse bei jedem Lauf einen Browser oeffnen wuerde. * * - `src/main.ts` steht bei 81,38 %. Ungemessen sind die Verdrahtungen der * Dateibefehle (Oeffnen, Speichern, Speichern unter); sie brauchen die * Desktop-Bruecke und einen Dateidialog. * * - `src/platform/**` sind sechs ausfuehrbare Zeilen und zwei Funktionen in * einer sonst reinen Typdatei. Die 66,66 % entstehen daraus, dass * `hasDesktopBridge` von niemandem aufgerufen wird. Die Zahl ist richtig, * aber sie sagt ueber die Pruefdichte nichts - eine einzige Zeile * verschiebt sie um 16 Punkte. * * WIE DIE SCHWELLEN ENTSTANDEN SIND. Eine Schwelle hat eine Aufgabe: fallen, * wenn die Abdeckung SINKT. Sie steht deshalb nicht auf einer runden Zahl, * sondern knapp unter dem gemessenen Stand - abgerundet auf eine * Nachkommastelle, davon noch ein Zehntelpunkt Luft. Je Bereich eine eigene * Schwelle, sonst deckt `src/domain/**` die Oberflaeche zu. Die Werte unten * sind am Stand 5.13.0 gemessen. * * WARUM UEBERHAUPT LUFT. Gar keine waere unzuverlaessig: Vier Laeufe ueber * denselben Baum lieferten fuer Zeilen und Funktionen jedes Mal dieselben * Zahlen, bei den ZWEIGEN aber wechselnde - `src/app/**` zaehlte zweimal 219 * von 238 und zweimal 218 von 237, also 92,01 gegen 91,98 %. Die Luft deckt * diese Streuung ab und sonst wenig: Sie betraegt einen bis zwei * Zehntelpunkte, in `src/domain/**` achtzehn Zeilen von 9803, in `src/ui/**` * zwanzig von 11544. Mehr waere die Erlaubnis, Pruefung abzubauen. * * WELCHE SCHWELLENARTEN. `lines` und `statements` liefern unter dem * v8-Anbieter in JEDEM Bereich denselben Wert (nachgemessen; v8-to-istanbul * bildet je Anweisung genau einen Zeilenbereich). Deshalb steht hier nur * `lines` - eine zweite Zahl daneben bewachte dasselbe zweimal. `branches` und * `functions` sagen etwas anderes und stehen einzeln. * * NEU MESSEN: Wert im Zweifel auf 100 setzen, `npm run test:coverage` fahren * und die Zeile "ERROR: Coverage for ... does not meet ..." lesen - sie nennt * den gemessenen Wert je Bereich. Kein `thresholds.autoUpdate`: Das schriebe * waehrend des pre-commit-Hakens in diese Datei und veraenderte die Wache * unbemerkt. */ export default defineConfig({ resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)), '@shared': fileURLToPath(new URL('./shared', import.meta.url)), }, }, test: { globals: true, environment: 'node', include: ['tests/**/*.test.ts'], environmentMatchGlobs: [ ['tests/ui/**', 'jsdom'], ['tests/export/**', 'jsdom'], ], coverage: { provider: 'v8', include: ['src/**', 'shared/**', 'electron/**', 'tools/**'], exclude: [...coverageConfigDefaults.exclude, 'electron/preload.ts'], reporter: ['text', 'html'], /* * Auch bei rotem Lauf messen. * * Ohne diese Zeile bricht vitest nach einem gefallenen Fall ab, ohne * Bericht und ohne Vergleich mit den Schwellen (nachgefahren am * 07.09.2026). Ein roter Lauf faellt ohnehin - aber solange ein FREMDER * Fall rot ist, liesse sich nicht mehr belegen, dass die Schwellen halten, * und genau das braucht man waehrend einer Behebung. */ reportOnFailure: true, thresholds: { // Auffangnetz fuer alles, was unten keinen eigenen Eintrag hat - etwa // eine neue Datei unmittelbar unter src/. lines: 93.4, branches: 89.0, functions: 90.4, 'src/domain/**': { lines: 96.3, branches: 91.4, functions: 97.1 }, 'src/services/**': { lines: 95.7, branches: 89.8, functions: 97.6 }, 'src/app/**': { lines: 94.4, branches: 91.8, functions: 93.7 }, 'src/render/**': { lines: 99.1, branches: 92.5, functions: 99.9 }, 'src/ui/**': { lines: 91.3, branches: 86.0, functions: 84.1 }, // Sechs Zeilen, zwei Funktionen - siehe "Was die Messung verzerrt". // Der Eintrag steht trotzdem hier: unter dem Auffangnetz waere der // schwaechste Bereich des Baumes unsichtbar. 'src/platform/**': { lines: 66.5, branches: 49.9, functions: 49.9 }, // Der Einstiegspunkt des Renderers, als einzelne Datei. 'src/main.ts': { lines: 81.2, branches: 75.6, functions: 74.9 }, // shared/ipc.ts hat keine Zweige und keine Funktionen; 0 von 0 zaehlt // istanbul als 100 %. Die Schwelle greift, sobald dort ein // ungeprueftes Stueck Ablauflogik entsteht. 'shared/**': { lines: 99.9, branches: 99.9, functions: 99.9 }, // Ohne preload.ts, siehe oben. 'electron/**': { lines: 83.4, branches: 84.6, functions: 79.3 }, /* * MIT 5.43.0 GESENKT, und zwar durch eine Behebung: Das Werkzeug gibt * die Hinweise der Ableitung aus, und der Hinweis "einfahrweg-null" * entstand an jeder Furt, solange der Einfahrweg einer Querung an der * Zeichenrichtung hing. Seit die Vermessung die unguenstigere * Gehrichtung nimmt, gibt es ihn dort nicht mehr; die Ausgabeschleife * und der Zweig "keine Beziehung" werden vom Lauf des Werkzeugs nicht * mehr genommen. Gemessen am 18.09.2026: 99,0 % Zeilen und 88,67 % * Zweige statt 99,3 % und 89,5 %. Der Kode bleibt, denn ein Hinweis * kann wiederkommen; die Schwelle folgt der Messung. */ 'tools/**': { lines: 98.9, branches: 88.5, functions: 99.9 }, }, }, }, });