/** * Unit test for the filesystem (mounted-path / NAS) backup transport * (`src/lib/services/backup-destinations/filesystem.ts`). */ import { mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync, mkdirSync } from 'node:fs'; import { tmpdir } from 'node:os'; import path from 'node:path'; import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { FilesystemTransport } from '@/lib/services/backup-destinations/filesystem'; import { BACKUP_NAME_PREFIX } from '@/lib/services/backup-destinations/types'; describe('FilesystemTransport', () => { let work: string; let destDir: string; beforeEach(() => { work = mkdtempSync(path.join(tmpdir(), 'pn-fstr-')); destDir = path.join(work, 'backups'); mkdirSync(destDir); }); afterEach(() => { rmSync(work, { recursive: true, force: true }); }); it('test() rejects when the directory does not exist', async () => { const t = new FilesystemTransport({ directory: path.join(work, 'nope') }); await expect(t.test()).rejects.toThrow(); }); it('push() copies the bundle into the destination directory', async () => { const local = path.join(work, `${BACKUP_NAME_PREFIX}2026-06-04.tar`); writeFileSync(local, Buffer.from('BUNDLE-BYTES')); const t = new FilesystemTransport({ directory: destDir }); const res = await t.push(local, `${BACKUP_NAME_PREFIX}2026-06-04.tar`); expect(res.bytes).toBe('BUNDLE-BYTES'.length); const landed = readFileSync(path.join(destDir, `${BACKUP_NAME_PREFIX}2026-06-04.tar`), 'utf8'); expect(landed).toBe('BUNDLE-BYTES'); }); it('prune() keeps the N newest bundles and ignores unrelated files', async () => { // Five backups (timestamp-in-name sorts chronologically) + an unrelated file. for (const d of ['01', '02', '03', '04', '05']) { writeFileSync(path.join(destDir, `${BACKUP_NAME_PREFIX}2026-06-${d}.tar`), 'x'); } writeFileSync(path.join(destDir, 'unrelated-keepme.txt'), 'y'); const t = new FilesystemTransport({ directory: destDir }); const { deleted } = await t.prune(2); expect(deleted).toBe(3); const remaining = readdirSync(destDir).sort(); expect(remaining).toEqual([ `${BACKUP_NAME_PREFIX}2026-06-04.tar`, `${BACKUP_NAME_PREFIX}2026-06-05.tar`, 'unrelated-keepme.txt', ]); }); it('prune(null) keeps everything', async () => { for (const d of ['01', '02', '03']) { writeFileSync(path.join(destDir, `${BACKUP_NAME_PREFIX}2026-06-${d}.tar`), 'x'); } const t = new FilesystemTransport({ directory: destDir }); const { deleted } = await t.prune(null); expect(deleted).toBe(0); expect(readdirSync(destDir).length).toBe(3); }); });