Files
FileHost/server/utils/activity-log.smoke.test.ts
T
O96u 91d71a1b40 fix: 修复 CI 活动日志冒烟测试在空数据库下失败
listActivityLogs 会 JOIN storage_backends;CI 无 data/ 目录时需在查询前初始化存储 schema。
2026-09-09 14:57:11 +08:00

113 lines
3.3 KiB
TypeScript

import { mkdtempSync, rmSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { DatabaseSync } from 'node:sqlite'
import { afterEach, describe, expect, it } from 'vitest'
const tempDirs: string[] = []
afterEach(() => {
while (tempDirs.length) {
const dir = tempDirs.pop()
if (dir) rmSync(dir, { recursive: true, force: true })
}
process.env.DATA_DIR = undefined
})
function useTempDataDir(): string {
const dir = mkdtempSync(join(tmpdir(), 'pichost-smoke-'))
tempDirs.push(dir)
process.env.DATA_DIR = dir
return dir
}
async function loadDbModule() {
const mod = await import('./db')
mod.closeDb()
return mod
}
describe('activity log smoke', () => {
it('migrates legacy activity_logs constraints and accepts new action types', async () => {
const dir = useTempDataDir()
const dbPath = join(dir, 'pichost.db')
const legacy = new DatabaseSync(dbPath)
legacy.exec(`
CREATE TABLE activity_logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
action TEXT NOT NULL CHECK(action IN ('upload', 'delete')),
key TEXT NOT NULL,
original_name TEXT NOT NULL,
size INTEGER NOT NULL DEFAULT 0,
content_type TEXT NOT NULL DEFAULT '',
source TEXT NOT NULL CHECK(source IN ('web', 'api')),
created_at TEXT NOT NULL,
user_id INTEGER,
backend_id TEXT,
ip_address TEXT,
status TEXT NOT NULL DEFAULT 'success'
);
INSERT INTO activity_logs (action, key, original_name, size, content_type, source, created_at)
VALUES ('upload', 'images/a.webp', 'a.webp', 100, 'image/webp', 'web', '2026-01-01T00:00:00.000Z');
CREATE TABLE settings (
key TEXT PRIMARY KEY,
value TEXT NOT NULL,
updated_at TEXT NOT NULL
);
`)
legacy.close()
const { getDb, insertActivityLog, listActivityLogs, closeDb } = await loadDbModule()
getDb()
const { ensureStorageSchema } = await import('./storage-backends')
ensureStorageSchema()
insertActivityLog({
action: 'login',
key: 'auth/login',
originalName: 'admin',
size: 0,
contentType: '',
source: 'web',
userId: 1,
ipAddress: '127.0.0.1'
})
insertActivityLog({
action: 'tags',
key: 'tags/1',
originalName: '生活',
size: 0,
contentType: '',
source: 'admin',
userId: 1
})
const result = listActivityLogs({ limit: 10, page: 1 })
expect(result.total).toBe(3)
expect(result.items.map(item => item.action).sort()).toEqual(['login', 'tags', 'upload'])
const migrated = getDb().prepare(`
SELECT value FROM settings WHERE key = 'activity_logs_schema_v2'
`).get() as { value: string } | undefined
expect(migrated?.value).toBe('1')
closeDb()
await new Promise(resolve => setTimeout(resolve, 50))
})
it('lists activity logs on a fresh database without throwing', async () => {
useTempDataDir()
const { getDb, listActivityLogs, closeDb } = await loadDbModule()
getDb()
const { ensureStorageSchema } = await import('./storage-backends')
ensureStorageSchema()
const result = listActivityLogs({ limit: 5, page: 1 })
expect(result.page).toBe(1)
expect(result.items).toEqual([])
closeDb()
await new Promise(resolve => setTimeout(resolve, 50))
})
})