import { mkdtemp, readdir, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' /** * Die Bereitschaftsprüfung der Dateiablage. * * Bis v1.12.0 fiel eine kaputte Speicherkonfiguration erst auf, wenn * jemand ein Dokument ablegen wollte. Auf dem Livesystem waren das * mehrere Wochen nach der Installation — und dann mitten in der Arbeit, * mit einer Meldung, die nichts sagte. * * Die Prüfung schreibt eine winzige Datei, liest sie zurück und räumt sie * weg. Sie beantwortet damit drei Fragen auf einmal: erreichbar, * Ablagebereich vorhanden, Schreibrecht da. */ let verzeichnis = '' beforeEach(async () => { verzeichnis = await mkdtemp(join(tmpdir(), 'bc-pruefung-')) process.env.SPEICHER_TREIBER = 'datei' process.env.DATEI_SPEICHER_PFAD = verzeichnis vi.resetModules() }) afterEach(async () => { await rm(verzeichnis, { recursive: true, force: true }) delete process.env.SPEICHER_TREIBER delete process.env.DATEI_SPEICHER_PFAD vi.restoreAllMocks() }) describe('Bereitschaftsprüfung', () => { it('meldet eine benutzbare Ablage', async () => { const { speicherPruefen } = await import('@/lib/speicher/pruefung') const zustand = await speicherPruefen() expect(zustand.ok).toBe(true) expect(zustand.treiber).toBe('datei') }) it('lässt nichts liegen', async () => { // Eine Pruefung, die bei jedem Aufruf eine Datei zuruecklaesst, waere // nach einem Jahr Betrieb ein Verzeichnis voller Muell. const { speicherPruefen } = await import('@/lib/speicher/pruefung') await speicherPruefen() await speicherPruefen() await speicherPruefen() const inhalt = await readdir(join(verzeichnis, 'pruefung')).catch(() => []) expect(inhalt).toEqual([]) }) it('meldet einen Fehler, statt zu werfen', async () => { // Der Aufrufer ist die Gesundheitsauskunft. Wirft die Pruefung, ist // die Auskunft weg - und mit ihr die Erklaerung. // Eine Datei als Ablageverzeichnis: Das Anlegen des Unterordners // scheitert dann zuverlaessig und auf jedem System. const alsDatei = join(verzeichnis, 'keine-ablage') await writeFile(alsDatei, 'ich bin eine Datei') process.env.DATEI_SPEICHER_PFAD = alsDatei const { speicherPruefen } = await import('@/lib/speicher/pruefung') const zustand = await speicherPruefen() expect(zustand.ok).toBe(false) if (!zustand.ok) expect(zustand.meldung.length).toBeGreaterThan(10) }) }) describe('Gemerkter Zustand', () => { it('prüft nicht bei jedem Aufruf neu', async () => { // Der Healthcheck fragt alle 30 Sekunden. Ohne Schonfrist schriebe er // ebenso oft eine Probedatei in den Objektspeicher. const modul = await import('@/lib/speicher/pruefung') modul.zustandVergessen() const erste = await modul.speicherZustand() const zweite = await modul.speicherZustand() expect(zweite).toBe(erste) }) it('meldet denselben Zustand nicht wieder und wieder', async () => { const protokoll = vi.spyOn(console, 'log').mockImplementation(() => {}) const modul = await import('@/lib/speicher/pruefung') modul.zustandVergessen() await modul.speicherZustand() // Wie nach fuenf Minuten: neu pruefen, aber das Meldegedaechtnis bleibt. modul.schonfristUeberspringen() await modul.speicherZustand() // Zweimal geprueft, aber nur die erste Meldung - sonst stuende alle // fuenf Minuten dieselbe Zeile im Log und niemand liest sie mehr. const speicherzeilen = protokoll.mock.calls.filter((aufruf) => String(aufruf[0]).startsWith('[speicher]'), ) expect(speicherzeilen).toHaveLength(1) }) })