Files
rippy/rippy-windows/test/db.test.ts
T
HitonabiandClaude Fable 5 c539e65cd2 feat(v5): Etappe W-0 — das Geruest steht
Electron 44 + TypeScript, drei Prozesse (haupt / kern als utilityProcess /
fenster mit React), Nachrichten-Schema mit Pruef-Funktionen, node:sqlite
als einzige Datenbank-Stelle (kern/speicher/db.ts, § 6.7), Prozess-Leine
im Haupt (Job Object aus beweise/leine.js — Begruendung fuer den Ort im
Dateikopf), MessagePort direkt Fenster<->Kern, Einzelinstanz-Sperre,
Kern-Neustart-Wache, strikte CSP im gebauten Fenster.

Wächter-Tests nach § 4.3: koffi nur an zwei benannten Orten (R1), kein
leerer catch und kein catch-mit-Leerwert (R2/R4), kein HTTP-Server
(§ 4.1), node:sqlite nur in db.ts (§ 6.7). Dazu Datenbank- und
Schema-Tests: 18/18 gruen, Typpruefung in drei Kontexten.

Der W-0-Beweis (npm run smoke, echtes Programm):
SMOKE: OK — fenster=geladen kern=pid:13676,node:24.18.1 datenbank=ok
leine=gesetzt pong=ok version=5.0.0-w0

Nachgemessen ausserdem: taskkill /F auf den Haupt-Prozess (ohne /T,
der Absturz-Fall aus rc10) — der Kern stirbt mit.

Bau-Fallen dokumentiert (BAUEN.md): npm 11 blockt Electrons
Install-Skript (§ 3.5), plugin-react 6 verlangt Vite 8 (deshalb 5.2),
TypeScript bewusst auf 5.9.3 gepinnt statt tsgo 7.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 16:53:30 +02:00

74 lines
2.9 KiB
TypeScript

// Tests für kern/speicher/db.ts — laufen mit dem System-Node (node:sqlite
// gibt es dort wie in Electrons Node, KONZEPT-WINDOWS.md § 3.4).
import { mkdtempSync, rmSync, existsSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, describe, expect, it } from 'vitest'
import { Datenbank } from '../src/kern/speicher/db'
let aufraeumen: Array<() => void> = []
afterEach(() => {
// LIFO — zuletzt Registriertes zuerst: die Datenbank muss ZU sein, bevor
// ihr Ordner gelöscht wird (Windows verweigert das Löschen offener Dateien).
for (const weg of aufraeumen.splice(0).reverse()) weg()
})
function frischerPfad(): string {
const ordner = mkdtempSync(join(tmpdir(), 'rippy-db-test-'))
aufraeumen.push(() => rmSync(ordner, { recursive: true, force: true }))
return join(ordner, 'unterordner', 'rippy.db')
}
describe('Datenbank', () => {
it('legt Datei samt fehlender Ordner an und meldet Schema-Version', () => {
const pfad = frischerPfad()
const db = new Datenbank(pfad)
aufraeumen.push(() => db.schliessen())
expect(existsSync(pfad)).toBe(true)
expect(db.schemaVersion()).toBe(1)
})
it('schreibt und liest eine Einstellung', () => {
const db = new Datenbank(':memory:')
aufraeumen.push(() => db.schliessen())
db.einstellungSchreiben('ablage', 'E:\\Rippy')
expect(db.einstellungLesen('ablage')).toBe('E:\\Rippy')
})
it('überschreibt eine vorhandene Einstellung', () => {
const db = new Datenbank(':memory:')
aufraeumen.push(() => db.schliessen())
db.einstellungSchreiben('ablage', 'C:\\alt')
db.einstellungSchreiben('ablage', 'E:\\neu')
expect(db.einstellungLesen('ablage')).toBe('E:\\neu')
})
it('unbekannter Schlüssel ist null, kein Fehler und kein Leerwert', () => {
// R2: „nicht gefunden" ist eine Aussage (null) — kein erfundener
// Leerstring, der als Wert gelesen würde.
const db = new Datenbank(':memory:')
aufraeumen.push(() => db.schliessen())
expect(db.einstellungLesen('gibt-es-nicht')).toBeNull()
})
it('bleibt über Schließen und Neuöffnen erhalten', () => {
const pfad = frischerPfad()
const erste = new Datenbank(pfad)
erste.einstellungSchreiben('letzter_start', '2026-08-30T12:00:00Z')
erste.schliessen()
const zweite = new Datenbank(pfad)
aufraeumen.push(() => zweite.schliessen())
expect(zweite.einstellungLesen('letzter_start')).toBe('2026-08-30T12:00:00Z')
})
it('wirft bei nicht anlegbarem Pfad, statt still weiterzumachen', () => {
// R4: Der Aufrufer (kern/index.ts) fängt das und MELDET es — aber die
// Datenbank selbst darf so einen Zustand nie verschlucken.
// NUL ist unter Windows als Ordnername unzulässig; unter Linux (CI)
// scheitert das Anlegen unterhalb einer Datei genauso zuverlässig.
const kaputt = join(process.platform === 'win32' ? 'C:\\NUL<>:' : '/dev/null/x', 'rippy.db')
expect(() => new Datenbank(kaputt)).toThrow()
})
})