upskill-event-manager/wordpress-dev/tests/e2e/test-reporter.ts
bengizmo d6211ee364 feat(testing): Implement HVAC_Test_User_Factory and update .gitignore
- Add HVAC_Test_User_Factory class with:
  * User creation with specific roles
  * Multiple role support
  * Persona management system
  * Account cleanup integration
- Create comprehensive test suite in HVAC_Test_User_Factory_Test.php
- Update testing improvement plan documentation
- Add implementation decisions to project memory bank
- Restructure .gitignore with:
  * Whitelist approach for better file management
  * Explicit backup exclusions
  * Specific bin directory inclusions

Part of the Account Management component from the testing framework improvement plan.
2025-04-14 17:41:36 -03:00

180 lines
No EOL
4.7 KiB
TypeScript

import { Reporter, TestCase, TestResult, TestStep, TestError } from '@playwright/test/reporter';
import * as fs from 'fs';
import * as path from 'path';
class CustomReporter implements Reporter {
private reports: TestReport[] = [];
onBegin(config: any, suite: any) {
console.log('Starting the test run with', suite.allTests().length, 'tests');
}
onTestBegin(test: TestCase) {
console.log(`Starting test: ${test.title}`);
}
onTestEnd(test: TestCase, result: TestResult) {
const report: TestReport = {
title: test.title,
status: result.status,
duration: result.duration,
error: result.error ? this.formatError(result.error) : undefined,
steps: result.steps.map(step => this.formatStep(step)),
retries: test.retries,
timestamp: new Date().toISOString(),
};
this.reports.push(report);
this.logTestResult(report);
}
onEnd(result: any) {
const summary = this.generateSummary();
this.saveReports(summary);
console.log('Testing completed. Reports generated.');
}
private formatError(error: TestError): ErrorReport {
return {
message: error.message || 'Unknown error',
stack: error.stack,
value: error.value?.toString(),
};
}
private formatStep(step: TestStep): StepReport {
return {
title: step.title,
duration: step.duration,
error: step.error ? this.formatError(step.error) : undefined,
};
}
private generateSummary(): TestSummary {
const total = this.reports.length;
const passed = this.reports.filter(r => r.status === 'passed').length;
const failed = this.reports.filter(r => r.status === 'failed').length;
const skipped = this.reports.filter(r => r.status === 'skipped').length;
return {
total,
passed,
failed,
skipped,
timestamp: new Date().toISOString(),
duration: this.reports.reduce((sum, r) => sum + (r.duration || 0), 0),
tests: this.reports,
};
}
private logTestResult(report: TestReport) {
const status = this.getStatusSymbol(report.status);
console.log(`${status} ${report.title} (${report.duration}ms)`);
if (report.error) {
console.error('Error:', report.error.message);
if (report.error.stack) {
console.error('Stack:', report.error.stack);
}
}
}
private getStatusSymbol(status: string): string {
switch (status) {
case 'passed': return '✓';
case 'failed': return '✗';
case 'skipped': return '-';
default: return '?';
}
}
private saveReports(summary: TestSummary) {
const reportsDir = path.join(process.cwd(), 'test-results');
// Ensure reports directory exists
if (!fs.existsSync(reportsDir)) {
fs.mkdirSync(reportsDir, { recursive: true });
}
// Save JSON report
const jsonReport = path.join(reportsDir, 'test-report.json');
fs.writeFileSync(jsonReport, JSON.stringify(summary, null, 2));
// Save Markdown report
const mdReport = path.join(reportsDir, 'test-report.md');
fs.writeFileSync(mdReport, this.generateMarkdownReport(summary));
}
private generateMarkdownReport(summary: TestSummary): string {
const now = new Date().toISOString();
let md = `# Test Execution Report\n\n`;
md += `Generated: ${now}\n\n`;
md += `## Summary\n\n`;
md += `- Total Tests: ${summary.total}\n`;
md += `- Passed: ${summary.passed}\n`;
md += `- Failed: ${summary.failed}\n`;
md += `- Skipped: ${summary.skipped}\n`;
md += `- Total Duration: ${summary.duration}ms\n\n`;
md += `## Test Results\n\n`;
summary.tests.forEach(test => {
md += `### ${test.title}\n\n`;
md += `- Status: ${test.status}\n`;
md += `- Duration: ${test.duration}ms\n`;
if (test.error) {
md += `- Error: ${test.error.message}\n`;
if (test.error.stack) {
md += `\`\`\`\n${test.error.stack}\n\`\`\`\n`;
}
}
if (test.steps.length > 0) {
md += `\nSteps:\n`;
test.steps.forEach(step => {
md += `- ${step.title} (${step.duration}ms)\n`;
if (step.error) {
md += ` Error: ${step.error.message}\n`;
}
});
}
md += `\n`;
});
return md;
}
}
interface TestReport {
title: string;
status: string;
duration?: number;
error?: ErrorReport;
steps: StepReport[];
retries: number;
timestamp: string;
}
interface ErrorReport {
message: string;
stack?: string;
value?: string;
}
interface StepReport {
title: string;
duration?: number;
error?: ErrorReport;
}
interface TestSummary {
total: number;
passed: number;
failed: number;
skipped: number;
timestamp: string;
duration: number;
tests: TestReport[];
}
export default CustomReporter;