import fs from 'fs'; import { FullConfig, Reporter, Suite, TestCase, TestError } from '@playwright/test/reporter'; class CustomReporter implements Reporter { onEnd(config: FullConfig, result: any) { const outputPath = 'tests/output/latest-result.txt'; const allTests = result.suites || []; const failed = result.status === 'failed' || result.numFailedTests > 0; const date = new Date().toISOString(); const duration = (result.duration || 0) + 'ms'; if (!fs.existsSync('tests/output')) fs.mkdirSync('tests/output', { recursive: true }); if (!failed) { const content = [ '==================================', 'TEST RESULT', 'PASSED', `Date: ${date}`, `Total Test: ${result.total || 0}`, `Passed: ${result.passed || 0}`, `Failed: ${result.failed || 0}`, `Duration: ${duration}`, '==================================', ].join('\n'); fs.writeFileSync(outputPath, content, 'utf-8'); return; } // Failed: build detailed report const lines: string[] = []; lines.push('=================================='); lines.push('FAILED'); lines.push(`Date: ${date}`); lines.push(`Duration: ${duration}`); lines.push('=================================='); for (const res of result.report || []) { // older Playwright may not provide report; fallback to result.annotations } // Walk tests const buildFailureDetails = (suites: any[]) => { for (const s of suites) { if (s.suites && s.suites.length) buildFailureDetails(s.suites); if (s.tests && s.tests.length) { for (const t of s.tests) { if (t.status === 'failed') { lines.push('Test Name: ' + t.title.join(' > ')); // try extract location const location = t.location ? `${t.location.file}:${t.location.line}` : ''; if (location) lines.push('Location: ' + location); for (const r of t.results || []) { if (r.status === 'failed') { const error = r.error as TestError | undefined; lines.push('Error Message: ' + (error?.message || '')); if (r.stdout && r.stdout.length) lines.push('Stdout: ' + r.stdout.join('\n')); if (error?.stack) lines.push('Stack Trace: ' + error.stack); } } lines.push('----------------------------------'); } } } } }; if (result.suites) buildFailureDetails(result.suites); fs.writeFileSync(outputPath, lines.join('\n'), 'utf-8'); } } export default CustomReporter;