import * as fs from 'fs'; import * as path from 'path'; import { FullResult, Suite, TestCase, TestResult } from '@playwright/test/reporter'; export class CustomReporter { private results: any[] = []; private startTime: number = Date.now(); onBegin(_config: any, suite: Suite) { console.log('\n=== 测试执行开始 ==='); console.log(`测试套件: ${suite.allTests().length} 个测试`); } onTestBegin(test: TestCase) { console.log(`开始测试: ${test.title}`); } onTestEnd(test: TestCase, result: TestResult) { this.results.push({ name: test.title, status: result.status, duration: result.duration, type: this.getTestType(test.title) }); } onEnd(result: FullResult) { const duration = Date.now() - this.startTime; const report = this.generateCustomReport(result, duration); this.writeReport(report); } private getTestType(title: string): 'performance' | 'seo' | 'accessibility' | 'form' { if (title.includes('性能')) return 'performance'; if (title.includes('SEO')) return 'seo'; if (title.includes('可访问性')) return 'accessibility'; if (title.includes('表单')) return 'form'; return 'form'; } private generateCustomReport(_result: FullResult, duration: number): string { const passed = this.results.filter(r => r.status === 'passed').length; const failed = this.results.filter(r => r.status === 'failed').length; const passRate = ((passed / this.results.length) * 100).toFixed(2); return ` # 测试执行报告 生成时间: ${new Date().toLocaleString('zh-CN')} ## 概览 - 总测试数: ${this.results.length} - 通过: ${passed} - 失败: ${failed} - 跳过: ${this.results.filter(r => r.status === 'skipped').length} - 通过率: ${passRate}% - 执行时间: ${(duration / 1000).toFixed(2)}s ## 性能测试结果 ${this.generatePerformanceSection()} ## 失败测试 ${this.generateFailuresSection()} ## 测试详情 ${this.generateDetailsSection()} `; } private generatePerformanceSection(): string { const performanceTests = this.results.filter(r => r.type === 'performance'); if (performanceTests.length === 0) { return '无性能测试\n'; } return ` | 测试名称 | 状态 | 耗时(ms) | |---------|------|----------| ${performanceTests.map(t => `| ${t.name} | ${t.status} | ${t.duration.toFixed(0)} |`).join('\n')} `; } private generateFailuresSection(): string { const failedTests = this.results.filter(r => r.status === 'failed'); if (failedTests.length === 0) { return '✅ 所有测试通过\n'; } return ` ### 失败测试列表 (${failedTests.length}) ${failedTests.map(t => `- ${t.name} (${t.duration.toFixed(0)}ms)`).join('\n')} `; } private generateDetailsSection(): string { return ` | 测试名称 | 类型 | 状态 | 耗时(ms) | |---------|------|------|----------| ${this.results.map(t => `| ${t.name} | ${t.type} | ${t.status} | ${t.duration.toFixed(0)} |`).join('\n')} `; } private writeReport(report: string): void { const reportDir = path.join(process.cwd(), 'test-framework', 'reports'); if (!fs.existsSync(reportDir)) { fs.mkdirSync(reportDir, { recursive: true }); } const reportPath = path.join(reportDir, 'custom-report.md'); fs.writeFileSync(reportPath, report); console.log(`\n报告已生成: ${reportPath}`); } }