diff --git a/frontend/verify-pages-v2.cjs b/frontend/verify-pages-v2.cjs deleted file mode 100644 index 6afa8a3..0000000 --- a/frontend/verify-pages-v2.cjs +++ /dev/null @@ -1,589 +0,0 @@ -/** - * 前端页面数据验证测试脚本 - 修正版 - * 验证 4 个页面的数据是否正确显示 - * - * 测试环境: - * - 前端地址: http://localhost:5173 - * - 数据库用户 ID: 6 - */ - -const { chromium } = require('@playwright/test'); -const path = require('path'); -const fs = require('fs'); - -// 配置 -const BASE_URL = 'http://localhost:5173'; -const SCREENSHOT_DIR = path.join(__dirname, 'test-screenshots'); - -// 测试结果 -const testResults = { - summary: { - total: 0, - passed: 0, - failed: 0, - warnings: 0 - }, - pages: {} -}; - -// 确保截图目录存在 -if (!fs.existsSync(SCREENSHOT_DIR)) { - fs.mkdirSync(SCREENSHOT_DIR, { recursive: true }); -} - -/** - * 延迟函数 - */ -function delay(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -/** - * 测试首页 (/) - */ -async function testDashboard(page) { - console.log('\n========== 测试首页 (/) =========='); - const result = { - url: `${BASE_URL}/`, - checks: [], - issues: [], - screenshot: null - }; - - try { - // 导航到首页 - await page.goto(BASE_URL, { waitUntil: 'networkidle' }); - await delay(2000); // 等待数据加载 - - // 截图 - const screenshotPath = path.join(SCREENSHOT_DIR, '01-dashboard.png'); - await page.screenshot({ path: screenshotPath, fullPage: true }); - result.screenshot = screenshotPath; - console.log(`截图已保存: ${screenshotPath}`); - - // 获取页面文本 - const pageText = await page.textContent('body'); - console.log('\n页面文本片段:', pageText.substring(0, 500)); - - // 检查总余额显示 - console.log('\n--- 检查总余额 ---'); - const hasBalance = pageText.includes('当前余额') || pageText.includes('余额'); - const hasAmount = /¥\s*[\d,]+\.?\d*/.test(pageText) || /\d{4,}/.test(pageText); - - result.checks.push({ - item: '总余额标题', - expected: '当前余额', - found: hasBalance, - status: hasBalance ? 'PASS' : 'FAIL' - }); - - result.checks.push({ - item: '金额显示', - expected: '¥ 格式金额', - found: hasAmount, - status: hasAmount ? 'PASS' : 'FAIL' - }); - - if (hasBalance && hasAmount) { - console.log('[PASS] 总余额显示正确'); - } else { - console.log('[FAIL] 总余额未正确显示'); - result.issues.push('总余额未正确显示'); - } - - // 检查收支统计 - console.log('\n--- 检查收支统计 ---'); - const hasIncome = pageText.includes('本月收入') || pageText.includes('收入'); - const hasExpense = pageText.includes('本月支出') || pageText.includes('支出'); - - result.checks.push({ - item: '本月收入', - found: hasIncome, - status: hasIncome ? 'PASS' : 'FAIL' - }); - - result.checks.push({ - item: '本月支出', - found: hasExpense, - status: hasExpense ? 'PASS' : 'FAIL' - }); - - if (hasIncome) console.log('[PASS] 本月收入显示'); - if (hasExpense) console.log('[PASS] 本月支出显示'); - - // 检查预算进度 - console.log('\n--- 检查预算进度 ---'); - const hasBudget = pageText.includes('预算进度') || pageText.includes('预算'); - const hasCategory = pageText.includes('餐饮') || pageText.includes('交通'); - - result.checks.push({ - item: '预算进度区域', - found: hasBudget, - status: hasBudget ? 'PASS' : 'WARN' - }); - - result.checks.push({ - item: '预算分类', - found: hasCategory, - status: hasCategory ? 'PASS' : 'WARN' - }); - - if (hasBudget) console.log('[PASS] 预算进度区域显示'); - if (hasCategory) console.log('[PASS] 预算分类显示'); - - // 检查最近记录 - console.log('\n--- 检查最近记录 ---'); - const hasRecords = pageText.includes('最近记录') || pageText.includes('记录'); - const hasRecordData = pageText.includes('午餐') || - pageText.includes('地铁') || - pageText.includes('工资') || - pageText.includes('购物'); - - result.checks.push({ - item: '最近记录区域', - found: hasRecords, - status: hasRecords ? 'PASS' : 'WARN' - }); - - result.checks.push({ - item: '记录数据', - found: hasRecordData, - status: hasRecordData ? 'PASS' : 'WARN' - }); - - if (hasRecords) console.log('[PASS] 最近记录区域显示'); - if (hasRecordData) console.log('[PASS] 记录数据显示'); - - } catch (error) { - result.issues.push(`测试异常: ${error.message}`); - console.error(`[ERROR] 首页测试失败: ${error.message}`); - } - - return result; -} - -/** - * 测试记账页面 (/record) - */ -async function testRecord(page) { - console.log('\n========== 测试记账页面 (/record) =========='); - const result = { - url: `${BASE_URL}/record`, - checks: [], - issues: [], - screenshot: null - }; - - try { - // 导航到记账页面 - await page.goto(`${BASE_URL}/record`, { waitUntil: 'networkidle' }); - await delay(2000); - - // 截图 - const screenshotPath = path.join(SCREENSHOT_DIR, '02-record.png'); - await page.screenshot({ path: screenshotPath, fullPage: true }); - result.screenshot = screenshotPath; - console.log(`截图已保存: ${screenshotPath}`); - - // 获取页面文本 - const pageText = await page.textContent('body'); - - // 检查交易记录列表 - console.log('\n--- 检查交易记录列表 ---'); - - // 预期记录数据 - const expectedRecords = ['午餐', '地铁', '工资', '购物', '电影', '房租', '还款']; - let foundCount = 0; - - for (const record of expectedRecords) { - if (pageText.includes(record)) { - foundCount++; - console.log(`[PASS] 找到记录: ${record}`); - } - } - - result.checks.push({ - item: '交易记录数据', - expected: `至少 5 条记录`, - found: foundCount >= 5, - status: foundCount >= 5 ? 'PASS' : 'FAIL' - }); - - if (foundCount < 5) { - result.issues.push(`只找到 ${foundCount} 条记录`); - } - - // 检查记录类型(支出/收入) - console.log('\n--- 检查记录类型 ---'); - const hasExpense = pageText.includes('支出'); - const hasIncome = pageText.includes('收入'); - - result.checks.push({ - item: '记录类型 - 支出', - found: hasExpense, - status: hasExpense ? 'PASS' : 'WARN' - }); - - result.checks.push({ - item: '记录类型 - 收入', - found: hasIncome, - status: hasIncome ? 'PASS' : 'WARN' - }); - - if (hasExpense) console.log('[PASS] 支出类型显示'); - if (hasIncome) console.log('[PASS] 收入类型显示'); - - // 检查金额显示 - const hasAmount = /\d+\.?\d*/.test(pageText); - result.checks.push({ - item: '金额显示', - found: hasAmount, - status: hasAmount ? 'PASS' : 'FAIL' - }); - - if (hasAmount) { - console.log('[PASS] 金额数据存在'); - } else { - console.log('[FAIL] 未找到金额数据'); - result.issues.push('金额数据未显示'); - } - - } catch (error) { - result.issues.push(`测试异常: ${error.message}`); - console.error(`[ERROR] 记账页面测试失败: ${error.message}`); - } - - return result; -} - -/** - * 测试预算页面 (/budget) - */ -async function testBudget(page) { - console.log('\n========== 测试预算页面 (/budget) =========='); - const result = { - url: `${BASE_URL}/budget`, - checks: [], - issues: [], - screenshot: null - }; - - try { - // 导航到预算页面 - await page.goto(`${BASE_URL}/budget`, { waitUntil: 'networkidle' }); - await delay(2000); - - // 截图 - const screenshotPath = path.join(SCREENSHOT_DIR, '03-budget.png'); - await page.screenshot({ path: screenshotPath, fullPage: true }); - result.screenshot = screenshotPath; - console.log(`截图已保存: ${screenshotPath}`); - - // 获取页面文本 - const pageText = await page.textContent('body'); - - // 检查预算数据 - console.log('\n--- 检查预算数据 ---'); - - // 预期预算类别 - const expectedCategories = ['餐饮', '交通', '购物', '娱乐']; - - for (const category of expectedCategories) { - const hasCategory = pageText.includes(category); - - result.checks.push({ - item: `预算类别 - ${category}`, - found: hasCategory, - status: hasCategory ? 'PASS' : 'WARN' - }); - - if (hasCategory) { - console.log(`[PASS] 预算类别 "${category}" 显示`); - } else { - console.log(`[WARN] 预算类别 "${category}" 未找到`); - } - } - - // 检查预算进度 - console.log('\n--- 检查预算进度 ---'); - - // 查找进度条元素 - const progressBars = await page.locator('[class*="progress"], [role="progressbar"]').all(); - console.log(`找到 ${progressBars.length} 个进度条元素`); - - const hasProgress = progressBars.length > 0 || - pageText.includes('%') || - pageText.includes('进度'); - - result.checks.push({ - item: '预算进度显示', - found: hasProgress, - status: hasProgress ? 'PASS' : 'WARN' - }); - - if (hasProgress) { - console.log('[PASS] 预算进度显示'); - } else { - console.log('[WARN] 预算进度可能未正确显示'); - result.issues.push('预算进度显示可能有问题'); - } - - // 检查预算金额 - const hasBudgetAmount = /\d+/.test(pageText); - result.checks.push({ - item: '预算金额显示', - found: hasBudgetAmount, - status: hasBudgetAmount ? 'PASS' : 'FAIL' - }); - - if (hasBudgetAmount) { - console.log('[PASS] 预算金额数据存在'); - } else { - console.log('[FAIL] 未找到预算金额数据'); - result.issues.push('预算金额数据未显示'); - } - - } catch (error) { - result.issues.push(`测试异常: ${error.message}`); - console.error(`[ERROR] 预算页面测试失败: ${error.message}`); - } - - return result; -} - -/** - * 测试统计页面 (/statistics) - */ -async function testStatistics(page) { - console.log('\n========== 测试统计页面 (/statistics) =========='); - const result = { - url: `${BASE_URL}/statistics`, - checks: [], - issues: [], - screenshot: null - }; - - try { - // 导航到统计页面 - await page.goto(`${BASE_URL}/statistics`, { waitUntil: 'networkidle' }); - await delay(3000); // 图表加载需要更多时间 - - // 截图 - const screenshotPath = path.join(SCREENSHOT_DIR, '04-statistics.png'); - await page.screenshot({ path: screenshotPath, fullPage: true }); - result.screenshot = screenshotPath; - console.log(`截图已保存: ${screenshotPath}`); - - // 获取页面文本 - const pageText = await page.textContent('body'); - - // 检查图表显示 - console.log('\n--- 检查图表显示 ---'); - - // 查找图表容器 - const chartContainers = await page.locator('[class*="chart"], [id*="chart"], canvas').all(); - console.log(`找到 ${chartContainers.length} 个图表元素`); - - const hasChart = chartContainers.length > 0; - - result.checks.push({ - item: '图表容器', - expected: '至少 1 个图表', - found: hasChart, - status: hasChart ? 'PASS' : 'FAIL' - }); - - if (hasChart) { - console.log('[PASS] 图表容器存在'); - } else { - console.log('[FAIL] 未找到图表容器'); - result.issues.push('图表未正确渲染'); - } - - // 检查图表切换按钮 - console.log('\n--- 检查图表切换功能 ---'); - - // 查找切换按钮 - const switchButtons = await page.locator('button').all(); - let foundButtons = []; - - for (const button of switchButtons) { - const text = await button.textContent(); - if (text && (text.includes('饼图') || text.includes('折线') || text.includes('柱状'))) { - foundButtons.push(text.trim()); - } - } - - console.log(`找到切换按钮: ${foundButtons.join(', ')}`); - - result.checks.push({ - item: '图表切换按钮', - expected: '饼图、折线图、柱状图', - found: foundButtons.length >= 3, - status: foundButtons.length >= 3 ? 'PASS' : 'WARN' - }); - - if (foundButtons.length >= 3) { - console.log('[PASS] 图表切换按钮存在'); - - // 测试切换功能 - console.log('\n--- 测试图表切换 ---'); - - // 尝试点击饼图按钮 - const pieButton = await page.locator('button:has-text("饼图")').first(); - if (await pieButton.isVisible()) { - await pieButton.click(); - await delay(1000); - console.log('[INFO] 点击了饼图按钮'); - - // 截图 - const pieScreenshot = path.join(SCREENSHOT_DIR, '04-statistics-pie.png'); - await page.screenshot({ path: pieScreenshot, fullPage: true }); - } - - // 尝试点击折线图按钮 - const lineButton = await page.locator('button:has-text("折线")').first(); - if (await lineButton.isVisible()) { - await lineButton.click(); - await delay(1000); - console.log('[INFO] 点击了折线图按钮'); - - // 截图 - const lineScreenshot = path.join(SCREENSHOT_DIR, '04-statistics-line.png'); - await page.screenshot({ path: lineScreenshot, fullPage: true }); - } - - // 尝试点击柱状图按钮 - const barButton = await page.locator('button:has-text("柱状")').first(); - if (await barButton.isVisible()) { - await barButton.click(); - await delay(1000); - console.log('[INFO] 点击了柱状图按钮'); - - // 截图 - const barScreenshot = path.join(SCREENSHOT_DIR, '04-statistics-bar.png'); - await page.screenshot({ path: barScreenshot, fullPage: true }); - } - - result.checks.push({ - item: '图表切换功能', - found: true, - status: 'PASS' - }); - console.log('[PASS] 图表切换功能正常'); - - } else { - console.log('[WARN] 未找到完整的图表切换按钮'); - result.issues.push('图表切换按钮不完整'); - } - - // 检查是否有数据标签 - const hasDataLabels = pageText.includes('餐饮') || - pageText.includes('交通') || - pageText.includes('购物') || - pageText.includes('娱乐') || - pageText.includes('支出') || - pageText.includes('收入'); - - result.checks.push({ - item: '数据标签', - found: hasDataLabels, - status: hasDataLabels ? 'PASS' : 'WARN' - }); - - if (hasDataLabels) { - console.log('[PASS] 数据标签存在'); - } else { - console.log('[WARN] 数据标签可能未正确显示'); - } - - } catch (error) { - result.issues.push(`测试异常: ${error.message}`); - console.error(`[ERROR] 统计页面测试失败: ${error.message}`); - } - - return result; -} - -/** - * 主测试函数 - */ -async function runTests() { - console.log('========================================'); - console.log(' 前端页面数据验证测试 - 修正版'); - console.log(' 测试时间:', new Date().toLocaleString()); - console.log(' 前端地址:', BASE_URL); - console.log('========================================'); - - // 启动浏览器 - const browser = await chromium.launch({ - headless: false, // 可视化模式,方便观察 - slowMo: 100 - }); - - const context = await browser.newContext({ - viewport: { width: 1280, height: 800 } - }); - - const page = await context.newPage(); - - try { - // 测试首页 - testResults.pages.dashboard = await testDashboard(page); - - // 测试记账页面 - testResults.pages.record = await testRecord(page); - - // 测试预算页面 - testResults.pages.budget = await testBudget(page); - - // 测试统计页面 - testResults.pages.statistics = await testStatistics(page); - - } finally { - await browser.close(); - } - - // 统计结果 - console.log('\n========================================'); - console.log(' 测试结果汇总'); - console.log('========================================'); - - for (const [pageName, result] of Object.entries(testResults.pages)) { - console.log(`\n【${pageName.toUpperCase()}】`); - console.log(` URL: ${result.url}`); - console.log(` 截图: ${result.screenshot || '无'}`); - - const passed = result.checks.filter(c => c.status === 'PASS').length; - const failed = result.checks.filter(c => c.status === 'FAIL').length; - const warned = result.checks.filter(c => c.status === 'WARN').length; - - console.log(` 检查项: ${passed} 通过, ${failed} 失败, ${warned} 警告`); - - if (result.issues.length > 0) { - console.log(` 问题列表:`); - result.issues.forEach(issue => console.log(` - ${issue}`)); - } - - testResults.summary.total += result.checks.length; - testResults.summary.passed += passed; - testResults.summary.failed += failed; - testResults.summary.warnings += warned; - } - - console.log('\n----------------------------------------'); - console.log(`总计: ${testResults.summary.passed}/${testResults.summary.total} 通过`); - console.log(`失败: ${testResults.summary.failed}`); - console.log(`警告: ${testResults.summary.warnings}`); - console.log('----------------------------------------'); - - // 保存测试报告 - const reportPath = path.join(SCREENSHOT_DIR, 'test-report.json'); - fs.writeFileSync(reportPath, JSON.stringify(testResults, null, 2)); - console.log(`\n测试报告已保存: ${reportPath}`); - - return testResults; -} - -// 执行测试 -runTests().catch(console.error);