process.env.NODE_ENV = 'test'; delete process.env.DATABASE_URL; const { db } = await import('../api/db.js'); const { database, closeDatabase } = await import('../api/database.js'); const { deriveCollectionStatus, recalculateCollectionStatus } = await import('../api/services/collectionsService.js'); function assert(condition: unknown, message: string): asserts condition { if (!condition) throw new Error(message); } async function current(collectionId: number) { return database.one<{ status: string; completed_at: string | null }>('SELECT status, completed_at FROM collections WHERE id = ?', [collectionId]); } assert(deriveCollectionStatus(0, 0) === 'draft', '空作品交付集应为待提交'); assert(deriveCollectionStatus(2, 1) === 'reviewing', '存在未通过作品时应为验收中'); assert(deriveCollectionStatus(2, 2) === 'completed', '全部作品通过后应为验收完毕'); db.exec('BEGIN IMMEDIATE'); try { const project = await database.one<{ id: number }>('SELECT id FROM projects ORDER BY id LIMIT 1'); assert(project, 'SQLite 测试需要至少一个项目'); const collectionId = await database.insertId("INSERT INTO collections (project_id, name, status) VALUES (?, ?, 'draft')", [project.id, `状态测试-${Date.now()}`]); await recalculateCollectionStatus(collectionId); assert((await current(collectionId))?.status === 'draft', '新建空作品交付集状态错误'); const noteId = await database.insertId("INSERT INTO notes (collection_id, title, review_status) VALUES (?, ?, 'pending')", [collectionId, 'SQLite 状态测试作品']); await recalculateCollectionStatus(collectionId); assert((await current(collectionId))?.status === 'reviewing', '新增待验收作品后未进入验收中'); await database.execute("UPDATE notes SET review_status = 'approved' WHERE id = ?", [noteId]); await recalculateCollectionStatus(collectionId); const completed = await current(collectionId); assert(completed?.status === 'completed' && completed.completed_at, '全部通过后未完成或缺少完成时间'); const secondNoteId = await database.insertId("INSERT INTO notes (collection_id, title, review_status) VALUES (?, ?, 'pending')", [collectionId, 'SQLite 状态测试作品二']); const partial = await recalculateCollectionStatus(collectionId); assert(partial?.status === 'reviewing' && partial.workCount === 2 && partial.approvedCount === 1, '部分作品通过时应保持验收中'); await database.execute("UPDATE notes SET review_status = 'approved' WHERE id = ?", [secondNoteId]); await recalculateCollectionStatus(collectionId); assert((await current(collectionId))?.status === 'completed', '多件作品全部通过后应验收完毕'); await database.execute("UPDATE collections SET status = 'archived' WHERE id = ?", [collectionId]); await database.execute("UPDATE notes SET review_status = 'pending' WHERE id = ?", [noteId]); await recalculateCollectionStatus(collectionId); assert((await current(collectionId))?.status === 'archived', '自动重算不应覆盖手动归档状态'); await database.execute("UPDATE collections SET status = 'reviewing' WHERE id = ?", [collectionId]); await recalculateCollectionStatus(collectionId); assert((await current(collectionId))?.status === 'reviewing', '恢复归档后应按作品状态重算'); await database.execute("UPDATE notes SET review_status = 'draft' WHERE id IN (?, ?)", [noteId, secondNoteId]); await recalculateCollectionStatus(collectionId); const draft = await current(collectionId); assert(draft?.status === 'draft' && draft.completed_at === null, '全部作品退回草稿后应回到待提交并清除完成时间'); process.stdout.write('SQLite 作品交付集状态验证通过:待提交、验收中、验收完毕、归档保护与恢复重算\n'); } finally { db.exec('ROLLBACK'); await closeDatabase(); }