/* eslint-disable no-console */ interface GlobalTeardownConfig { projects?: Array<{ name: string; use?: Record; }>; webServer?: Array<{ command: string; port: number; timeout: number; reuseExistingServer: boolean; }>; use?: { baseURL?: string; trace?: string; screenshot?: string; }; [key: string]: unknown; } /** * Global teardown for authentication debug tests * Cleans up test environment and generates summary report */ async function globalTeardown(_config: GlobalTeardownConfig) { console.log('๐Ÿงน Starting authentication debug test teardown...'); const startTime = Date.now(); try { // Clean up test data await cleanupTestData(); // Generate test summary await generateTestSummary(); // Clean up test artifacts await cleanupTestArtifacts(); // Log final status await logFinalStatus(); const duration = Date.now() - startTime; console.log(`โœ… Auth debug teardown completed in ${duration}ms`); } catch (error) { console.error('โŒ Auth debug teardown failed:', error); // Don't throw error to avoid masking test failures } } /** * Clean up test data created during tests */ async function cleanupTestData(): Promise { console.log('๐Ÿ—‘๏ธ Cleaning up test data...'); try { // Clean up test users created during the test run await cleanupTestUsers(); // Clean up any temporary files await cleanupTempFiles(); console.log('โœ… Test data cleanup completed'); } catch (error) { console.warn('โš ๏ธ Test data cleanup had issues:', error); } } /** * Remove test users created during testing */ async function cleanupTestUsers(): Promise { console.log('๐Ÿ‘ฅ Cleaning up test users...'); try { // Get list of databases const response = await fetch('http://localhost:5984/_all_dbs', { headers: { Authorization: 'Basic ' + Buffer.from('admin:password').toString('base64'), }, }); if (!response.ok) { console.warn('โš ๏ธ Could not access CouchDB for user cleanup'); return; } // Look for users database const databases = await response.json(); if (databases.includes('users')) { await cleanupUsersFromDatabase(); } console.log('โœ… Test users cleanup completed'); } catch (error) { console.warn('โš ๏ธ Could not cleanup test users:', error); } } /** * Clean up test users from the users database */ async function cleanupUsersFromDatabase(): Promise { try { // Get all users const response = await fetch( 'http://localhost:5984/users/_all_docs?include_docs=true', { headers: { Authorization: 'Basic ' + Buffer.from('admin:password').toString('base64'), }, } ); if (!response.ok) { return; } const data = await response.json(); const testUserPattern = /debug-test.*@localhost|test.*@localhost|strong.*@localhost/; // Find and delete test users for (const row of data.rows) { if (row.doc && row.doc.email && testUserPattern.test(row.doc.email)) { await deleteTestUser(row.doc._id, row.doc._rev); } } } catch (error) { console.warn('โš ๏ธ Error cleaning users database:', error); } } /** * Delete a specific test user */ async function deleteTestUser(userId: string, rev: string): Promise { try { const response = await fetch( `http://localhost:5984/users/${userId}?rev=${rev}`, { method: 'DELETE', headers: { Authorization: 'Basic ' + Buffer.from('admin:password').toString('base64'), }, } ); if (response.ok) { console.log(`๐Ÿ—‘๏ธ Deleted test user: ${userId}`); } } catch (error) { console.warn(`โš ๏ธ Could not delete test user ${userId}:`, error); } } /** * Clean up temporary files created during tests */ async function cleanupTempFiles(): Promise { console.log('๐Ÿ“‚ Cleaning up temporary files...'); try { const fs = await import('fs').then(m => m.promises); const path = await import('path'); // Clean up any temporary screenshots or videos from failed tests const tempDirs = [ 'test-results-auth', 'playwright-report-auth', 'screenshots-temp', 'videos-temp', ]; for (const dir of tempDirs) { try { const fullPath = path.join(process.cwd(), dir); await fs.access(fullPath); // Directory exists, but don't delete it as it may contain useful debug info console.log(`๐Ÿ“ Preserved test artifacts in: ${dir}`); } catch { // Directory doesn't exist, which is fine } } console.log('โœ… Temporary files cleanup completed'); } catch (error) { console.warn('โš ๏ธ Temporary files cleanup had issues:', error); } } /** * Generate test summary report */ async function generateTestSummary(): Promise { console.log('๐Ÿ“Š Generating test summary...'); try { const fs = await import('fs').then(m => m.promises); const path = await import('path'); // Check if test results exist const reportPath = path.join(process.cwd(), 'playwright-report-auth.json'); try { await fs.access(reportPath); const reportData = await fs.readFile(reportPath, 'utf-8'); const report = JSON.parse(reportData); // Generate summary const summary = { timestamp: new Date().toISOString(), testType: 'Authentication Debug', totalTests: report.suites?.reduce( (total: number, suite: { specs?: unknown[] }) => total + (suite.specs?.length || 0), 0 ) || 0, passedTests: 0, failedTests: 0, skippedTests: 0, duration: report.stats?.duration || 0, environment: { nodeVersion: process.version, platform: process.platform, ci: !!process.env.CI, }, }; // Count test results if (report.suites) { for (const suite of report.suites) { if (suite.specs) { for (const spec of suite.specs) { if (spec.tests) { for (const test of spec.tests) { switch (test.status) { case 'passed': summary.passedTests++; break; case 'failed': summary.failedTests++; break; case 'skipped': summary.skippedTests++; break; } } } } } } } // Save summary const summaryPath = path.join(process.cwd(), 'auth-debug-summary.json'); await fs.writeFile(summaryPath, JSON.stringify(summary, null, 2)); console.log('๐Ÿ“ˆ Test Summary:'); console.log(` Total Tests: ${summary.totalTests}`); console.log(` Passed: ${summary.passedTests}`); console.log(` Failed: ${summary.failedTests}`); console.log(` Skipped: ${summary.skippedTests}`); console.log(` Duration: ${summary.duration}ms`); console.log(` Summary saved to: auth-debug-summary.json`); } catch (_error) { console.warn('โš ๏ธ Could not find test report for summary generation'); } console.log('โœ… Test summary generation completed'); } catch (error) { console.warn('โš ๏ธ Test summary generation had issues:', error); } } /** * Clean up test artifacts but preserve important debug information */ async function cleanupTestArtifacts(): Promise { console.log('๐Ÿงน Managing test artifacts...'); try { const fs = await import('fs').then(m => m.promises); const path = await import('path'); // Archive old test results if they exist const testResultsDir = 'test-results-auth'; const archiveDir = 'test-results-archive'; try { await fs.access(testResultsDir); // Create archive directory if it doesn't exist try { await fs.mkdir(archiveDir, { recursive: true }); } catch { // Directory might already exist } // Move current results to archive with timestamp const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const archivePath = path.join(archiveDir, `auth-debug-${timestamp}`); await fs.rename(testResultsDir, archivePath); console.log(`๐Ÿ“ฆ Archived test results to: ${archivePath}`); } catch { // No test results to archive } console.log('โœ… Test artifacts management completed'); } catch (error) { console.warn('โš ๏ธ Test artifacts cleanup had issues:', error); } } /** * Log final status and cleanup recommendations */ async function logFinalStatus(): Promise { console.log('๐Ÿ“‹ Auth Debug Test Session Complete'); console.log(''); console.log('๐Ÿ“ Available Reports:'); console.log(' โ€ข HTML Report: playwright-report-auth/index.html'); console.log(' โ€ข JSON Report: playwright-report-auth.json'); console.log(' โ€ข Summary: auth-debug-summary.json'); console.log(''); console.log('๐Ÿ”ง Debug Commands:'); console.log( ' โ€ข View HTML report: npx playwright show-report playwright-report-auth' ); console.log( ' โ€ข Run specific test: bunx playwright test auth-debug.spec.ts --debug' ); console.log(' โ€ข Interactive mode: make test-e2e-ui'); console.log(''); console.log('๐Ÿงน Cleanup Status:'); console.log(' โ€ข Test users: Cleaned up'); console.log(' โ€ข Temporary files: Preserved for debugging'); console.log(' โ€ข Test artifacts: Archived'); console.log(''); // Check for failed tests and provide guidance try { const fs = await import('fs').then(m => m.promises); const path = await import('path'); const summaryPath = path.join(process.cwd(), 'auth-debug-summary.json'); const summaryData = await fs.readFile(summaryPath, 'utf-8'); const summary = JSON.parse(summaryData); if (summary.failedTests > 0) { console.log('โš ๏ธ Test Failures Detected:'); console.log(` ${summary.failedTests} test(s) failed`); console.log(' Check the HTML report for detailed failure information'); console.log(' Use --debug flag to interactively debug failing tests'); console.log(''); } else if (summary.passedTests > 0) { console.log('โœ… All Authentication Tests Passed!'); console.log(' Authentication flows are working correctly'); console.log(''); } } catch { // Summary file might not exist } console.log('๐ŸŽฏ Next Steps:'); console.log(' โ€ข Review test reports for any issues'); console.log(' โ€ข Update authentication tests as features evolve'); console.log(' โ€ข Run tests regularly in CI/CD pipeline'); console.log(''); } /** * Emergency cleanup in case of critical errors */ async function emergencyCleanup(): Promise { console.log('๐Ÿšจ Running emergency cleanup...'); try { // Force cleanup of any hanging processes or connections // This is a safety net for test environments console.log('โœ… Emergency cleanup completed'); } catch (error) { console.error('โŒ Emergency cleanup failed:', error); } } // Execute teardown export default async function (config: GlobalTeardownConfig) { try { await globalTeardown(config); } catch (_error) { console.error('โŒ Teardown failed, running emergency cleanup...'); await emergencyCleanup(); } }