258 lines
7.3 KiB
JavaScript
258 lines
7.3 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Script de tests de production pour Veza V5 Ultra
|
|
* Objectif: 100% tests passés, 0 bugs critiques
|
|
*/
|
|
|
|
const { execSync } = require('child_process');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
console.log('🧪 VEZA V5 ULTRA - Production Tests');
|
|
console.log('===================================\n');
|
|
|
|
// Configuration des tests
|
|
const testConfig = {
|
|
unit: {
|
|
command: 'npm run test:unit',
|
|
coverage: 80,
|
|
timeout: 30000,
|
|
},
|
|
e2e: {
|
|
command: 'npm run test:e2e',
|
|
timeout: 60000,
|
|
},
|
|
lighthouse: {
|
|
command: 'npm run lighthouse:ci',
|
|
score: 100,
|
|
},
|
|
performance: {
|
|
command: 'npm run test:perf',
|
|
fcp: 0.8, // First Contentful Paint < 0.8s
|
|
tti: 1.5, // Time to Interactive < 1.5s
|
|
cls: 0.1, // Cumulative Layout Shift < 0.1
|
|
},
|
|
accessibility: {
|
|
command: 'npm run test:a11y',
|
|
score: 100,
|
|
},
|
|
};
|
|
|
|
// Fonction pour exécuter un test
|
|
function runTest(name, config) {
|
|
console.log(`\n🔍 Running ${name}...`);
|
|
|
|
try {
|
|
const startTime = Date.now();
|
|
const result = execSync(config.command, {
|
|
encoding: 'utf8',
|
|
timeout: config.timeout || 30000,
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const duration = (Date.now() - startTime) / 1000;
|
|
console.log(`✅ ${name} passed in ${duration.toFixed(2)}s`);
|
|
|
|
// Analyser les résultats spécifiques
|
|
if (name === 'Unit Tests' && config.coverage) {
|
|
const coverageMatch = result.match(/(\d+)%/);
|
|
if (coverageMatch) {
|
|
const coverage = parseInt(coverageMatch[1]);
|
|
if (coverage >= config.coverage) {
|
|
console.log(`✅ Coverage: ${coverage}% (target: ${config.coverage}%)`);
|
|
} else {
|
|
console.log(`⚠️ Coverage: ${coverage}% (target: ${config.coverage}%)`);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (name === 'Lighthouse' && config.score) {
|
|
const scoreMatch = result.match(/Performance: (\d+)/);
|
|
if (scoreMatch) {
|
|
const score = parseInt(scoreMatch[1]);
|
|
if (score >= config.score) {
|
|
console.log(`✅ Lighthouse Score: ${score}/100`);
|
|
} else {
|
|
console.log(`⚠️ Lighthouse Score: ${score}/100 (target: ${config.score})`);
|
|
}
|
|
}
|
|
}
|
|
|
|
return { success: true, duration, result };
|
|
} catch (error) {
|
|
console.log(`❌ ${name} failed:`, error.message);
|
|
return { success: false, error: error.message };
|
|
}
|
|
}
|
|
|
|
// Fonction pour vérifier les métriques de performance
|
|
function checkPerformanceMetrics() {
|
|
console.log('\n📊 Checking Performance Metrics...');
|
|
|
|
const metrics = {
|
|
bundleSize: checkBundleSize(),
|
|
buildTime: checkBuildTime(),
|
|
memoryUsage: checkMemoryUsage(),
|
|
};
|
|
|
|
return metrics;
|
|
}
|
|
|
|
function checkBundleSize() {
|
|
const distPath = path.join(__dirname, '..', 'dist');
|
|
if (!fs.existsSync(distPath)) {
|
|
return { error: 'No dist folder found' };
|
|
}
|
|
|
|
let totalSize = 0;
|
|
let jsFiles = [];
|
|
|
|
function scanDir(dir) {
|
|
const files = fs.readdirSync(dir);
|
|
files.forEach(file => {
|
|
const filePath = path.join(dir, file);
|
|
if (fs.statSync(filePath).isDirectory()) {
|
|
scanDir(filePath);
|
|
} else if (file.endsWith('.js')) {
|
|
const size = fs.statSync(filePath).size;
|
|
totalSize += size;
|
|
jsFiles.push({ name: file, size });
|
|
}
|
|
});
|
|
}
|
|
|
|
scanDir(distPath);
|
|
|
|
const initialBundle = jsFiles.find(f => f.name.includes('index'))?.size || 0;
|
|
const maxChunk = Math.max(...jsFiles.map(f => f.size));
|
|
|
|
return {
|
|
total: totalSize,
|
|
initial: initialBundle,
|
|
maxChunk,
|
|
files: jsFiles.length,
|
|
target: 150 * 1024, // 150KB
|
|
};
|
|
}
|
|
|
|
function checkBuildTime() {
|
|
const startTime = Date.now();
|
|
try {
|
|
execSync('npm run build', { stdio: 'pipe' });
|
|
return Date.now() - startTime;
|
|
} catch (error) {
|
|
return { error: error.message };
|
|
}
|
|
}
|
|
|
|
function checkMemoryUsage() {
|
|
const usage = process.memoryUsage();
|
|
return {
|
|
rss: Math.round(usage.rss / 1024 / 1024), // MB
|
|
heapUsed: Math.round(usage.heapUsed / 1024 / 1024), // MB
|
|
heapTotal: Math.round(usage.heapTotal / 1024 / 1024), // MB
|
|
};
|
|
}
|
|
|
|
// Fonction pour générer le rapport de tests
|
|
function generateTestReport(results) {
|
|
const report = {
|
|
timestamp: new Date().toISOString(),
|
|
summary: {
|
|
total: Object.keys(testConfig).length,
|
|
passed: Object.values(results).filter(r => r.success).length,
|
|
failed: Object.values(results).filter(r => !r.success).length,
|
|
},
|
|
results,
|
|
performance: checkPerformanceMetrics(),
|
|
};
|
|
|
|
const reportPath = path.join(__dirname, '..', 'test-report-production.json');
|
|
fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
|
|
console.log(`\n📄 Test report saved to: ${reportPath}`);
|
|
return report;
|
|
}
|
|
|
|
// Exécuter tous les tests
|
|
async function runAllTests() {
|
|
console.log('🚀 Starting Production Test Suite...\n');
|
|
|
|
const results = {};
|
|
|
|
// Tests unitaires
|
|
results.unit = runTest('Unit Tests', testConfig.unit);
|
|
|
|
// Tests E2E
|
|
results.e2e = runTest('E2E Tests', testConfig.e2e);
|
|
|
|
// Tests Lighthouse
|
|
results.lighthouse = runTest('Lighthouse', testConfig.lighthouse);
|
|
|
|
// Tests de performance
|
|
results.performance = runTest('Performance Tests', testConfig.performance);
|
|
|
|
// Tests d'accessibilité
|
|
results.accessibility = runTest('Accessibility Tests', testConfig.accessibility);
|
|
|
|
// Générer le rapport
|
|
const report = generateTestReport(results);
|
|
|
|
// Afficher le résumé
|
|
console.log('\n📋 TEST SUMMARY');
|
|
console.log('================');
|
|
console.log(`Total Tests: ${report.summary.total}`);
|
|
console.log(`Passed: ${report.summary.passed} ✅`);
|
|
console.log(`Failed: ${report.summary.failed} ❌`);
|
|
console.log(`Success Rate: ${((report.summary.passed / report.summary.total) * 100).toFixed(1)}%`);
|
|
|
|
// Métriques de performance
|
|
console.log('\n📊 PERFORMANCE METRICS');
|
|
console.log('======================');
|
|
if (report.performance.bundleSize) {
|
|
const bundle = report.performance.bundleSize;
|
|
console.log(`Bundle Size: ${(bundle.initial / 1024).toFixed(2)} KB (target: < 150 KB)`);
|
|
console.log(`Max Chunk: ${(bundle.maxChunk / 1024).toFixed(2)} KB (target: < 50 KB)`);
|
|
console.log(`Total Files: ${bundle.files}`);
|
|
}
|
|
|
|
if (report.performance.buildTime) {
|
|
console.log(`Build Time: ${(report.performance.buildTime / 1000).toFixed(2)}s`);
|
|
}
|
|
|
|
if (report.performance.memoryUsage) {
|
|
const mem = report.performance.memoryUsage;
|
|
console.log(`Memory Usage: ${mem.heapUsed}MB / ${mem.heapTotal}MB`);
|
|
}
|
|
|
|
// Recommandations
|
|
console.log('\n💡 RECOMMENDATIONS');
|
|
console.log('==================');
|
|
|
|
if (report.summary.failed > 0) {
|
|
console.log('❌ Fix failing tests before production deployment');
|
|
}
|
|
|
|
if (report.performance.bundleSize?.initial > report.performance.bundleSize?.target) {
|
|
console.log('⚠️ Bundle size too large - consider code splitting');
|
|
}
|
|
|
|
if (report.performance.buildTime > 30000) {
|
|
console.log('⚠️ Build time too slow - consider optimization');
|
|
}
|
|
|
|
if (report.summary.passed === report.summary.total) {
|
|
console.log('🎉 All tests passed! Ready for production deployment');
|
|
}
|
|
|
|
return report.summary.passed === report.summary.total;
|
|
}
|
|
|
|
// Exécuter les tests
|
|
runAllTests().then(success => {
|
|
process.exit(success ? 0 : 1);
|
|
}).catch(error => {
|
|
console.error('❌ Test suite failed:', error);
|
|
process.exit(1);
|
|
});
|