Add unit tests for data file rotation utility functions
Some checks failed
Code Analysis and Production Deploy / analyze (push) Failing after 5m24s
Code Analysis and Production Deploy / deploy-production (push) Has been skipped
Code Analysis and Production Deploy / deploy-test (push) Has been skipped

- Implement tests for writing data files with rotation, ensuring backups are created only on changes.
- Verify that old backups are rotated correctly and the maximum number of backups is maintained.
- Test restoration of backups while preserving the current state as a backup.
- Utilize Vitest for testing framework and manage temporary file storage during tests.
This commit is contained in:
Torsten Schulz (local)
2026-06-01 11:21:21 +02:00
parent 80834d8652
commit 2014abe660
17 changed files with 563 additions and 14 deletions

View File

@@ -0,0 +1,163 @@
#!/usr/bin/env node
import path from 'path'
import {
getBackupDirectoryForDataFile,
listDataFileBackups,
restoreDataFileBackup
} from '../server/utils/data-file-rotation.js'
const FILES = {
'users.json': getDataPath('users.json'),
'sessions.json': getDataPath('sessions.json'),
'members.json': getDataPath('members.json'),
'newsletter-subscribers.json': getDataPath('newsletter-subscribers.json'),
'news.json': getDataPath('news.json'),
'termine.csv': getDataPath('termine.csv'),
'contact-requests.json': getDataPath('contact-requests.json')
}
function getDataPath(filename) {
const cwd = process.cwd()
if (cwd.endsWith('.output')) {
return path.join(cwd, '../server/data', filename)
}
return path.join(cwd, 'server/data', filename)
}
function parseArg(name) {
const index = process.argv.findIndex((arg) => arg === name)
if (index === -1) return null
const next = process.argv[index + 1]
if (!next || next.startsWith('--')) return null
return next
}
function hasFlag(name) {
return process.argv.includes(name)
}
function printUsage() {
console.log('Verwendung:')
console.log(' node scripts/data-backup-restore.js list [--file users.json]')
console.log(' node scripts/data-backup-restore.js restore --file users.json --latest')
console.log(' node scripts/data-backup-restore.js restore --file users.json --backup <backup-datei.bak>')
console.log('')
console.log('Optionen:')
console.log(' --file Eine der bekannten Daten-Dateien')
console.log(' --latest Stellt das neueste Backup wieder her')
console.log(' --backup Konkreter Backup-Dateiname (*.bak)')
console.log('')
console.log('Bekannte Dateien:')
Object.keys(FILES).forEach((name) => console.log(` - ${name}`))
}
async function listCommand() {
const requestedFile = parseArg('--file')
const names = requestedFile ? [requestedFile] : Object.keys(FILES)
for (const name of names) {
const dataPath = FILES[name]
if (!dataPath) {
console.error(`Unbekannte Datei: ${name}`)
process.exitCode = 1
continue
}
const backups = await listDataFileBackups(dataPath)
const backupDir = getBackupDirectoryForDataFile(dataPath)
console.log(`\n${name}`)
console.log(` Datenpfad: ${dataPath}`)
console.log(` Backup-Ordner: ${backupDir}`)
if (backups.length === 0) {
console.log(' Backups: keine')
continue
}
console.log(` Backups (${backups.length}, neuestes zuerst):`)
backups.slice(0, 15).forEach((backup) => {
console.log(` - ${backup}`)
})
if (backups.length > 15) {
console.log(` ... (${backups.length - 15} weitere)`)
}
}
}
async function restoreCommand() {
const fileName = parseArg('--file')
if (!fileName) {
console.error('Fehlend: --file <datei>')
printUsage()
process.exit(1)
}
const dataPath = FILES[fileName]
if (!dataPath) {
console.error(`Unbekannte Datei: ${fileName}`)
process.exit(1)
}
const backups = await listDataFileBackups(dataPath)
if (backups.length === 0) {
console.error(`Keine Backups gefunden für ${fileName}`)
process.exit(1)
}
const backupName = parseArg('--backup')
const latest = hasFlag('--latest')
let targetBackup = backupName
if (!targetBackup && latest) {
targetBackup = backups[0]
}
if (!targetBackup) {
console.error('Bitte --latest oder --backup <name> angeben')
process.exit(1)
}
if (!backups.includes(targetBackup)) {
console.error(`Backup nicht gefunden: ${targetBackup}`)
console.error('Nutzen Sie zuerst: node scripts/data-backup-restore.js list --file <datei>')
process.exit(1)
}
const result = await restoreDataFileBackup(dataPath, targetBackup)
console.log(`Wiederherstellung abgeschlossen: ${fileName}`)
console.log(` Eingespieltes Backup: ${targetBackup}`)
if (result.backupPath) {
console.log(` Backup des vorherigen Zustands: ${result.backupPath}`)
}
}
async function main() {
const command = process.argv[2]
if (!command || command === '--help' || command === '-h') {
printUsage()
return
}
if (command === 'list') {
await listCommand()
return
}
if (command === 'restore') {
await restoreCommand()
return
}
console.error(`Unbekannter Befehl: ${command}`)
printUsage()
process.exit(1)
}
main().catch((error) => {
console.error('Fehler im Backup/Restore-Skript:', error)
process.exit(1)
})