import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' import { chmod, mkdtemp, rm } from 'node:fs/promises' import { tmpdir } from 'node:os' import path from 'node:path' /** * Die Statusanzeige ist die einzige Stelle, an der ein stiller Ausfall * auffaellt, bevor jemand darueber stolpert. Beide Faelle, die es hier je * wirklich gab, stehen deshalb als Pruefung da: ein Virenscanner, der nicht * antwortet, und eine Dateiablage, in die der Dienst nicht schreiben darf. */ let ablage = '' vi.mock('@/lib/db', () => ({ db: { $queryRaw: vi.fn(async () => [{ '?column?': 1 }]), serviceHeartbeat: { findUnique: vi.fn(async () => ({ service: 'worker', status: 'up', detail: null, at: new Date() })) }, }, })) vi.mock('@/lib/env', () => ({ getEnv: () => ({ CLAMAV_ADDRESS: 'clamav:3310', FILES_DIR: ablage }), })) vi.mock('@/lib/files/clamav', () => ({ pingClamav: vi.fn(async () => true) })) describe('collectHealth', () => { beforeAll(async () => { ablage = await mkdtemp(path.join(tmpdir(), 'afis-ablage-')) }) afterAll(async () => { await chmod(ablage, 0o755).catch(() => undefined) await rm(ablage, { recursive: true, force: true }) }) it('meldet betriebsbereit, wenn alle Abhaengigkeiten antworten', async () => { const { collectHealth } = await import('@/lib/health/check') const report = await collectHealth() expect(report.status).toBe('up') expect(report.components.database.status).toBe('up') expect(report.components.discordGateway.status).toBe('up') expect(report.components.clamav.status).toBe('up') expect(report.components.fileStore.status).toBe('up') }) it('legt die beiden Verzeichnisse an, wenn sie fehlen', async () => { // Eine frische Ablage ist leer. Das ist kein Fehler, sondern der // Normalfall beim ersten Start. const { collectHealth } = await import('@/lib/health/check') const report = await collectHealth() expect(report.components.fileStore.status).toBe('up') }) it('meldet eine Ablage, in die der Dienst nicht schreiben darf', async () => { // Genau der Fehler, der jeden Upload scheitern liess: das Volume gehoerte // root, der Dienst laeuft als afis. Zu sehen war davon nichts. // // Nachgestellt wird ein **leeres**, gesperrtes Verzeichnis - so lag es // auch im Container. Ein Verzeichnis, in dem quarantine/ und store/ schon // stehen und beschreibbar sind, ist der Fall nicht: dann arbeitet der // Dienst weiter, und die Anzeige soll ihn auch nicht anschwaerzen. const vorher = ablage ablage = await mkdtemp(path.join(tmpdir(), 'afis-gesperrt-')) await chmod(ablage, 0o555) try { const { collectHealth } = await import('@/lib/health/check') const report = await collectHealth() expect(report.components.fileStore.status).toBe('down') expect(report.components.fileStore.detail).toContain('nicht beschreibbar') // Die Datenbank steht, also faellt nicht alles aus - aber betriebsbereit // ist es auch nicht. expect(report.status).toBe('degraded') } finally { await chmod(ablage, 0o755) await rm(ablage, { recursive: true, force: true }) ablage = vorher } }) it('bleibt nur eingeschraenkt, wenn allein die Virenpruefung ausfaellt', async () => { const clamav = await import('@/lib/files/clamav') vi.mocked(clamav.pingClamav).mockResolvedValueOnce(false) const { collectHealth } = await import('@/lib/health/check') const report = await collectHealth() expect(report.status).toBe('degraded') }) })