- Add HVAC_Test_User_Factory class with: * User creation with specific roles * Multiple role support * Persona management system * Account cleanup integration - Create comprehensive test suite in HVAC_Test_User_Factory_Test.php - Update testing improvement plan documentation - Add implementation decisions to project memory bank - Restructure .gitignore with: * Whitelist approach for better file management * Explicit backup exclusions * Specific bin directory inclusions Part of the Account Management component from the testing framework improvement plan.
		
			
				
	
	
		
			135 lines
		
	
	
		
			No EOL
		
	
	
		
			3.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			No EOL
		
	
	
		
			3.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { FullConfig } from '@playwright/test';
 | |
| import { Client } from 'ssh2';
 | |
| import { STAGING_CONFIG } from '../../playwright.config';
 | |
| import * as fs from 'fs';
 | |
| import * as path from 'path';
 | |
| 
 | |
| interface LogFileStats {
 | |
|     size: number;
 | |
|     lastModified: Date;
 | |
| }
 | |
| 
 | |
| interface LogSummary {
 | |
|     testRun: {
 | |
|         startTime: string;
 | |
|         endTime: string;
 | |
|         logsLocation: string;
 | |
|     };
 | |
|     logFiles: {
 | |
|         [key: string]: LogFileStats;
 | |
|     };
 | |
| }
 | |
| 
 | |
| async function globalTeardown(config: FullConfig) {
 | |
|     const testLogsDir = process.env.TEST_LOGS_DIR;
 | |
|     const testStartTime = process.env.TEST_START_TIME;
 | |
|     
 | |
|     if (!testLogsDir || !testStartTime) {
 | |
|         console.warn('Warning: Test environment variables not found during teardown');
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     // Create final logs directory with timestamp
 | |
|     const finalLogsDir = path.join(
 | |
|         testLogsDir,
 | |
|         `run-${new Date().toISOString().replace(/[:.]/g, '-')}`
 | |
|     );
 | |
|     fs.mkdirSync(finalLogsDir, { recursive: true });
 | |
| 
 | |
|     // Fetch final state of logs
 | |
|     const conn = new Client();
 | |
|     
 | |
|     try {
 | |
|         await new Promise<void>((resolve, reject) => {
 | |
|             conn.on('ready', () => {
 | |
|                 conn.sftp((err, sftp) => {
 | |
|                     if (err) {
 | |
|                         reject(err);
 | |
|                         return;
 | |
|                     }
 | |
| 
 | |
|                     const logFiles = [
 | |
|                         'debug.log',
 | |
|                         'error.log',
 | |
|                         'access.log'
 | |
|                     ];
 | |
| 
 | |
|                     let completedFiles = 0;
 | |
| 
 | |
|                     // Fetch all log files
 | |
|                     logFiles.forEach(logFile => {
 | |
|                         const remotePath = `${STAGING_CONFIG.path}/wp-content/${logFile}`;
 | |
|                         const localPath = path.join(finalLogsDir, logFile);
 | |
| 
 | |
|                         sftp.fastGet(remotePath, localPath, (err) => {
 | |
|                             if (err) {
 | |
|                                 console.warn(`Warning: Could not fetch ${logFile}:`, err);
 | |
|                             }
 | |
|                             
 | |
|                             completedFiles++;
 | |
|                             if (completedFiles === logFiles.length) {
 | |
|                                 resolve();
 | |
|                             }
 | |
|                         });
 | |
|                     });
 | |
|                 });
 | |
|             }).connect({
 | |
|                 host: STAGING_CONFIG.ip,
 | |
|                 username: STAGING_CONFIG.sshUser
 | |
|             });
 | |
|         });
 | |
| 
 | |
|         // Generate log summary
 | |
|         const summary: LogSummary = {
 | |
|             testRun: {
 | |
|                 startTime: testStartTime,
 | |
|                 endTime: new Date().toISOString(),
 | |
|                 logsLocation: finalLogsDir
 | |
|             },
 | |
|             logFiles: {}
 | |
|         };
 | |
| 
 | |
|         // Add log file statistics to summary
 | |
|         const logFiles = fs.readdirSync(finalLogsDir);
 | |
|         for (const file of logFiles) {
 | |
|             const stats = fs.statSync(path.join(finalLogsDir, file)) as fs.Stats;
 | |
|             summary.logFiles[file] = {
 | |
|                 size: stats.size,
 | |
|                 lastModified: stats.mtime
 | |
|             } as LogFileStats;
 | |
|         }
 | |
| 
 | |
|         // Write summary to JSON file
 | |
|         fs.writeFileSync(
 | |
|             path.join(finalLogsDir, 'log-summary.json'),
 | |
|             JSON.stringify(summary, null, 2)
 | |
|         );
 | |
| 
 | |
|         // Generate Markdown report
 | |
|         const markdownReport = `# Test Run Log Summary
 | |
| ## Run Information
 | |
| - Start Time: ${summary.testRun.startTime}
 | |
| - End Time: ${summary.testRun.endTime}
 | |
| - Logs Location: ${summary.testRun.logsLocation}
 | |
| 
 | |
| ## Log Files
 | |
| ${Object.entries(summary.logFiles)
 | |
|     .map(([file, stats]) => `### ${file}
 | |
| - Size: ${stats.size} bytes
 | |
| - Last Modified: ${stats.lastModified}`)
 | |
|     .join('\n\n')}
 | |
| `;
 | |
| 
 | |
|         fs.writeFileSync(
 | |
|             path.join(finalLogsDir, 'log-summary.md'),
 | |
|             markdownReport
 | |
|         );
 | |
| 
 | |
|     } catch (error) {
 | |
|         console.error('Error during global teardown:', error);
 | |
|     } finally {
 | |
|         conn.end();
 | |
|     }
 | |
| }
 | |
| 
 | |
| export default globalTeardown; |