import { FullConfig } from '@playwright/test'; import { Client } from 'ssh2'; import { STAGING_CONFIG } from '../../playwright.config'; async function globalSetup(config: FullConfig) { // Validate required environment variables if (!process.env.UPSKILL_STAGING_PASS && !process.env.SSH_PRIVATE_KEY) { throw new Error('Either UPSKILL_STAGING_PASS or SSH_PRIVATE_KEY must be set for authentication'); } if (!STAGING_CONFIG.ip || !STAGING_CONFIG.sshUser) { throw new Error('Missing required staging configuration: ip and sshUser must be set'); } console.log('Starting global setup with configuration:', { host: STAGING_CONFIG.ip, username: STAGING_CONFIG.sshUser, authMethod: process.env.SSH_PRIVATE_KEY ? 'key-based' : 'password' }); // Ensure test results directory exists const fs = require('fs'); const path = require('path'); const testResultsDir = path.join(__dirname, '../../test-results'); const logsDir = path.join(testResultsDir, 'logs'); if (!fs.existsSync(testResultsDir)) { fs.mkdirSync(testResultsDir, { recursive: true }); } if (!fs.existsSync(logsDir)) { fs.mkdirSync(logsDir, { recursive: true }); } // Initialize SSH connection and fetch initial logs const maxRetries = 3; const retryDelay = 5000; // 5 seconds between retries for (let attempt = 1; attempt <= maxRetries; attempt++) { const conn = new Client(); try { console.log(`SSH Connection Attempt ${attempt}/${maxRetries}`); await new Promise((resolve, reject) => { let connectionTimeout: NodeJS.Timeout; conn.on('ready', () => { clearTimeout(connectionTimeout); console.log('SSH Connection Ready'); conn.exec("echo 'SSH Connection Test Successful'", (err, stream) => { if (err) { console.error('SSH command execution failed:', err); reject(err); return; } stream.on('close', (code: number) => { console.log('SSH command completed with code:', code); conn.sftp((sftpErr, sftp) => { if (sftpErr) { console.error('SFTP initialization failed:', sftpErr); reject(sftpErr); return; } const remotePath = `${STAGING_CONFIG.path}/wp-content/debug.log`; const localPath = path.join(logsDir, 'wordpress-initial.log'); sftp.fastGet(remotePath, localPath, (getErr) => { if (getErr) { console.warn('Warning: Could not fetch initial log state:', getErr); } else { console.log('Initial log state fetched successfully.'); } resolve(); }); }); }).on('data', (data: Buffer) => { console.log('SSH command output:', data.toString().trim()); }).stderr.on('data', (data: Buffer) => { console.error('SSH command error:', data.toString()); }); }); }); conn.on('error', (err) => { clearTimeout(connectionTimeout); console.error(`SSH Connection Error (Attempt ${attempt}):`, err); reject(err); }); connectionTimeout = setTimeout(() => { conn.end(); reject(new Error(`Connection timeout (Attempt ${attempt})`)); }, 20000); conn.connect({ host: STAGING_CONFIG.ip, username: STAGING_CONFIG.sshUser, password: process.env.UPSKILL_STAGING_PASS, readyTimeout: 20000, debug: (debug) => console.log('SSH Debug:', debug) }); }); // If we get here, connection was successful console.log('SSH operations completed successfully'); break; } catch (error) { console.error(`Attempt ${attempt} failed:`, error); conn.end(); if (attempt === maxRetries) { throw new Error(`Failed to establish SSH connection after ${maxRetries} attempts`); } // Wait before next retry await new Promise(resolve => setTimeout(resolve, retryDelay)); } } // Set up custom test environment variables process.env.TEST_LOGS_DIR = logsDir; process.env.TEST_START_TIME = new Date().toISOString(); } export default globalSetup;