This commit is contained in:
seb
2026-10-14 03:07:21 +02:00
parent 1991c0b529
commit 6c821d381e
10 changed files with 607 additions and 124 deletions

View File

@@ -10,6 +10,8 @@ import {
startBackupService,
stopBackupService,
resolveBackupPaths,
listBackupVfsFiles,
recoverBackupVfsFile,
} from '../src/services/backupService.js';
import { closeStore } from '../src/db/store.js';
@@ -23,8 +25,9 @@ async function runTests() {
// 2. Execute a backup
console.log('\n[Test 1] Running createHourlyBackup()...');
const backupResult = await createHourlyBackup({ manual: true });
const backupResult = await createHourlyBackup();
assert(backupResult.success === true, 'Backup should report success');
assert(backupResult.manifest.manual === undefined, 'manual field should not exist in manifest');
console.log(`Backup created: ${backupResult.id}, size: ${(backupResult.totalSizeBytes / 1024 / 1024).toFixed(2)} MB`);
console.log(`Promoted to daily: ${backupResult.promotedDaily}, Promoted to monthly: ${backupResult.promotedMonthly}`);
@@ -64,8 +67,55 @@ async function runTests() {
assert(listing.monthly.length >= 1, 'Should have at least 1 monthly backup');
console.log(`Counts -> hourly: ${listing.counts.hourly}, daily: ${listing.counts.daily}, monthly: ${listing.counts.monthly}`);
// 4. Test Retention Pruning (exceeding 50 entries)
console.log('\n[Test 3] Testing retention pruning for > 50 entries...');
// 4. Test VFS listing and recovery from specific backup
console.log('\n[Test 3] Testing listBackupVfsFiles() and recoverBackupVfsFile()...');
const vfsListing = await listBackupVfsFiles({ backupId: backupResult.id, companyId: 1 });
assert(vfsListing.backupId === backupResult.id, 'backupId should match');
assert(vfsListing.companyId === 1, 'companyId should be 1');
assert(Array.isArray(vfsListing.files), 'files should be an array');
console.log(`Found ${vfsListing.files.length} VFS files in backup for company 1.`);
if (vfsListing.files.length > 0) {
const fileToRecover = vfsListing.files[0];
console.log(`Attempting recovery of ${fileToRecover.name}...`);
const recoverRes = await recoverBackupVfsFile({
backupId: backupResult.id,
companyId: 1,
filePath: fileToRecover.name,
});
assert(recoverRes.success === true, 'Recovery should succeed');
assert(recoverRes.path === fileToRecover.name, 'Recovered path should match');
assert(recoverRes.sizeBytes > 0, 'Recovered size should be > 0');
const recoveredDiskPath = path.resolve(paths.vfsDir, '1', fileToRecover.name);
assert(fs.existsSync(recoveredDiskPath), 'Recovered file should exist on disk');
console.log(`Successfully recovered ${fileToRecover.name} (${recoverRes.sizeBytes} bytes).`);
}
// Test error cases
let backupNotFound = false;
try {
await listBackupVfsFiles({ backupId: 'backup-nonexistent', companyId: 1 });
} catch (e) {
if (e.message === 'Backup not found') backupNotFound = true;
}
assert(backupNotFound, 'Should throw Backup not found for invalid backupId');
let fileNotFound = false;
try {
await recoverBackupVfsFile({
backupId: backupResult.id,
companyId: 1,
filePath: 'completely-nonexistent-file.xyz',
});
} catch (e) {
if (e.message === 'File not found in backup') fileNotFound = true;
}
assert(fileNotFound, 'Should throw File not found in backup for invalid file');
console.log('VFS listing and recovery tests passed.');
// 5. Test Retention Pruning (exceeding 50 entries)
console.log('\n[Test 4] Testing retention pruning for > 50 entries...');
// Create dummy hourly backup folders
for (let i = 1; i <= 55; i++) {
const dummyName = `backup-2020-01-01_${String(i).padStart(2, '0')}-00-00`;
@@ -111,8 +161,8 @@ async function runTests() {
if (fs.existsSync(mPath)) fs.rmSync(mPath, { recursive: true, force: true });
}
// 5. Test MSSQL warning behavior
console.log('\n[Test 4] Testing MSSQL console warning behavior...');
// 6. Test MSSQL warning behavior
console.log('\n[Test 5] Testing MSSQL console warning behavior...');
const originalProvider = env.dbProvider;
let warningCaptured = false;
const origWarn = console.warn;
@@ -126,7 +176,7 @@ async function runTests() {
try {
env.dbProvider = 'mssql';
const mssqlBackup = await createHourlyBackup({ manual: true });
const mssqlBackup = await createHourlyBackup();
assert(warningCaptured, 'Console warning must be printed when running on MSSQL');
assert(mssqlBackup.manifest.files.database.backedUp === false, 'Database backup must be skipped on MSSQL');
console.log('MSSQL warning and database skip verified.');
@@ -135,8 +185,8 @@ async function runTests() {
env.dbProvider = originalProvider;
}
// 6. Test Lifecycle methods
console.log('\n[Test 5] Testing startBackupService() and stopBackupService()...');
// 7. Test Lifecycle methods
console.log('\n[Test 6] Testing startBackupService() and stopBackupService()...');
startBackupService();
assert(getBackupServiceStatus().isRunning === true, 'Service should be running');
await stopBackupService();