Files
rippy/rippy-windows/test/speicher.test.ts
HitonabiandClaude Fable 5.1 3dc6798c79 feat(v5): 5.5.0 — Kern und Oberfläche aufgeteilt, Übersicht und Einstellungen neu, Erst-Einrichtung mit Poster-Kulisse
Commander-Wünsche vom 02.09.2026 vor der Freigabe von 5.4.0 (die deshalb nie
veröffentlicht wurde):

Kern: kern/index.ts ist nur noch Bootstrap und Router; Dienste in
kern/dienste/ (Einstellungen, Werkzeuge, Laufwerke, Erkennung, Vorgänge,
Speicher, Benachrichtigung, Automatik), Kontext in kern/kontext.ts,
Protokoll-Datei in gemeinsam/protokoll.ts, Platz-Rechnung in gemeinsam/platz.ts.

Oberfläche: fenster/App.tsx ist nur noch der Rahmen; bausteine.tsx, dialoge/,
uebersicht/ (LaufwerkKachel, KompressionsKarte, SpeicherKarte, VerlaufKarte),
einstellungen/ (Karten je Funktion, SprachAuswahl), einrichtung/
(ErstEinrichtung, PosterHintergrund).

Neu: Bibliothek weg, dafür Verlauf; Speicher-und-Bilanz-Karte (statfs);
LED-Fußleiste; MakeMKV-Kopf in die Einstellungen; Sprach-Chips mit Dropdown
statt Allgemeinem Preset; Karten Automatik/Benachrichtigung/Allgemein/Update;
Durchsuchen bei Werkzeugen; Arbeitsordner lokal (Encode dort, dann in die
Ablage); Platz-Prüfung vor dem Rip (Dialog und Kern); Automatik mit Countdown;
Serien-Merker über Discs; Rettungs-Abbild mit Nullen nur nach gesehenen
Lesefehlern (kern/rip/rettung.ts, Phase rettet, iso:-Quelle); Warteschlange
pausieren; Discord/Telegram-Benachrichtigung; Protokoll-Datei je Tag;
Fensterlage 80 % mittig, gemerkt; Erst-Einrichtung in acht Schritten vor dem
Poster-Grid.

Beweise: 413 Tests (neu: speicher, benachrichtigung, automatik, rettung,
fensterlage, protokoll, kleinkram-550), drei Typprüfungen, Klick-Beweis mit
29 Schritten inklusive Erst-Einrichtung (zweiter Start mit
RIPPY_START_BEREICH=einrichtung), Bilder beweise/klick/01…09.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 17:51:15 +02:00

68 lines
3.0 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Tests des freien Platzes (kern/dienste/speicher.ts, 5.5.0): der nächste
// vorhandene Elternpfad, die Messung mit nachgebautem statfs, das Urteil
// vor dem Rip. Der echte statfs-Aufruf ist am 01.09.2026 gemessen (siehe
// Kopf der Datei) — hier zählt die Rechnung. Die Pfade stehen mit
// Schrägstrichen: dirname versteht sie auf Windows UND auf dem Linux-Runner
// der CI gleich.
import { describe, expect, it } from 'vitest'
import { platzMessen, platzUrteil, vorhandenerPfad } from '../src/kern/dienste/speicher'
describe('vorhandenerPfad', () => {
it('nimmt den Ordner selbst, wenn es ihn gibt', () => {
expect(vorhandenerPfad('X:/rippy/ablage', (p) => p === 'X:/rippy/ablage')).toBe('X:/rippy/ablage')
})
it('geht hoch bis zum ersten vorhandenen Elternpfad — die Ablage darf noch fehlen', () => {
const da = new Set(['X:/', 'X:/rippy'])
expect(vorhandenerPfad('X:/rippy/ablage/Filme', (p) => da.has(p))).toBe('X:/rippy')
})
it('bleibt an der Wurzel stehen, wenn nichts existiert (Windows: Q:/ — auf dem Linux-Runner endet dirname bei „.")', () => {
expect(vorhandenerPfad('Q:/gibt/es/nicht', () => false)).toBe(process.platform === 'win32' ? 'Q:/' : '.')
})
})
describe('platzMessen', () => {
it('rechnet bavail × bsize und blocks × bsize', () => {
const platz = platzMessen('X:/rippy', () => ({ bavail: 1000, bsize: 4096, blocks: 5000 }), () => true)
expect(platz).toEqual({ pfad: 'X:/rippy', ok: true, freiBytes: 4_096_000, gesamtBytes: 20_480_000, fehler: '' })
})
it('ein leerer Pfad ist nicht messbar — und sagt es (R2)', () => {
const platz = platzMessen(' ', () => ({ bavail: 1, bsize: 1, blocks: 1 }))
expect(platz.ok).toBe(false)
expect(platz.fehler).toBe('kein Pfad')
})
it('ein Fehler der Messung wird zum Grund, nie zu einer erfundenen Null', () => {
const platz = platzMessen(
'Z:/weg',
() => {
throw new Error('ENOENT: no such file or directory')
},
() => true,
)
expect(platz.ok).toBe(false)
expect(platz.freiBytes).toBe(0)
expect(platz.fehler).toContain('ENOENT')
})
})
describe('platzUrteil', () => {
const GB = 1e9
it('reicht: Roh plus 25 % plus 2 GB Luft passen', () => {
expect(platzUrteil(60 * GB, 40 * GB, true)).toEqual({ text: '', hart: false })
})
it('knapp: der Rip passt, die Kompression nicht mehr sicher', () => {
const urteil = platzUrteil(45 * GB, 40 * GB, true)
expect(urteil.hart).toBe(false)
expect(urteil.text.startsWith('Knapp')).toBe(true)
expect(urteil.text).toContain('45,0 GB frei')
})
it('zu wenig: nicht einmal der verlustfreie Rip passt', () => {
const urteil = platzUrteil(30 * GB, 40 * GB, false)
expect(urteil.hart).toBe(true)
expect(urteil.text.startsWith('Zu wenig Platz')).toBe(true)
})
it('ohne Kompression zählt nur Roh plus Luft', () => {
expect(platzUrteil(43 * GB, 40 * GB, false).text).toBe('')
expect(platzUrteil(43 * GB, 40 * GB, true).text.startsWith('Knapp')).toBe(true)
})
})