/** * Global Test Teardown for HVAC Testing Framework * * Runs once after all tests to: * - Clean up test data and artifacts * - Generate final reports * - Archive screenshots and videos * - Display test summary * * @package HVAC_Community_Events * @version 2.0.0 * @created 2025-08-27 */ const ConfigManager = require('../core/ConfigManager'); const AuthManager = require('../core/AuthManager'); const WordPressUtils = require('../utils/WordPressUtils'); const ScreenshotManager = require('../utils/ScreenshotManager'); const fs = require('fs').promises; const path = require('path'); async function globalTeardown(config) { console.log('\n๐Ÿ HVAC Testing Framework - Global Teardown'); console.log('='.repeat(50)); const startTime = Date.now(); const configManager = ConfigManager; const authManager = AuthManager; const wpUtils = new WordPressUtils(); const screenshotManager = new ScreenshotManager(); try { // 1. Clean Up Test Data console.log('\n๐Ÿงน 1. Cleaning Up Test Data'); const environment = configManager.getEnvironment(); if (configManager.get('testData.cleanupAfterTests') && environment !== 'staging') { try { // Clean up WordPress test data const testIds = await getTestIds(); for (const testId of testIds) { await wpUtils.cleanupTestData(testId); } console.log(` โœ… Cleaned up ${testIds.length} test datasets`); } catch (error) { console.warn(' โš ๏ธ Test data cleanup failed:', error.message); } } else { console.log(' โ„น๏ธ Skipping test data cleanup (staging environment)'); } // 2. Authentication State Management console.log('\n๐Ÿ” 2. Authentication State Management'); // Get auth status before cleanup const authStatus = await authManager.getAuthStatus(); console.log(` ๐Ÿ“Š Storage states: ${Object.keys(authStatus).length} roles`); // Clear validation cache authManager.clearValidationCache(); console.log(' โœ… Validation cache cleared'); // Clean up old storage states if configured if (environment === 'local') { // Only clean on local environment const oldStatesCount = await cleanOldStorageStates(); if (oldStatesCount > 0) { console.log(` ๐Ÿ—‘๏ธ Removed ${oldStatesCount} old storage states`); } } // 3. Generate Screenshot Reports console.log('\n๐Ÿ“ธ 3. Processing Screenshots and Media'); try { // Generate screenshot report const screenshotReport = await screenshotManager.generateReport(); if (screenshotReport) { console.log(` ๐Ÿ“Š Screenshot report: ${screenshotReport.totalScreenshots} files`); } // Create screenshot gallery const galleryPath = await screenshotManager.createGallery('HVAC Test Results'); if (galleryPath) { console.log(` ๐Ÿ–ผ๏ธ Screenshot gallery: ${galleryPath}`); } // Clean up old screenshots if configured const daysToKeep = 7; await screenshotManager.cleanup(daysToKeep); } catch (error) { console.warn(' โš ๏ธ Screenshot processing failed:', error.message); } // 4. Generate Final Test Report console.log('\n๐Ÿ“Š 4. Generating Final Reports'); try { const finalReport = await generateFinalReport(startTime); const reportPath = path.resolve('./test-results/final-report.json'); await fs.writeFile(reportPath, JSON.stringify(finalReport, null, 2)); console.log(` โœ… Final report: ${reportPath}`); // Generate HTML summary const htmlReport = await generateHTMLReport(finalReport); const htmlPath = path.resolve('./test-results/summary.html'); await fs.writeFile(htmlPath, htmlReport); console.log(` ๐Ÿ“„ HTML report: ${htmlPath}`); } catch (error) { console.warn(' โš ๏ธ Report generation failed:', error.message); } // 5. Archive Test Artifacts console.log('\n๐Ÿ“ฆ 5. Archiving Test Artifacts'); try { await archiveTestArtifacts(); console.log(' โœ… Test artifacts archived'); } catch (error) { console.warn(' โš ๏ธ Archiving failed:', error.message); } // 6. WordPress Cleanup (if safe) console.log('\nโš™๏ธ 6. WordPress Environment Cleanup'); if (environment === 'local' || environment === 'docker') { try { // Clear cache one final time await wpUtils.clearCache(); console.log(' โœ… Final cache clear'); } catch (error) { console.warn(' โš ๏ธ WordPress cleanup failed:', error.message); } } else { console.log(' โ„น๏ธ Skipping WordPress cleanup (staging environment)'); } // 7. Display Final Summary console.log('\n๐Ÿ“‹ 7. Test Session Summary'); await displayTestSummary(); // 8. Final Teardown Report const duration = ((Date.now() - startTime) / 1000).toFixed(2); console.log('\n' + '='.repeat(50)); console.log('โœ… Global Teardown Complete'); console.log(`โฑ๏ธ Teardown Duration: ${duration}s`); console.log(`๐ŸŒ Environment: ${environment}`); console.log('='.repeat(50) + '\n'); } catch (error) { console.error('\nโŒ Global Teardown Failed'); console.error('Error:', error.message); console.error('='.repeat(50) + '\n'); // Don't throw - teardown failures shouldn't fail the test suite } } /** * Get list of test IDs for cleanup */ async function getTestIds() { try { const testResults = await fs.readFile('./test-results/test-metrics.jsonl', 'utf8'); const lines = testResults.trim().split('\n'); const testIds = lines .map(line => JSON.parse(line)) .map(test => test.testId) .filter(id => id.startsWith('hvac-test-')); return [...new Set(testIds)]; // Remove duplicates } catch (error) { return []; } } /** * Clean old storage states */ async function cleanOldStorageStates() { try { const storageStatesDir = path.resolve(__dirname, '../fixtures/storage-states'); const files = await fs.readdir(storageStatesDir); const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - 7); let deletedCount = 0; for (const file of files) { if (file.endsWith('.json')) { const filePath = path.join(storageStatesDir, file); const stats = await fs.stat(filePath); if (stats.mtime < cutoffDate) { await fs.unlink(filePath); deletedCount++; } } } return deletedCount; } catch (error) { return 0; } } /** * Generate comprehensive final report */ async function generateFinalReport(startTime) { const report = { timestamp: new Date().toISOString(), environment: ConfigManager.getEnvironment(), teardownDuration: Date.now() - startTime, framework: { version: '2.0.0', features: ConfigManager.get('features') } }; // Add test metrics if available try { const metricsFile = './test-results/test-metrics.jsonl'; const metricsData = await fs.readFile(metricsFile, 'utf8'); const metrics = metricsData.trim().split('\n').map(line => JSON.parse(line)); report.testMetrics = { totalTests: metrics.length, passed: metrics.filter(t => t.passed).length, failed: metrics.filter(t => !t.passed).length, categories: groupBy(metrics, 'category'), avgDuration: metrics.reduce((sum, t) => sum + t.duration, 0) / metrics.length }; } catch (error) { report.testMetrics = { error: 'Metrics not available' }; } return report; } /** * Generate HTML report */ async function generateHTMLReport(report) { const testMetrics = report.testMetrics || {}; const passRate = testMetrics.totalTests ? ((testMetrics.passed / testMetrics.totalTests) * 100).toFixed(1) : 'N/A'; return ` HVAC Test Results Summary

๐Ÿงช HVAC Testing Framework Results

Environment: ${report.environment}

Generated: ${new Date(report.timestamp).toLocaleString()}

Total Tests

${testMetrics.totalTests || 0}

Passed

${testMetrics.passed || 0}

Failed

${testMetrics.failed || 0}

Pass Rate

${passRate}%

๐Ÿ“Š Detailed Report

${JSON.stringify(report, null, 2)}
`; } /** * Archive test artifacts */ async function archiveTestArtifacts() { const archiveDir = path.resolve('./test-results/archives'); const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const archiveName = `test-session-${timestamp}`; const sessionArchive = path.join(archiveDir, archiveName); await fs.mkdir(sessionArchive, { recursive: true }); // Copy important files to archive const filesToArchive = [ './test-results/final-report.json', './test-results/summary.html', './test-results/setup-report.json' ]; for (const file of filesToArchive) { try { const filename = path.basename(file); const sourcePath = path.resolve(file); const destPath = path.join(sessionArchive, filename); await fs.copyFile(sourcePath, destPath); } catch (error) { // File might not exist, continue } } } /** * Display test session summary */ async function displayTestSummary() { try { const metricsFile = './test-results/test-metrics.jsonl'; const metricsData = await fs.readFile(metricsFile, 'utf8'); const metrics = metricsData.trim().split('\n').map(line => JSON.parse(line)); const totalTests = metrics.length; const passed = metrics.filter(t => t.passed).length; const failed = metrics.filter(t => !t.passed).length; const passRate = ((passed / totalTests) * 100).toFixed(1); console.log(` ๐Ÿ“Š Total Tests: ${totalTests}`); console.log(` โœ… Passed: ${passed}`); console.log(` โŒ Failed: ${failed}`); console.log(` ๐Ÿ“ˆ Pass Rate: ${passRate}%`); if (failed > 0) { console.log('\n โŒ Failed Tests:'); metrics .filter(t => !t.passed) .slice(0, 5) // Show first 5 failures .forEach(t => console.log(` - ${t.title}`)); if (failed > 5) { console.log(` ... and ${failed - 5} more`); } } } catch (error) { console.log(' โ„น๏ธ No test metrics available'); } } /** * Helper function to group by property */ function groupBy(array, property) { return array.reduce((groups, item) => { const key = item[property] || 'unknown'; groups[key] = (groups[key] || 0) + 1; return groups; }, {}); } module.exports = globalTeardown;