import test from 'node:test'; import assert from 'node:assert/strict'; import { randomUUID } from 'node:crypto'; process.env.NODE_ENV = 'test'; process.env.DB_PATH = ':memory:'; const jsonFetch = async ( baseUrl: string, path: string, options?: { method?: string; body?: unknown }, ) => { const res = await fetch(`${baseUrl}${path}`, { method: options?.method ?? 'GET', headers: options?.body ? { 'Content-Type': 'application/json' } : undefined, body: options?.body ? JSON.stringify(options.body) : undefined, }); const text = await res.text(); let json: any = null; try { json = text ? JSON.parse(text) : null; } catch { json = null; } return { status: res.status, json, text }; }; test('用户任务接口返回未开始/进行中/已结束任务(由前端分组)', async () => { const { initDatabase, run } = await import('../api/database'); await initDatabase(); const { app } = await import('../api/server'); const server = app.listen(0); try { const addr = server.address(); assert.ok(addr && typeof addr === 'object'); const baseUrl = `http://127.0.0.1:${addr.port}`; const now = Date.now(); const userId = randomUUID(); const subjectId = randomUUID(); const historyTaskId = randomUUID(); const upcomingTaskId = randomUUID(); const activeTaskId = randomUUID(); await run(`INSERT INTO users (id, name, phone, password) VALUES (?, ?, ?, ?)`, [ userId, '测试用户', '13800138099', '', ]); await run( `INSERT INTO exam_subjects (id, name, type_ratios, category_ratios, total_score, duration_minutes) VALUES (?, ?, ?, ?, ?, ?)`, [ subjectId, '测试科目', JSON.stringify({ single: 100 }), JSON.stringify({ 通用: 100 }), 100, 60, ], ); const historyStartAt = new Date(now - 3 * 24 * 60 * 60 * 1000).toISOString(); const historyEndAt = new Date(now - 2 * 24 * 60 * 60 * 1000).toISOString(); const upcomingStartAt = new Date(now + 2 * 24 * 60 * 60 * 1000).toISOString(); const upcomingEndAt = new Date(now + 3 * 24 * 60 * 60 * 1000).toISOString(); const activeStartAt = new Date(now - 1 * 24 * 60 * 60 * 1000).toISOString(); const activeEndAt = new Date(now + 1 * 24 * 60 * 60 * 1000).toISOString(); await run( `INSERT INTO exam_tasks (id, name, subject_id, start_at, end_at, selection_config) VALUES (?, ?, ?, ?, ?, ?)`, [historyTaskId, '历史任务', subjectId, historyStartAt, historyEndAt, null], ); await run( `INSERT INTO exam_tasks (id, name, subject_id, start_at, end_at, selection_config) VALUES (?, ?, ?, ?, ?, ?)`, [upcomingTaskId, '未开始任务', subjectId, upcomingStartAt, upcomingEndAt, null], ); await run( `INSERT INTO exam_tasks (id, name, subject_id, start_at, end_at, selection_config) VALUES (?, ?, ?, ?, ?, ?)`, [activeTaskId, '进行中任务', subjectId, activeStartAt, activeEndAt, null], ); const linkUserToTask = async (taskId: string) => { await run(`INSERT INTO exam_task_users (id, task_id, user_id) VALUES (?, ?, ?)`, [ randomUUID(), taskId, userId, ]); }; await linkUserToTask(historyTaskId); await linkUserToTask(upcomingTaskId); await linkUserToTask(activeTaskId); const res = await jsonFetch(baseUrl, `/api/exam-tasks/user/${userId}`); assert.equal(res.status, 200); assert.equal(res.json?.success, true); assert.ok(Array.isArray(res.json?.data)); const names = (res.json?.data as any[]).map((t) => t.name).sort(); assert.deepEqual(names, ['历史任务', '未开始任务', '进行中任务'].sort()); const upcoming = (res.json?.data as any[]).find((t) => t.name === '未开始任务'); assert.ok(upcoming); assert.equal(typeof upcoming.startAt, 'string'); assert.equal(typeof upcoming.endAt, 'string'); } finally { server.close(); } });