Files
novalon-website/e2e/run-tests-with-progress.js
T
张翔 5d5b7feb0a feat(e2e): 添加完整的E2E测试框架和测试用例
添加Playwright测试框架配置和基础页面对象
实现冒烟测试用例覆盖首页和联系页面核心功能
更新导航组件以支持滚动高亮功能
添加BackButton组件统一返回按钮行为
配置Woodpecker CI集成和测试报告生成
2026-02-27 10:30:33 +08:00

148 lines
5.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
const { spawn } = require('child_process');
const fs = require('fs');
const { glob } = require('glob');
const testTypes = [
{ name: '冒烟测试', script: 'test:smoke', pattern: 'src/tests/smoke/**/*.spec.ts' },
{ name: '回归测试', script: 'test:regression', pattern: 'src/tests/regression/**/*.spec.ts' },
{ name: '性能测试', script: 'test:performance', pattern: 'src/tests/performance/**/*.spec.ts' },
{ name: '响应式测试', script: 'test:responsive', pattern: 'src/tests/responsive/**/*.spec.ts' }
];
const TIMEOUT_SECONDS = 600;
async function runTests() {
console.log('🧪 开始运行E2E测试...\n');
const results = {
total: 0,
passed: 0,
failed: 0,
byType: {}
};
for (const testType of testTypes) {
console.log(`\n${'='.repeat(60)}`);
console.log(`📋 ${testType.name}`);
console.log(`${'='.repeat(60)}`);
await new Promise((resolve) => {
const startTime = Date.now();
let lastUpdateTime = startTime;
let currentTest = 0;
let passedCount = 0;
let failedCount = 0;
let isComplete = false;
let lastTestName = '';
const testProcess = spawn('npm', ['run', testType.script], {
cwd: __dirname,
shell: true,
stdio: ['pipe', 'pipe', 'pipe']
});
testProcess.stdout.on('data', (data) => {
const output = data.toString();
if (output.includes('')) {
currentTest++;
const progress = Math.min(100, Math.round((currentTest / 100) * 100));
const elapsed = Math.round((Date.now() - startTime) / 1000);
const barLength = Math.floor(progress / 2);
const bar = '█'.repeat(barLength) + '░'.repeat(50 - barLength);
const testNameMatch = output.match(/\s+(.+)/);
if (testNameMatch) {
lastTestName = testNameMatch[1].trim();
}
process.stdout.write(`\r⏳ 进度: [${bar}] ${progress}% - ${elapsed}s - ${lastTestName}`);
lastUpdateTime = Date.now();
}
if (output.includes('passed')) {
const match = output.match(/(\d+)\s+passed/);
if (match) {
passedCount = parseInt(match[1]);
}
}
if (output.includes('failed')) {
const match = output.match(/(\d+)\s+failed/);
if (match) {
failedCount = parseInt(match[1]);
}
}
});
testProcess.stderr.on('data', (data) => {
const output = data.toString();
if (output.includes('Error') || output.includes('error')) {
process.stdout.write('\n❌ 错误: ' + output);
}
});
testProcess.on('close', (code) => {
isComplete = true;
const elapsed = Math.round((Date.now() - startTime) / 1000);
process.stdout.write(`\r✅ 完成: [${'█'.repeat(50)}] 100% - ${elapsed}s\n`);
results.total += passedCount + failedCount;
results.passed += passedCount;
results.failed += failedCount;
results.byType[testType.name] = {
total: passedCount + failedCount,
passed: passedCount,
failed: failedCount,
elapsed: elapsed
};
resolve();
});
const progressInterval = setInterval(() => {
if (!isComplete) {
const elapsed = Math.round((Date.now() - startTime) / 1000);
const timeSinceLastUpdate = Date.now() - lastUpdateTime;
if (timeSinceLastUpdate > 10000 && timeSinceLastUpdate < 30000) {
process.stdout.write(`\r⏳ 等待测试... (${elapsed}s) - ${lastTestName}`);
} else if (timeSinceLastUpdate >= 30000) {
process.stdout.write(`\r⚠️ 测试可能卡住 (${elapsed}s) - ${lastTestName}`);
}
if (elapsed > TIMEOUT_SECONDS) {
console.log(`\n❌ 测试超时 (${TIMEOUT_SECONDS}s),正在停止...`);
testProcess.kill();
clearInterval(progressInterval);
isComplete = true;
resolve();
}
}
}, 5000);
testProcess.on('close', () => {
clearInterval(progressInterval);
});
});
}
console.log(`\n${'='.repeat(60)}`);
console.log('📊 测试结果汇总');
console.log(`${'='.repeat(60)}`);
console.log(`总测试数: ${results.total}`);
console.log(`通过: ${results.passed} (${((results.passed / results.total) * 100).toFixed(1)}%)`);
console.log(`失败: ${results.failed} (${((results.failed / results.total) * 100).toFixed(1)}%)`);
console.log('\n分类结果:');
for (const [name, result] of Object.entries(results.byType)) {
const passRate = ((result.passed / result.total) * 100).toFixed(1);
const status = passRate >= 80 ? '✅' : passRate >= 50 ? '⚠️' : '❌';
console.log(` ${status} ${name}: ${result.passed}/${result.total} (${passRate}%) - ${result.elapsed}s`);
}
}
runTests().catch(console.error);