From f92d698cf22274493be8bccfe047d88c20b8d31f Mon Sep 17 00:00:00 2001 From: snowgitea Date: Wed, 29 Apr 2026 02:11:55 +0800 Subject: [PATCH] chore: remove verify-data-consistency.js --- verify-data-consistency.js | 416 ------------------------------------- 1 file changed, 416 deletions(-) delete mode 100644 verify-data-consistency.js diff --git a/verify-data-consistency.js b/verify-data-consistency.js deleted file mode 100644 index d27ae30..0000000 --- a/verify-data-consistency.js +++ /dev/null @@ -1,416 +0,0 @@ -/** - * 前后端数据一致性验证测试 - * - * 验证内容: - * 1. 首页 - Dashboard Summary - * 2. 记账页面 - Records - * 3. 预算页面 - Budgets - * 4. 统计页面 - Statistics - * - * 验证标准: - * - 金额误差:0.01 - * - 百分比误差:0.1% - * - 计数误差:0 - */ - -const { chromium } = require('playwright'); -const fs = require('fs'); -const path = require('path'); - -// 配置 -const CONFIG = { - frontendUrl: 'http://localhost:5173', - backendUrl: 'http://localhost:3001', - userId: 6, - tolerance: { - amount: 0.01, - percentage: 0.1, - count: 0 - } -}; - -// 测试结果 -const testResults = { - timestamp: new Date().toISOString(), - summary: { - total: 0, - passed: 0, - failed: 0 - }, - pages: [] -}; - -// API 数据获取 -async function fetchApiData(endpoint) { - const response = await fetch(`${CONFIG.backendUrl}${endpoint}`); - const data = await response.json(); - return data.data; -} - -// 比较数值(考虑误差) -function compareNumbers(actual, expected, tolerance = CONFIG.tolerance.amount) { - const diff = Math.abs(actual - expected); - return { - match: diff <= tolerance, - actual, - expected, - diff - }; -} - -// 主测试函数 -async function runTests() { - console.log('========================================'); - console.log('前后端数据一致性验证测试'); - console.log('========================================\n'); - - const browser = await chromium.launch({ headless: false }); - const context = await browser.newContext(); - const page = await context.newPage(); - - try { - // ======================================== - // 1. 首页验证 - // ======================================== - console.log('[1/4] 验证首页数据...'); - testResults.summary.total++; - - const dashboardApiData = await fetchApiData(`/api/dashboard/summary?userId=${CONFIG.userId}`); - - await page.goto(CONFIG.frontendUrl); - await page.waitForLoadState('networkidle'); - await page.waitForTimeout(2000); - - // 截图 - const dashboardScreenshot = path.join(__dirname, 'test-screenshots', 'verify-dashboard.png'); - await page.screenshot({ path: dashboardScreenshot, fullPage: true }); - - // 提取页面数据 - const pageData = await page.evaluate(() => { - const getText = (selector) => { - const el = document.querySelector(selector); - return el ? el.textContent.trim() : null; - }; - - const parseAmount = (text) => { - if (!text) return null; - const match = text.match(/[\d,]+\.?\d*/); - return match ? parseFloat(match[0].replace(/,/g, '')) : null; - }; - - // 尝试多种选择器 - const balanceText = getText('.balance-amount, [data-testid="balance"], .total-balance, h2'); - const incomeText = getText('.income-amount, [data-testid="income"], .month-income'); - const expenseText = getText('.expense-amount, [data-testid="expense"], .month-expense'); - - return { - balance: parseAmount(balanceText), - income: parseAmount(incomeText), - expense: parseAmount(expenseText), - balanceText, - incomeText, - expenseText - }; - }); - - // 比较 - const dashboardResult = { - page: '首页 (Dashboard)', - url: CONFIG.frontendUrl, - screenshot: dashboardScreenshot, - apiData: { - totalBalance: dashboardApiData.totalBalance, - monthIncome: dashboardApiData.monthIncome, - monthExpense: dashboardApiData.monthExpense - }, - pageData: pageData, - comparisons: { - totalBalance: compareNumbers(pageData.balance || dashboardApiData.totalBalance, dashboardApiData.totalBalance), - monthIncome: compareNumbers(pageData.income || dashboardApiData.monthIncome, dashboardApiData.monthIncome), - monthExpense: compareNumbers(pageData.expense || dashboardApiData.monthExpense, dashboardApiData.monthExpense) - }, - passed: true, - issues: [] - }; - - // 检查账户数量 - 首页没有账户列表卡片,跳过此检查 - // 检查预算进度数量 - const budgetProgressCount = await page.locator('.budget-progress-item').count(); - if (budgetProgressCount !== dashboardApiData.budgetUsage.length) { - dashboardResult.issues.push(`预算进度数量不一致: 页面显示 ${budgetProgressCount} 个, API返回 ${dashboardApiData.budgetUsage.length} 个`); - } - - if (dashboardResult.issues.length > 0) { - dashboardResult.passed = false; - } - - if (dashboardResult.passed) { - testResults.summary.passed++; - console.log(' [PASS] 首页数据验证通过'); - } else { - testResults.summary.failed++; - console.log(' [FAIL] 首页数据验证失败'); - dashboardResult.issues.forEach(issue => console.log(` - ${issue}`)); - } - - testResults.pages.push(dashboardResult); - - // ======================================== - // 2. 记账页面验证 - // ======================================== - console.log('\n[2/4] 验证记账页面数据...'); - testResults.summary.total++; - - const recordsApiData = await fetchApiData(`/api/records?userId=${CONFIG.userId}`); - - // 导航到记账页面 - await page.click('a[href="/record"], button:has-text("记账"), nav a:has-text("记账")').catch(() => { - return page.goto(`${CONFIG.frontendUrl}/record`); - }); - await page.waitForLoadState('networkidle'); - await page.waitForTimeout(2000); - - const recordScreenshot = path.join(__dirname, 'test-screenshots', 'verify-record.png'); - await page.screenshot({ path: recordScreenshot, fullPage: true }); - - // 提取页面记录数量 - const recordPageData = await page.evaluate(() => { - const records = document.querySelectorAll('.record-item, [data-testid="record"], tr[data-id]'); - return { - recordCount: records.length - }; - }); - - const recordResult = { - page: '记账页面 (Records)', - url: `${CONFIG.frontendUrl}/record`, - screenshot: recordScreenshot, - apiData: { - recordCount: recordsApiData.length, - records: recordsApiData.slice(0, 5) // 只保存前5条 - }, - pageData: recordPageData, - comparisons: { - recordCount: { - match: recordPageData.recordCount === recordsApiData.length, - actual: recordPageData.recordCount, - expected: recordsApiData.length, - diff: Math.abs(recordPageData.recordCount - recordsApiData.length) - } - }, - passed: recordPageData.recordCount === recordsApiData.length, - issues: [] - }; - - if (!recordResult.passed) { - recordResult.issues.push(`记录数量不一致: 页面显示 ${recordPageData.recordCount} 条, API返回 ${recordsApiData.length} 条`); - } - - if (recordResult.passed) { - testResults.summary.passed++; - console.log(' [PASS] 记账页面数据验证通过'); - } else { - testResults.summary.failed++; - console.log(' [FAIL] 记账页面数据验证失败'); - recordResult.issues.forEach(issue => console.log(` - ${issue}`)); - } - - testResults.pages.push(recordResult); - - // ======================================== - // 3. 预算页面验证 - // ======================================== - console.log('\n[3/4] 验证预算页面数据...'); - testResults.summary.total++; - - const budgetsApiData = await fetchApiData(`/api/budgets?userId=${CONFIG.userId}`); - - // 导航到预算页面 - await page.click('a[href="/budget"], button:has-text("预算"), nav a:has-text("预算")').catch(() => { - return page.goto(`${CONFIG.frontendUrl}/budget`); - }); - await page.waitForLoadState('networkidle'); - await page.waitForTimeout(2000); - - const budgetScreenshot = path.join(__dirname, 'test-screenshots', 'verify-budget.png'); - await page.screenshot({ path: budgetScreenshot, fullPage: true }); - - // 提取页面预算数据 - const budgetPageData = await page.evaluate(() => { - // 预算页面显示的是所有分类(6个),不是已设置的预算数量 - // 所以我们需要检查已设置预算的分类数量 - const categoryCards = document.querySelectorAll('.category-card[data-category]'); - const budgetItems = document.querySelectorAll('.budget-progress-item'); - - // 统计有预算的分类(进度条存在) - let budgetSetCount = 0; - categoryCards.forEach(card => { - const progressBar = card.querySelector('.progress-fill'); - if (progressBar && progressBar.style.width !== '0%' && progressBar.style.width !== '') { - budgetSetCount++; - } - }); - - return { - categoryCount: categoryCards.length, - budgetSetCount: budgetSetCount, - budgetProgressCount: budgetItems.length - }; - }); - - const budgetResult = { - page: '预算页面 (Budgets)', - url: `${CONFIG.frontendUrl}/budget`, - screenshot: budgetScreenshot, - apiData: { - budgetCount: budgetsApiData.length, - budgets: budgetsApiData - }, - pageData: budgetPageData, - comparisons: { - budgetCount: { - match: budgetPageData.budgetSetCount === budgetsApiData.length, - actual: budgetPageData.budgetSetCount, - expected: budgetsApiData.length, - diff: Math.abs(budgetPageData.budgetSetCount - budgetsApiData.length) - } - }, - passed: budgetPageData.budgetSetCount === budgetsApiData.length, - issues: [] - }; - - if (!budgetResult.passed) { - budgetResult.issues.push(`已设置预算的分类数量不一致: 页面显示 ${budgetPageData.budgetSetCount} 个, API返回 ${budgetsApiData.length} 个`); - } - - if (budgetResult.passed) { - testResults.summary.passed++; - console.log(' [PASS] 预算页面数据验证通过'); - } else { - testResults.summary.failed++; - console.log(' [FAIL] 预算页面数据验证失败'); - budgetResult.issues.forEach(issue => console.log(` - ${issue}`)); - } - - testResults.pages.push(budgetResult); - - // ======================================== - // 4. 统计页面验证 - // ======================================== - console.log('\n[4/4] 验证统计页面数据...'); - testResults.summary.total++; - - const trendApiData = await fetchApiData(`/api/statistics/trend?userId=${CONFIG.userId}`); - const compareApiData = await fetchApiData(`/api/statistics/compare?userId=${CONFIG.userId}&month=2026-04`); - - // 导航到统计页面 - await page.click('a[href="/statistics"], button:has-text("统计"), nav a:has-text("统计")').catch(() => { - return page.goto(`${CONFIG.frontendUrl}/statistics`); - }); - await page.waitForLoadState('networkidle'); - await page.waitForTimeout(2000); - - const statisticsScreenshot = path.join(__dirname, 'test-screenshots', 'verify-statistics.png'); - await page.screenshot({ path: statisticsScreenshot, fullPage: true }); - - // 提取页面统计数据 - const statisticsPageData = await page.evaluate(() => { - // 检查图表是否存在 - const charts = document.querySelectorAll('canvas, .echarts-container, [data-testid="chart"]'); - - // 检查月度对比数据 - const currentMonthIncome = document.querySelector('.current-income, [data-testid="current-income"]')?.textContent?.trim(); - const currentMonthExpense = document.querySelector('.current-expense, [data-testid="current-expense"]')?.textContent?.trim(); - const lastMonthIncome = document.querySelector('.last-income, [data-testid="last-income"]')?.textContent?.trim(); - const lastMonthExpense = document.querySelector('.last-expense, [data-testid="last-expense"]')?.textContent?.trim(); - - const parseAmount = (text) => { - if (!text) return null; - const match = text.match(/[\d,]+\.?\d*/); - return match ? parseFloat(match[0].replace(/,/g, '')) : null; - }; - - return { - chartCount: charts.length, - currentMonth: { - income: parseAmount(currentMonthIncome), - expense: parseAmount(currentMonthExpense) - }, - lastMonth: { - income: parseAmount(lastMonthIncome), - expense: parseAmount(lastMonthExpense) - } - }; - }); - - const statisticsResult = { - page: '统计页面 (Statistics)', - url: `${CONFIG.frontendUrl}/statistics`, - screenshot: statisticsScreenshot, - apiData: { - trend: trendApiData, - compare: compareApiData - }, - pageData: statisticsPageData, - comparisons: { - chartCount: { - match: statisticsPageData.chartCount > 0, - actual: statisticsPageData.chartCount, - expected: '>= 1', - diff: 0 - }, - currentMonthIncome: compareNumbers( - statisticsPageData.currentMonth.income || compareApiData.currentMonth.income, - compareApiData.currentMonth.income - ), - currentMonthExpense: compareNumbers( - statisticsPageData.currentMonth.expense || compareApiData.currentMonth.expense, - compareApiData.currentMonth.expense - ) - }, - passed: statisticsPageData.chartCount > 0, - issues: [] - }; - - if (statisticsPageData.chartCount === 0) { - statisticsResult.issues.push('未检测到图表元素'); - } - - if (statisticsResult.passed) { - testResults.summary.passed++; - console.log(' [PASS] 统计页面数据验证通过'); - } else { - testResults.summary.failed++; - console.log(' [FAIL] 统计页面数据验证失败'); - statisticsResult.issues.forEach(issue => console.log(` - ${issue}`)); - } - - testResults.pages.push(statisticsResult); - - } catch (error) { - console.error('\n[FATAL] 测试执行出错:', error.message); - testResults.error = error.message; - } finally { - await browser.close(); - } - - // 输出测试报告 - console.log('\n========================================'); - console.log('测试报告'); - console.log('========================================'); - console.log(`总计: ${testResults.summary.total} 个测试`); - console.log(`通过: ${testResults.summary.passed} 个`); - console.log(`失败: ${testResults.summary.failed} 个`); - console.log(`通过率: ${((testResults.summary.passed / testResults.summary.total) * 100).toFixed(1)}%`); - console.log('========================================\n'); - - // 保存测试报告 - const reportPath = path.join(__dirname, 'test-screenshots', 'data-consistency-report.json'); - fs.writeFileSync(reportPath, JSON.stringify(testResults, null, 2)); - console.log(`测试报告已保存: ${reportPath}`); - - return testResults; -} - -// 执行测试 -runTests().catch(console.error);