managarten/scripts/test-reporting/generate-summary.js
Wuesteon 304897261d test: implement comprehensive automated testing system with daily CI/CD
Implement rock-solid automated testing infrastructure for mana-core-auth
with daily execution, notifications, and comprehensive monitoring.

Test Suite Improvements:
- Fix all 36 failing BetterAuthService tests (missing service mocks)
- Add 21 JwtAuthGuard tests achieving 100% statement coverage
- Create silentError helper to suppress intentional error logs
- Fix Todo backend TaskService test structure
- Add jose mock for JWT testing
- Configure jest collectCoverageFrom for mana-core-auth

GitHub Actions Workflow:
- Daily automated test execution (2 AM UTC + manual trigger)
- Matrix parallelization across 6 backend services
- PostgreSQL and Redis service containers
- Coverage enforcement (80% threshold)
- Multi-channel notifications (Discord, Slack, GitHub Issues)
- Support for success notifications (opt-in)

Test Infrastructure:
- Coverage aggregation across multiple services
- Flaky test detection with 30-run history tracking
- Performance metrics tracking with regression detection
- Test data seeding and cleanup scripts
- Comprehensive test reporting with formatted metrics

Documentation:
- TESTING_GUIDE.md (4000+ words) - Complete testing documentation
- AUTOMATED_TESTING_SYSTEM.md - System architecture and workflows
- DISCORD_NOTIFICATIONS_SETUP.md - Discord webhook setup guide
- TESTING_DEPLOYMENT_CHECKLIST.md - Pre-deployment verification
- TESTING_QUICK_REFERENCE.md - Quick command reference

Final Result:
- 180/180 tests passing (100% pass rate)
- Zero console errors in test output
- Automated daily testing with rich notifications
- Production-ready test infrastructure
2025-12-25 19:12:27 +01:00

130 lines
3.4 KiB
JavaScript

#!/usr/bin/env node
/* eslint-disable @typescript-eslint/no-require-imports, no-console */
/**
* Generate Test Summary
*
* Creates a GitHub Actions summary with test results, coverage, and trends.
*
* Usage:
* node generate-summary.js <test-results-dir>
*/
const fs = require('fs');
const path = require('path');
function findTestResults(dir) {
const results = {
coverage: [],
testResults: [],
};
function walk(currentDir) {
if (!fs.existsSync(currentDir)) {
return;
}
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(currentDir, entry.name);
if (entry.isDirectory()) {
walk(fullPath);
} else if (entry.name === 'coverage-summary.json') {
results.coverage.push(fullPath);
} else if (entry.name.includes('test-results.json')) {
results.testResults.push(fullPath);
}
}
}
walk(dir);
return results;
}
function generateSummary(resultsDir) {
const { coverage } = findTestResults(resultsDir);
let summary = '# 🧪 Daily Test Suite Results\n\n';
summary += `**Date:** ${new Date().toISOString().split('T')[0]}\n\n`;
if (coverage.length === 0) {
summary += '⚠️ No coverage reports found.\n';
return summary;
}
// Aggregate coverage stats
const suites = [];
let totalPassed = 0;
let totalFailed = 0;
coverage.forEach((file) => {
const content = JSON.parse(fs.readFileSync(file, 'utf8'));
const suiteName = path.basename(path.dirname(path.dirname(file)));
if (content.total) {
suites.push({
name: suiteName,
lines: content.total.lines.pct,
statements: content.total.statements.pct,
functions: content.total.functions.pct,
branches: content.total.branches.pct,
});
}
});
// Coverage table
summary += '## Coverage by Suite\n\n';
summary += '| Suite | Lines | Statements | Functions | Branches | Status |\n';
summary += '|-------|-------|------------|-----------|----------|--------|\n';
suites.forEach((suite) => {
const avgCoverage = (suite.lines + suite.statements + suite.functions + suite.branches) / 4;
const status = avgCoverage >= 80 ? '✅ Pass' : avgCoverage >= 60 ? '⚠️ Warning' : '❌ Fail';
summary += `| ${suite.name} | ${suite.lines.toFixed(1)}% | ${suite.statements.toFixed(1)}% | ${suite.functions.toFixed(1)}% | ${suite.branches.toFixed(1)}% | ${status} |\n`;
if (avgCoverage >= 80) {
totalPassed++;
} else {
totalFailed++;
}
});
// Overall stats
summary += '\n## Overall Statistics\n\n';
summary += `- **Total Test Suites:** ${suites.length}\n`;
summary += `- **Passed:** ${totalPassed}\n`;
summary += `- **Failed:** ${totalFailed}\n`;
const successRate = ((totalPassed / suites.length) * 100).toFixed(1);
summary += `- **Success Rate:** ${successRate}%\n`;
// Recommendations
if (totalFailed > 0) {
summary += '\n## ⚠️ Recommendations\n\n';
summary += 'The following test suites need attention:\n\n';
suites
.filter((s) => (s.lines + s.statements + s.functions + s.branches) / 4 < 80)
.forEach((suite) => {
summary += `- **${suite.name}**: Improve coverage (currently ${((suite.lines + suite.statements + suite.functions + suite.branches) / 4).toFixed(1)}%)\n`;
});
}
return summary;
}
function main() {
const resultsDir = process.argv[2];
if (!resultsDir) {
console.error('Usage: node generate-summary.js <test-results-dir>');
process.exit(1);
}
const summary = generateSummary(resultsDir);
console.log(summary);
}
main();