Files
n8n/packages/testing/playwright/scripts/generate-coverage-report.js
2025-12-29 10:37:15 +00:00

142 lines
4.5 KiB
JavaScript
Executable File

#!/usr/bin/env node
/**
* Simple script to merge coverage reports and generate HTML output
*/
const { execSync } = require('child_process');
const path = require('path');
const fs = require('fs');
const NYC_OUTPUT_DIR = path.join(__dirname, '..', '.nyc_output');
const COVERAGE_DIR = path.join(__dirname, '..', 'coverage');
const NYC_CONFIG = path.join(__dirname, '..', 'nyc.config.ts');
// Coverage directories to look for - Currents writes to .nyc_output/{projectName}/
// Project names come from playwright-projects.ts
const COVERAGE_PROJECT_PATTERNS = [
'e2e', // Local mode project
'sqlite:e2e', // Container mode projects
'sqlite:e2e:isolated',
'postgres:e2e',
'postgres:e2e:isolated',
'queue:e2e',
'queue:e2e:isolated',
'multi-main:e2e',
'multi-main:e2e:isolated',
];
/**
* Find all coverage directories that exist and contain JSON files
*/
function findCoverageDirectories() {
const foundDirs = [];
for (const projectName of COVERAGE_PROJECT_PATTERNS) {
const projectDir = path.join(NYC_OUTPUT_DIR, projectName);
if (fs.existsSync(projectDir)) {
const files = fs.readdirSync(projectDir);
const jsonFiles = files.filter((f) => f.endsWith('.json'));
if (jsonFiles.length > 0) {
foundDirs.push({ dir: projectDir, projectName, fileCount: jsonFiles.length });
}
}
}
return foundDirs;
}
function main() {
console.log('🔍 Generating Coverage Report');
console.log('==============================\n');
// Find all coverage directories
const coverageDirs = findCoverageDirectories();
if (coverageDirs.length === 0) {
console.error('❌ No coverage data found in .nyc_output/');
console.log('\nSearched for coverage in these project directories:');
COVERAGE_PROJECT_PATTERNS.forEach((p) => console.log(` - .nyc_output/${p}/`));
console.log('\nTo generate coverage data:');
console.log(
'1. Build editor-ui with coverage: BUILD_WITH_COVERAGE=true pnpm --filter n8n-editor-ui build',
);
console.log(
'2. Run Playwright tests with coverage: BUILD_WITH_COVERAGE=true pnpm test:container:sqlite',
);
process.exit(1);
}
console.log('Found coverage data in:');
coverageDirs.forEach(({ projectName, fileCount }) =>
console.log(` - ${projectName}: ${fileCount} files`),
);
console.log('');
try {
// Merge coverage files from all found project directories
// nyc merge only accepts one input directory, so we need to:
// 1. Copy all JSON files to a single temp directory
// 2. Run nyc merge on that directory
console.log('Merging coverage files from all projects...');
const mergedFile = path.join(NYC_OUTPUT_DIR, 'out.json');
const tempMergeDir = path.join(NYC_OUTPUT_DIR, '_merge_temp');
// Create temp directory for merging
if (fs.existsSync(tempMergeDir)) {
fs.rmSync(tempMergeDir, { recursive: true });
}
fs.mkdirSync(tempMergeDir, { recursive: true });
// Copy all JSON files from all project directories to the temp directory
let fileIndex = 0;
for (const { dir, projectName } of coverageDirs) {
const files = fs.readdirSync(dir).filter((f) => f.endsWith('.json'));
for (const file of files) {
const srcPath = path.join(dir, file);
// Use unique names to avoid collisions between projects
const destPath = path.join(
tempMergeDir,
`${projectName.replace(/:/g, '_')}_${fileIndex++}_${file}`,
);
fs.copyFileSync(srcPath, destPath);
}
}
console.log(`Copied ${fileIndex} coverage files to temp directory`);
// Now merge the single temp directory
execSync(`npx nyc merge "${tempMergeDir}" "${mergedFile}"`, { stdio: 'inherit' });
// Clean up temp directory
fs.rmSync(tempMergeDir, { recursive: true });
// Generate reports (HTML for viewing, LCOV for Codecov)
console.log('Generating coverage reports...');
execSync(
`npx nyc report --reporter=html --reporter=lcov --report-dir=${COVERAGE_DIR} --temp-dir=${NYC_OUTPUT_DIR} --config=${NYC_CONFIG} --exclude-after-remap=false`,
{ stdio: 'inherit' },
);
const htmlReportPath = path.join(COVERAGE_DIR, 'index.html');
const lcovPath = path.join(COVERAGE_DIR, 'lcov.info');
console.log(`\n✅ Coverage reports generated successfully!`);
if (fs.existsSync(htmlReportPath)) {
console.log(`📊 HTML Report: ${htmlReportPath}`);
}
if (fs.existsSync(lcovPath)) {
console.log(`📄 LCOV Report: ${lcovPath} (for Codecov)`);
}
} catch (error) {
console.error('❌ Failed to generate coverage report:', error.message);
process.exit(1);
}
}
if (require.main === module) {
main();
}
module.exports = { main };