mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 20:41:09 +02:00
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
130 lines
3.4 KiB
JavaScript
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();
|