UNPKG

playwright-test-workflow

Version:

Global test workflow package for Playwright with custom reporters

129 lines (111 loc) 5.09 kB
const fs = require('fs'); const path = require('path'); class CustomHTMLReporter { constructor(options = {}) { this.outputDir = options.outputDir || 'test-results'; this.results = []; this.testGroupPatterns = options.testGroupPatterns || this.getDefaultPatterns(); } getDefaultPatterns() { return { 'TEST#1': ['load', 'display', 'show', 'heading', 'button', 'input', 'result display'], 'TEST#2': ['calculate', 'sum', 'negative', 'zero', 'large', 'decimal'], 'TEST#3': ['empty', 'non-numeric', 'precision', 'error', 'validation'], 'TEST#4': ['responsive', 'clickable', 'accept', 'update', 'ui', 'ux'] }; } determineTestGroup(testName) { const lowerName = testName.toLowerCase(); for (const [group, patterns] of Object.entries(this.testGroupPatterns)) { if (patterns.some(pattern => lowerName.includes(pattern))) { return group; } } return 'UNKNOWN'; } onTestEnd(test, result) { const status = result.status === 'passed' ? 'PASS' : 'FAIL'; const testName = test.title; const error = result.error ? result.error.message : ''; const duration = result.duration || 0; const testGroup = this.determineTestGroup(testName); this.results.push({ name: testName, status: status, error: error, group: testGroup, duration: duration }); } onEnd() { if (!fs.existsSync(this.outputDir)) { fs.mkdirSync(this.outputDir, { recursive: true }); } const testGroups = [...new Set(this.results.map(r => r.group))]; testGroups.forEach(group => { if (group === 'UNKNOWN') return; const groupTests = this.results.filter(t => t.group === group); const groupPassed = groupTests.filter(t => t.status === 'PASS').length; const groupFailed = groupTests.filter(t => t.status === 'FAIL').length; const groupTotal = groupTests.length; const html = this.generateHTML(group, groupTests, groupPassed, groupFailed, groupTotal); const groupFile = path.join(this.outputDir, `${group}-results.html`); fs.writeFileSync(groupFile, html); }); } generateHTML(group, tests, passed, failed, total) { return `<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>${group} Test Results</title> <style> body { font-family: Arial, sans-serif; margin: 20px; background-color: #f5f5f5; } .container { max-width: 1000px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } h1 { color: #333; border-bottom: 2px solid #ddd; padding-bottom: 10px; } .summary { background: #f9f9f9; padding: 15px; border-radius: 5px; margin: 20px 0; } .summary-item { display: inline-block; margin: 0 20px 0 0; } .pass { color: #44aa44; font-weight: bold; } .fail { color: #ff4444; font-weight: bold; } .test-item { margin: 10px 0; padding: 10px; border-left: 4px solid #ddd; background: #fafafa; } .test-item.pass { border-left-color: #44aa44; } .test-item.fail { border-left-color: #ff4444; background: #fff5f5; } .test-name { font-weight: bold; margin-bottom: 5px; } .test-error { color: #ff4444; font-size: 0.9em; margin-top: 5px; padding: 5px; background: #ffeeee; border-radius: 3px; } .test-duration { color: #666; font-size: 0.8em; } .status-badge { padding: 2px 6px; border-radius: 3px; color: white; font-size: 0.8em; font-weight: bold; } .status-pass { background: #44aa44; } .status-fail { background: #ff4444; } </style> </head> <body> <div class="container"> <h1>${group} Test Results</h1> <div class="summary"> <div class="summary-item"><strong>Total Tests:</strong> ${total}</div> <div class="summary-item"><strong class="pass">Passed:</strong> ${passed}</div> <div class="summary-item"><strong class="fail">Failed:</strong> ${failed}</div> <div class="summary-item"><strong>Success Rate:</strong> ${Math.round((passed / total) * 100)}%</div> </div> <div class="test-list"> ${tests.map(test => ` <div class="test-item ${test.status.toLowerCase()}"> <div class="test-name"> <span class="status-badge status-${test.status.toLowerCase()}">${test.status}</span> ${test.name} </div> <div class="test-duration">Duration: ${test.duration}ms</div> ${test.error ? `<div class="test-error">Error: ${test.error}</div>` : ''} </div> `).join('')} </div> <div style="margin-top: 30px; text-align: center; color: #666; font-size: 0.9em;"> Generated on ${new Date().toLocaleString()} </div> </div> </body> </html>`; } } module.exports = CustomHTMLReporter;