From b886e37218011762c1e9d931adb6688b6a1faf43 Mon Sep 17 00:00:00 2001 From: snowgitea Date: Wed, 29 Apr 2026 02:08:55 +0800 Subject: [PATCH] chore: remove backend/test-time-fix-regression.js --- backend/test-time-fix-regression.js | 607 ---------------------------- 1 file changed, 607 deletions(-) delete mode 100644 backend/test-time-fix-regression.js diff --git a/backend/test-time-fix-regression.js b/backend/test-time-fix-regression.js deleted file mode 100644 index e394e45..0000000 --- a/backend/test-time-fix-regression.js +++ /dev/null @@ -1,607 +0,0 @@ -/** - * ============================================= - * 时间显示修复 - 完整回归测试脚本 - * ============================================= - * 测试目标: 验证 createdAt 排序修复和 parseDate 本地时区解析 - * 测试环境: 后端 API (localhost:3001) - * 测试日期: 2026-04-26 - * ============================================= - */ - -import http from 'http'; -import fs from 'fs'; -import path from 'path'; -import { fileURLToPath } from 'url'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -const BASE_URL = 'http://localhost:3001'; -const USER_ID = 1; - -// 测试报告 -const report = { - total: 0, - passed: 0, - failed: 0, - warnings: 0, - results: [], - startTime: new Date(), - endTime: null -}; - -function log(msg, level = 'INFO') { - const icon = { INFO: '📝', PASS: '✅', FAIL: '❌', WARN: '⚠️', HEADER: '📋', SEP: '─' }; - const prefix = icon[level] || '📝'; - console.log(`${prefix} ${msg}`); -} - -function recordTest(name, status, detail = '') { - report.total++; - if (status === 'PASS') { - report.passed++; - log(`${name} - PASS${detail ? ' | ' + detail : ''}`, 'PASS'); - } else if (status === 'WARN') { - report.warnings++; - log(`${name} - WARN${detail ? ' | ' + detail : ''}`, 'WARN'); - } else { - report.failed++; - log(`${name} - FAIL${detail ? ' | ' + detail : ''}`, 'FAIL'); - } - report.results.push({ name, status, detail }); -} - -// API 请求封装 -function apiRequest(method, path, body = null) { - return new Promise((resolve, reject) => { - const url = new URL(path, BASE_URL); - const options = { - hostname: url.hostname, - port: url.port, - path: url.pathname + url.search, - method, - headers: { 'Content-Type': 'application/json' } - }; - - const req = http.request(options, (res) => { - let data = ''; - res.on('data', (chunk) => (data += chunk)); - res.on('end', () => { - try { - resolve({ statusCode: res.statusCode, body: JSON.parse(data) }); - } catch (e) { - resolve({ statusCode: res.statusCode, body: data }); - } - }); - }); - - req.on('error', reject); - if (body) req.write(JSON.stringify(body)); - req.end(); - }); -} - -// 创建记录辅助函数 -async function createRecord(type, category, amount, description, date = null) { - const payload = { - userId: USER_ID, - accountId: 3, - type, - amount, - category, - description, - date: date || new Date().toISOString().split('T')[0] - }; - const result = await apiRequest('POST', '/api/records', payload); - if (result.body.success) { - return result.body.data; - } else { - throw new Error(`创建记录失败: ${result.body.message}`); - } -} - -// 获取记录辅助函数 -async function getRecords(params = {}) { - const query = new URLSearchParams({ userId: USER_ID, ...params }); - const result = await apiRequest('GET', `/api/records?${query}`); - if (result.body.success) { - return result.body.data; - } - return []; -} - -// 删除记录辅助函数 -async function deleteRecord(id) { - await apiRequest('DELETE', `/api/records/${id}`); -} - -async function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -// ============================================= -// 主测试流程 -// ============================================= -async function runTests() { - console.log('\n' + '='.repeat(60)); - console.log('🧪 时间显示修复 - 完整回归测试'); - console.log('='.repeat(60)); - console.log(`测试开始时间: ${new Date().toLocaleString('zh-CN')}`); - console.log(`后端地址: ${BASE_URL}`); - console.log(`测试用户: userId=${USER_ID}`); - console.log('='.repeat(60) + '\n'); - - // ========================================== - // 测试1: 验证后端 parseDate 函数 - // ========================================== - log('═══════════════════════════════════════════════════════', 'HEADER'); - log('【测试1】验证后端 parseDate 函数对纯日期字符串的解析', 'HEADER'); - log('═══════════════════════════════════════════════════════', 'HEADER'); - - // 创建一条记录,使用纯日期字符串 - const now = new Date(); - const dateStr = '2026-04-26'; - const record1 = await createRecord('expense', '餐饮', 10, 'parseDate测试', dateStr); - - const parsedDate = new Date(record1.date); - const expectedHour = 0; // 应该解析为当天 00:00 北京时间 - const actualHour = parsedDate.getHours(); - - log(`输入日期字符串: "${dateStr}"`, 'INFO'); - log(`解析结果: ${parsedDate.toLocaleString('zh-CN')}`, 'INFO'); - log(`解析结果 ISO: ${parsedDate.toISOString()}`, 'INFO'); - log(`本地时区小时: ${actualHour}:00`, 'INFO'); - - if (actualHour === expectedHour) { - recordTest('parseDate 解析纯日期为本地时区 00:00', 'PASS', - `解析为 ${parsedDate.toLocaleString('zh-CN')} (北京时间 00:00,非 UTC 00:00)`); - } else { - recordTest('parseDate 解析纯日期为本地时区 00:00', 'FAIL', - `期望 00:00,实际 ${actualHour}:00`); - } - - // 验证 createdAt 为实际创建时间 - const createdAt = new Date(record1.createdAt); - const createdAtDiff = Math.abs(createdAt.getTime() - now.getTime()); - - log(`记录创建时间 (createdAt): ${createdAt.toLocaleString('zh-CN')}`, 'INFO'); - log(`创建时间差: ${createdAtDiff}ms`, 'INFO'); - - if (createdAtDiff < 5000) { - recordTest('createdAt 反映实际创建时间', 'PASS', - `与当前时间差 ${createdAtDiff}ms < 5s`); - } else { - recordTest('createdAt 反映实际创建时间', 'FAIL', - `与当前时间差 ${createdAtDiff}ms > 5s`); - } - - await deleteRecord(record1.id); - - // ========================================== - // 测试2: 验证后端 API 返回的 createdAt 字段 - // ========================================== - log('\n═══════════════════════════════════════════════════════', 'HEADER'); - log('【测试2】验证后端 API 返回的 createdAt 字段是否正确', 'HEADER'); - log('═══════════════════════════════════════════════════════', 'HEADER'); - - const beforeCreate = new Date(); - await sleep(100); - const record2 = await createRecord('expense', '交通', 20, 'createdAt验证'); - const afterCreate = new Date(); - - const apiCreatedAt = new Date(record2.createdAt); - - log(`创建前时间: ${beforeCreate.toLocaleString('zh-CN')}`, 'INFO'); - log(`API返回 createdAt: ${apiCreatedAt.toLocaleString('zh-CN')}`, 'INFO'); - log(`创建后时间: ${afterCreate.toLocaleString('zh-CN')}`, 'INFO'); - - const isWithinRange = apiCreatedAt >= beforeCreate && apiCreatedAt <= afterCreate; - - if (isWithinRange) { - recordTest('API 返回的 createdAt 在创建时间范围内', 'PASS', - `${apiCreatedAt.toLocaleString('zh-CN')} 在 [${beforeCreate.toLocaleString('zh-CN')}, ${afterCreate.toLocaleString('zh-CN')}] 内`); - } else { - recordTest('API 返回的 createdAt 在创建时间范围内', 'FAIL', - `createdAt 不在预期时间范围内`); - } - - // 验证 createdAt 包含时分秒 - const hasTimeComponent = record2.createdAt.includes(':'); - if (hasTimeComponent) { - recordTest('createdAt 包含时分秒信息', 'PASS', `值: ${record2.createdAt}`); - } else { - recordTest('createdAt 包含时分秒信息', 'FAIL', `值: ${record2.createdAt}`); - } - - await deleteRecord(record2.id); - - // ========================================== - // 测试3: 验证后端排序逻辑 (orderBy: { createdAt: 'desc' }) - // ========================================== - log('\n═══════════════════════════════════════════════════════', 'HEADER'); - log('【测试3】验证后端排序逻辑 (orderBy: createdAt desc)', 'HEADER'); - log('═══════════════════════════════════════════════════════', 'HEADER'); - - // 清空现有记录,确保测试环境干净 - const existingRecords = await getRecords(); - for (const r of existingRecords) { - await deleteRecord(r.id); - } - log(`已清理 ${existingRecords.length} 条现有记录`, 'INFO'); - - // 创建3条同一天但不同时间的记录 - const records = []; - for (let i = 0; i < 3; i++) { - const r = await createRecord('expense', '餐饮', 10 + i, `同天记录${i + 1}`); - records.push(r); - log(`创建记录 ${i + 1}: ID=${r.id}, createdAt=${new Date(r.createdAt).toLocaleTimeString('zh-CN')}`, 'INFO'); - await sleep(500); // 确保 createdAt 有差异 - } - - // 获取排序后的记录 - const sortedRecords = await getRecords(); - - log(`\n后端返回的排序顺序:`, 'INFO'); - sortedRecords.forEach((r, i) => { - log(` [${i + 1}] ${r.category} ¥${r.amount} ${r.description} | createdAt=${new Date(r.createdAt).toLocaleTimeString('zh-CN')}`, 'INFO'); - }); - - // 验证最新的记录在最前面 - const firstRecord = sortedRecords[0]; - const lastRecord = sortedRecords[sortedRecords.length - 1]; - - if (firstRecord && firstRecord.description === '同天记录3') { - recordTest('最新创建的记录排在第一位', 'PASS', `ID=${firstRecord.id}`); - } else { - recordTest('最新创建的记录排在第一位', 'FAIL', - `期望"同天记录3",实际"${firstRecord?.description}"`); - } - - // 验证排序是严格降序 - let isStrictDescending = true; - for (let i = 0; i < sortedRecords.length - 1; i++) { - const t1 = new Date(sortedRecords[i].createdAt).getTime(); - const t2 = new Date(sortedRecords[i + 1].createdAt).getTime(); - if (t1 < t2) { - isStrictDescending = false; - break; - } - } - - if (isStrictDescending) { - recordTest('后端排序为严格降序', 'PASS', `${sortedRecords.length} 条记录排序正确`); - } else { - recordTest('后端排序为严格降序', 'FAIL', '排序出现异常'); - } - - // ========================================== - // 测试4: 验证前端 Dashboard 排序逻辑 - // ========================================== - log('\n═══════════════════════════════════════════════════════', 'HEADER'); - log('【测试4】验证前端 Dashboard 使用 createdAt 排序', 'HEADER'); - log('═══════════════════════════════════════════════════════', 'HEADER'); - - // 读取前端代码验证排序逻辑 - const dashboardPath = path.join(__dirname, '..', 'frontend', 'src', 'pages', 'Dashboard', 'index.tsx'); - - if (fs.existsSync(dashboardPath)) { - const dashboardCode = fs.readFileSync(dashboardPath, 'utf-8'); - - // 检查是否使用 createdAt 排序 - const hasCreatedAtSort = dashboardCode.includes('.sort((a, b) => new Date(b.createdAt)'); - const hasDateSort = dashboardCode.includes('.sort((a, b) => new Date(b.date)') && !hasCreatedAtSort; - - if (hasCreatedAtSort) { - recordTest('Dashboard 使用 createdAt 排序', 'PASS', '代码使用 new Date(b.createdAt) 排序'); - } else if (hasDateSort) { - recordTest('Dashboard 使用 createdAt 排序', 'FAIL', '代码仍使用 new Date(b.date) 排序'); - } else { - recordTest('Dashboard 使用 createdAt 排序', 'WARN', '未能识别排序逻辑,请手动确认'); - } - - // 检查 formatRecordTime 函数 - const hasFormatRecordTime = dashboardCode.includes('const formatRecordTime'); - const usesCreatedAtForTime = dashboardCode.includes('new Date(record.createdAt)'); - - if (hasFormatRecordTime && usesCreatedAtForTime) { - recordTest('Dashboard 时间格式化使用 createdAt', 'PASS', 'formatRecordTime 使用 record.createdAt'); - } else { - recordTest('Dashboard 时间格式化使用 createdAt', 'FAIL', '时间格式化未使用 createdAt'); - } - - // 检查时间显示逻辑 - const showsHHMMForToday = dashboardCode.includes("createdAt.getHours()") && dashboardCode.includes("createdAt.getMinutes()"); - if (showsHHMMForToday) { - recordTest('Dashboard 今天显示 HH:MM 格式', 'PASS', '使用 getHours() 和 getMinutes() 格式化'); - } else { - recordTest('Dashboard 今天显示 HH:MM 格式', 'FAIL', '未找到 HH:MM 格式化逻辑'); - } - - const showsYesterday = dashboardCode.includes("'昨天'") || dashboardCode.includes('"昨天"'); - if (showsYesterday) { - recordTest('Dashboard 昨天显示"昨天"文本', 'PASS', '包含"昨天"显示逻辑'); - } else { - recordTest('Dashboard 昨天显示"昨天"文本', 'WARN', '未找到"昨天"显示逻辑'); - } - } else { - recordTest('Dashboard 文件存在性', 'FAIL', `文件不存在: ${dashboardPath}`); - } - - // ========================================== - // 测试5: 验证前端 Record 页面排序逻辑 - // ========================================== - log('\n═══════════════════════════════════════════════════════', 'HEADER'); - log('【测试5】验证前端 Record 页面使用 createdAt 排序', 'HEADER'); - log('═══════════════════════════════════════════════════════', 'HEADER'); - - const recordPath = path.join(__dirname, '..', 'frontend', 'src', 'pages', 'Record', 'index.tsx'); - - if (fs.existsSync(recordPath)) { - const recordCode = fs.readFileSync(recordPath, 'utf-8'); - - // 检查排序逻辑 - const hasCreatedAtSort = recordCode.includes('.sort((a, b) => new Date(b.createdAt)'); - const hasDateSort = recordCode.includes('.sort((a, b) => new Date(b.date)') && !hasCreatedAtSort; - - if (hasCreatedAtSort) { - recordTest('Record 页面使用 createdAt 排序', 'PASS', '代码使用 new Date(b.createdAt) 排序'); - } else if (hasDateSort) { - recordTest('Record 页面使用 createdAt 排序', 'FAIL', '代码仍使用 new Date(b.date) 排序'); - } else { - recordTest('Record 页面使用 createdAt 排序', 'WARN', '未能识别排序逻辑'); - } - - // 检查 formatTime 函数 - const hasFormatTime = recordCode.includes('const formatTime'); - const usesCreatedAtForTime = recordCode.includes('new Date(record.createdAt)'); - - if (hasFormatTime && usesCreatedAtForTime) { - recordTest('Record 页面时间格式化使用 createdAt', 'PASS', 'formatTime 使用 record.createdAt'); - } else { - recordTest('Record 页面时间格式化使用 createdAt', 'FAIL', '时间格式化未使用 createdAt'); - } - - // 检查今天显示 HH:MM - const showsHHMM = recordCode.includes("hour: '2-digit'") && recordCode.includes("minute: '2-digit'"); - if (showsHHMM) { - recordTest('Record 页面今天显示 HH:MM 格式', 'PASS', '使用 toLocaleTimeString 格式化'); - } else { - recordTest('Record 页面今天显示 HH:MM 格式', 'FAIL', '未找到 HH:MM 格式化逻辑'); - } - - // 检查昨天显示 - const showsYesterday = recordCode.includes("'昨天'") || recordCode.includes('"昨天"'); - if (showsYesterday) { - recordTest('Record 页面昨天显示"昨天"文本', 'PASS', '包含"昨天"显示逻辑'); - } else { - recordTest('Record 页面昨天显示"昨天"文本', 'WARN', '未找到"昨天"显示逻辑'); - } - - // 检查过滤后再排序 - const filterThenSort = recordCode.includes('.filter(') && recordCode.includes('.sort('); - if (filterThenSort) { - recordTest('Record 页面先过滤再排序', 'PASS', '排序在过滤后执行'); - } else { - recordTest('Record 页面先过滤再排序', 'WARN', '过滤和排序顺序需确认'); - } - } else { - recordTest('Record 文件存在性', 'FAIL', `文件不存在: ${recordPath}`); - } - - // ========================================== - // 测试6: 验证同一天多条记录的排序 - // ========================================== - log('\n═══════════════════════════════════════════════════════', 'HEADER'); - log('【测试6】验证同一天添加多条记录的排序稳定性', 'HEADER'); - log('═══════════════════════════════════════════════════════', 'HEADER'); - - // 当前记录应该已经是按 createdAt 降序(来自测试3) - // 再添加2条记录,验证最新始终在最前 - - const extra1 = await createRecord('expense', '购物', 50, '额外记录1'); - log(`创建额外记录1: ID=${extra1.id}`, 'INFO'); - await sleep(500); - - const extra2 = await createRecord('income', '兼职', 100, '额外记录2'); - log(`创建额外记录2: ID=${extra2.id}`, 'INFO'); - await sleep(500); - - const recordsAfterExtra = await getRecords(); - - log(`\n添加额外记录后的排序:`, 'INFO'); - recordsAfterExtra.forEach((r, i) => { - log(` [${i + 1}] ${r.type === 'income' ? '+' : '-'}¥${r.amount} ${r.category} ${r.description} | ${new Date(r.createdAt).toLocaleTimeString('zh-CN')}`, 'INFO'); - }); - - const latestRecord = recordsAfterExtra[0]; - if (latestRecord && latestRecord.id === extra2.id) { - recordTest('最新添加的记录始终在最前面', 'PASS', `最新记录: "${latestRecord.description}"`); - } else { - recordTest('最新添加的记录始终在最前面', 'FAIL', - `期望"额外记录2"在最前,实际"${latestRecord?.description}"`); - } - - // 验证支出筛选后的排序 - const expenseRecords = await getRecords({ type: 'expense' }); - let expenseSorted = true; - for (let i = 0; i < expenseRecords.length - 1; i++) { - const t1 = new Date(expenseRecords[i].createdAt).getTime(); - const t2 = new Date(expenseRecords[i + 1].createdAt).getTime(); - if (t1 < t2) { - expenseSorted = false; - break; - } - } - - if (expenseSorted) { - recordTest('支出筛选后仍保持 createdAt 降序', 'PASS', `${expenseRecords.length} 条支出记录排序正确`); - } else { - recordTest('支出筛选后仍保持 createdAt 降序', 'FAIL', '支出排序异常'); - } - - // 验证收入筛选后的排序 - const incomeRecords = await getRecords({ type: 'income' }); - let incomeSorted = true; - for (let i = 0; i < incomeRecords.length - 1; i++) { - const t1 = new Date(incomeRecords[i].createdAt).getTime(); - const t2 = new Date(incomeRecords[i + 1].createdAt).getTime(); - if (t1 < t2) { - incomeSorted = false; - break; - } - } - - if (incomeSorted) { - recordTest('收入筛选后仍保持 createdAt 降序', 'PASS', `${incomeRecords.length} 条收入记录排序正确`); - } else { - recordTest('收入筛选后仍保持 createdAt 降序', 'FAIL', '收入排序异常'); - } - - // ========================================== - // 测试7: 验证前端时间显示逻辑 (模拟) - // ========================================== - log('\n═══════════════════════════════════════════════════════', 'HEADER'); - log('【测试7】验证前端时间显示格式 (模拟前端逻辑)', 'HEADER'); - log('═══════════════════════════════════════════════════════', 'HEADER'); - - // 模拟前端 formatRecordTime 逻辑 (Dashboard) - function simulateDashboardFormatTime(record) { - const createdAt = new Date(record.createdAt); - const now = new Date(); - const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime(); - const recordDay = new Date(createdAt.getFullYear(), createdAt.getMonth(), createdAt.getDate()).getTime(); - const diffDays = Math.floor((today - recordDay) / (1000 * 60 * 60 * 24)); - - if (diffDays === 0) { - return `${createdAt.getHours().toString().padStart(2, '0')}:${createdAt.getMinutes().toString().padStart(2, '0')}`; - } else if (diffDays === 1) { - return '昨天'; - } else if (diffDays <= 7) { - return `${diffDays}天前`; - } else { - return `${createdAt.getMonth() + 1}月${createdAt.getDate()}日`; - } - } - - // 模拟前端 formatTime 逻辑 (Record) - function simulateRecordFormatTime(record) { - const createdAt = new Date(record.createdAt); - const today = new Date(); - const todayStr = new Date(today.getFullYear(), today.getMonth(), today.getDate()).toDateString(); - const recordDay = new Date(createdAt.getFullYear(), createdAt.getMonth(), createdAt.getDate()).toDateString(); - - if (todayStr === recordDay) { - return createdAt.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }); - } - - const yesterday = new Date(today); - yesterday.setDate(yesterday.getDate() - 1); - const yesterdayStr = new Date(yesterday.getFullYear(), yesterday.getMonth(), yesterday.getDate()).toDateString(); - if (yesterdayStr === recordDay) { - return '昨天'; - } - - return createdAt.toLocaleDateString('zh-CN', { month: 'short', day: 'numeric' }); - } - - // 使用现有记录测试时间显示 - const allRecords = await getRecords(); - - if (allRecords.length > 0) { - const todayRecord = allRecords.find(r => { - const created = new Date(r.createdAt); - const today = new Date(); - return created.getFullYear() === today.getFullYear() && - created.getMonth() === today.getMonth() && - created.getDate() === today.getDate(); - }); - - if (todayRecord) { - const dashTime = simulateDashboardFormatTime(todayRecord); - const recordTime = simulateRecordFormatTime(todayRecord); - - log(`今天创建的记录: "${todayRecord.description}"`, 'INFO'); - log(` Dashboard 显示: "${dashTime}"`, 'INFO'); - log(` Record 显示: "${recordTime}"`, 'INFO'); - - // 验证不是 08:00 - if (dashTime !== '08:00') { - recordTest('Dashboard 今天记录不显示 08:00', 'PASS', `显示: "${dashTime}"`); - } else { - recordTest('Dashboard 今天记录不显示 08:00', 'FAIL', `仍显示 "08:00"`); - } - - if (recordTime !== '08:00') { - recordTest('Record 页面今天记录不显示 08:00', 'PASS', `显示: "${recordTime}"`); - } else { - recordTest('Record 页面今天记录不显示 08:00', 'FAIL', `仍显示 "08:00"`); - } - - // 验证格式为 HH:MM - const dashTimeRegex = /^\d{2}:\d{2}$/; - if (dashTimeRegex.test(dashTime)) { - recordTest('Dashboard 时间格式为 HH:MM', 'PASS', `格式正确: "${dashTime}"`); - } else { - recordTest('Dashboard 时间格式为 HH:MM', 'FAIL', `格式不正确: "${dashTime}"`); - } - } else { - recordTest('今天记录时间显示验证', 'WARN', '当前没有今天的记录,跳过此测试'); - } - } else { - recordTest('时间显示验证', 'WARN', '无记录可验证'); - } - - // ========================================== - // 测试8: 清理测试数据 - // ========================================== - log('\n═══════════════════════════════════════════════════════', 'HEADER'); - log('【测试8】清理测试数据', 'HEADER'); - log('═══════════════════════════════════════════════════════', 'HEADER'); - - const finalRecords = await getRecords(); - for (const r of finalRecords) { - await deleteRecord(r.id); - } - log(`已清理 ${finalRecords.length} 条测试记录`, 'INFO'); - recordTest('测试数据清理完成', 'PASS', `清理 ${finalRecords.length} 条记录`); - - // ========================================== - // 生成测试报告 - // ========================================== - report.endTime = new Date(); - const duration = report.endTime - report.startTime; - - console.log('\n' + '='.repeat(60)); - console.log('📊 测试报告'); - console.log('='.repeat(60)); - console.log(`测试总数: ${report.total}`); - console.log(`通过: ${report.passed}`); - console.log(`失败: ${report.failed}`); - console.log(`警告: ${report.warnings}`); - console.log(`通过率: ${((report.passed / report.total) * 100).toFixed(1)}%`); - console.log(`耗时: ${duration}ms`); - console.log('='.repeat(60)); - - console.log('\n📋 测试结果明细:'); - console.log('-'.repeat(60)); - report.results.forEach((r, i) => { - const icon = r.status === 'PASS' ? '✅' : r.status === 'WARN' ? '⚠️' : '❌'; - console.log(` ${icon} [${i + 1}] ${r.name}${r.detail ? ' | ' + r.detail : ''}`); - }); - - console.log('\n' + '='.repeat(60)); - if (report.failed === 0) { - console.log('🎉 全部测试通过!时间显示修复验证成功!'); - } else { - console.log(`❌ ${report.failed} 项测试失败,请检查修复!`); - } - console.log('='.repeat(60) + '\n'); - - return report; -} - -// 执行测试 -runTests().catch(err => { - console.error('测试执行异常:', err); - process.exit(1); -});