Files

83 lines
2.9 KiB
TypeScript

import { mkdtempSync, rmSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { listBackups } from '@authportal/db'
import { loadConfig } from '../src/config.js'
import { backupDirFor, runBackup, startBackupJob } from '../src/services/backup.js'
import { buildApp } from '../src/app.js'
import { adminToken } from './helpers.js'
const dirs: string[] = []
afterEach(() => {
vi.useRealTimers()
for (const d of dirs.splice(0)) {
try {
rmSync(d, { recursive: true, force: true })
} catch {
/* Windows может держать файл БД до GC — временный каталог не критичен */
}
}
})
function env(dir: string, extra: NodeJS.ProcessEnv = {}) {
return loadConfig({
JWT_SECRET: 'test-secret-at-least-8',
ADMIN_EMAIL: 'admin@test.local',
ADMIN_PASSWORD: 'adminpass',
DATABASE_URL: `sqlite:${join(dir, 'app.db')}`,
NODE_ENV: 'test',
...extra,
})
}
describe('backup', () => {
it('backupDirFor: по умолчанию рядом с БД, BACKUP_DIR приоритетнее', () => {
const cfg = env('/data/x')
expect(backupDirFor(cfg).replaceAll(String.fromCharCode(92), '/')).toMatch(/\/data\/x\/backups$/)
const custom = env('/data/x', { BACKUP_DIR: '/mnt/bk' })
expect(backupDirFor(custom).replaceAll(String.fromCharCode(92), '/')).toMatch(/\/mnt\/bk$/)
})
it('бэкап живого приложения восстанавливается: вход админа работает', async () => {
const dir = mkdtempSync(join(tmpdir(), 'ap-api-bk-'))
dirs.push(dir)
const config = env(dir, { BACKUP_KEEP: '2' })
const app = await buildApp({ config })
const res = await runBackup(app.sqlite, config)
expect(listBackups(backupDirFor(config))).toHaveLength(1)
await app.close()
const restored = await buildApp({
config: env(dir),
databaseUrl: `sqlite:${res.file}`,
})
const token = await adminToken(restored as never)
expect(token).toBeTruthy()
await restored.close()
})
it('startBackupJob выключен при 0 часов и работает по таймеру', async () => {
vi.useFakeTimers()
const dir = mkdtempSync(join(tmpdir(), 'ap-job-bk-'))
dirs.push(dir)
const config = env(dir, { BACKUP_INTERVAL_HOURS: '1' })
const app = await buildApp({ config })
const base = vi.getTimerCount()
const off = startBackupJob({ ...app, config: { ...config, backupIntervalHours: 0 } } as never)
expect(vi.getTimerCount()).toBe(base)
off()
const stop = startBackupJob(app)
expect(vi.getTimerCount()).toBe(base + 1)
await vi.advanceTimersByTimeAsync(60 * 60 * 1000 + 10)
vi.useRealTimers()
await vi.waitFor(() =>
expect(listBackups(backupDirFor(config)).length).toBeGreaterThan(0),
)
stop()
await app.close()
})
})