mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-10 10:00:08 +00:00
- Add extract-playwright-counts.mjs script to parse test results from Playwright reports - Update pr-playwright-deploy-and-comment.sh to extract and display test counts - Show overall summary with passed/failed/flaky/skipped counts - Display per-browser test counts inline with report links - Use dynamic status icons based on test results (✅/❌/⚠️) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
130 lines
5.1 KiB
JavaScript
Executable File
130 lines
5.1 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
/**
|
|
* Extract test counts from Playwright HTML report
|
|
* @param {string} reportDir - Path to the playwright-report directory
|
|
* @returns {Object} Test counts { passed, failed, flaky, skipped, total }
|
|
*/
|
|
function extractTestCounts(reportDir) {
|
|
const counts = {
|
|
passed: 0,
|
|
failed: 0,
|
|
flaky: 0,
|
|
skipped: 0,
|
|
total: 0
|
|
};
|
|
|
|
try {
|
|
// First, try to find report.json which Playwright generates with JSON reporter
|
|
const jsonReportFile = path.join(reportDir, 'report.json');
|
|
if (fs.existsSync(jsonReportFile)) {
|
|
const reportJson = JSON.parse(fs.readFileSync(jsonReportFile, 'utf-8'));
|
|
if (reportJson.stats) {
|
|
counts.total = reportJson.stats.expected || 0;
|
|
counts.passed = reportJson.stats.expected - (reportJson.stats.unexpected || 0) - (reportJson.stats.flaky || 0) - (reportJson.stats.skipped || 0);
|
|
counts.failed = reportJson.stats.unexpected || 0;
|
|
counts.flaky = reportJson.stats.flaky || 0;
|
|
counts.skipped = reportJson.stats.skipped || 0;
|
|
return counts;
|
|
}
|
|
}
|
|
|
|
// Try index.html - Playwright HTML report embeds data in a script tag
|
|
const indexFile = path.join(reportDir, 'index.html');
|
|
if (fs.existsSync(indexFile)) {
|
|
const content = fs.readFileSync(indexFile, 'utf-8');
|
|
|
|
// Look for the embedded report data in various formats
|
|
// Format 1: window.playwrightReportBase64
|
|
let dataMatch = content.match(/window\.playwrightReportBase64\s*=\s*["']([^"']+)["']/);
|
|
if (dataMatch) {
|
|
try {
|
|
const decodedData = Buffer.from(dataMatch[1], 'base64').toString('utf-8');
|
|
const reportData = JSON.parse(decodedData);
|
|
|
|
if (reportData.stats) {
|
|
counts.total = reportData.stats.expected || 0;
|
|
counts.passed = reportData.stats.expected - (reportData.stats.unexpected || 0) - (reportData.stats.flaky || 0) - (reportData.stats.skipped || 0);
|
|
counts.failed = reportData.stats.unexpected || 0;
|
|
counts.flaky = reportData.stats.flaky || 0;
|
|
counts.skipped = reportData.stats.skipped || 0;
|
|
return counts;
|
|
}
|
|
} catch (e) {
|
|
// Continue to try other formats
|
|
}
|
|
}
|
|
|
|
// Format 2: window.playwrightReport
|
|
dataMatch = content.match(/window\.playwrightReport\s*=\s*({[\s\S]*?});/);
|
|
if (dataMatch) {
|
|
try {
|
|
// Use Function constructor instead of eval for safety
|
|
const reportData = (new Function('return ' + dataMatch[1]))();
|
|
|
|
if (reportData.stats) {
|
|
counts.total = reportData.stats.expected || 0;
|
|
counts.passed = reportData.stats.expected - (reportData.stats.unexpected || 0) - (reportData.stats.flaky || 0) - (reportData.stats.skipped || 0);
|
|
counts.failed = reportData.stats.unexpected || 0;
|
|
counts.flaky = reportData.stats.flaky || 0;
|
|
counts.skipped = reportData.stats.skipped || 0;
|
|
return counts;
|
|
}
|
|
} catch (e) {
|
|
// Continue to try other formats
|
|
}
|
|
}
|
|
|
|
// Format 3: Look for stats in the HTML content directly
|
|
// Playwright sometimes renders stats in the UI
|
|
const statsMatch = content.match(/(\d+)\s+passed[^0-9]*(\d+)\s+failed[^0-9]*(\d+)\s+flaky[^0-9]*(\d+)\s+skipped/i);
|
|
if (statsMatch) {
|
|
counts.passed = parseInt(statsMatch[1]) || 0;
|
|
counts.failed = parseInt(statsMatch[2]) || 0;
|
|
counts.flaky = parseInt(statsMatch[3]) || 0;
|
|
counts.skipped = parseInt(statsMatch[4]) || 0;
|
|
counts.total = counts.passed + counts.failed + counts.flaky + counts.skipped;
|
|
return counts;
|
|
}
|
|
|
|
// Format 4: Try to extract from summary text patterns
|
|
const passedMatch = content.match(/(\d+)\s+(?:tests?|specs?)\s+passed/i);
|
|
const failedMatch = content.match(/(\d+)\s+(?:tests?|specs?)\s+failed/i);
|
|
const flakyMatch = content.match(/(\d+)\s+(?:tests?|specs?)\s+flaky/i);
|
|
const skippedMatch = content.match(/(\d+)\s+(?:tests?|specs?)\s+skipped/i);
|
|
const totalMatch = content.match(/(\d+)\s+(?:tests?|specs?)\s+(?:total|ran)/i);
|
|
|
|
if (passedMatch) counts.passed = parseInt(passedMatch[1]) || 0;
|
|
if (failedMatch) counts.failed = parseInt(failedMatch[1]) || 0;
|
|
if (flakyMatch) counts.flaky = parseInt(flakyMatch[1]) || 0;
|
|
if (skippedMatch) counts.skipped = parseInt(skippedMatch[1]) || 0;
|
|
if (totalMatch) {
|
|
counts.total = parseInt(totalMatch[1]) || 0;
|
|
} else if (counts.passed || counts.failed || counts.flaky || counts.skipped) {
|
|
counts.total = counts.passed + counts.failed + counts.flaky + counts.skipped;
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error(`Error reading report from ${reportDir}:`, error);
|
|
}
|
|
|
|
return counts;
|
|
}
|
|
|
|
// Main execution
|
|
const reportDir = process.argv[2];
|
|
|
|
if (!reportDir) {
|
|
console.error('Usage: extract-playwright-counts.mjs <report-directory>');
|
|
process.exit(1);
|
|
}
|
|
|
|
const counts = extractTestCounts(reportDir);
|
|
|
|
// Output as JSON for easy parsing in shell script
|
|
console.log(JSON.stringify(counts));
|
|
|
|
export { extractTestCounts }; |