#!/usr/bin/env node /** * Master Trainer Comprehensive E2E Test Setup Validator * * Validates that all components are properly configured for comprehensive testing * * @package HVAC_Community_Events * @version 2.0.0 * @created 2025-08-27 */ const fs = require('fs').promises; const path = require('path'); const { execSync } = require('child_process'); class MasterTrainerSetupValidator { constructor() { this.validationResults = { passed: 0, failed: 0, warnings: 0, details: [] }; this.requiredFiles = [ 'e2e/master-trainer-comprehensive.test.js', 'page-objects/master-trainer/MasterTrainerDashboard.js', 'page-objects/master-trainer/MasterTrainerEvents.js', 'page-objects/master-trainer/MasterTrainerTrainers.js', 'scripts/run-master-trainer-comprehensive.js', 'playwright-master-trainer.config.js', 'README-MASTER-TRAINER-COMPREHENSIVE.md' ]; this.requiredDirectories = [ 'test-results', 'test-results/master-trainer-comprehensive', 'test-results/screenshots', 'test-results/screenshots/master-trainer', 'test-results/videos', 'test-results/videos/master-trainer' ]; this.environment = { baseUrl: process.env.BASE_URL || 'https://upskill-staging.measurequick.com', display: process.env.DISPLAY || ':0', xauthority: process.env.XAUTHORITY || '/run/user/1000/.mutter-Xwaylandauth.U8VEB3', desktop: process.env.XDG_CURRENT_DESKTOP || 'unknown' }; } async validate() { console.log('🔍 Master Trainer E2E Test Setup Validation'); console.log('=========================================='); console.log(''); try { await this.validateFileStructure(); await this.validateDirectoryStructure(); await this.validatePackageJsonScripts(); await this.validatePlaywrightConfig(); await this.validateEnvironment(); await this.validateTestAccounts(); await this.validatePageObjects(); await this.validateDependencies(); this.printValidationReport(); if (this.validationResults.failed === 0) { console.log('✅ All validations passed! Master Trainer E2E tests are ready to execute.'); console.log(''); console.log('🚀 Quick start commands:'); console.log(' npm run test:master-trainer-comprehensive'); console.log(' HEADLESS=false npm run test:master-trainer-headed'); console.log(''); return true; } else { console.log(`❌ ${this.validationResults.failed} validation(s) failed. Please fix the issues above.`); return false; } } catch (error) { console.error('❌ Validation failed with error:', error.message); return false; } } async validateFileStructure() { console.log('📁 Validating file structure...'); for (const file of this.requiredFiles) { const filePath = path.join(__dirname, '..', file); try { await fs.access(filePath); this.pass(`✅ ${file} exists`); } catch (error) { this.fail(`❌ Missing required file: ${file}`); } } } async validateDirectoryStructure() { console.log('📂 Validating directory structure...'); for (const dir of this.requiredDirectories) { const dirPath = path.join(__dirname, '..', dir); try { await fs.mkdir(dirPath, { recursive: true }); this.pass(`✅ Directory ${dir} exists/created`); } catch (error) { this.fail(`❌ Failed to create directory: ${dir} - ${error.message}`); } } } async validatePackageJsonScripts() { console.log('📜 Validating package.json scripts...'); try { const packagePath = path.join(__dirname, '..', 'package.json'); const packageData = await fs.readFile(packagePath, 'utf8'); const packageJson = JSON.parse(packageData); const requiredScripts = [ 'test:master-trainer', 'test:master-trainer-headed', 'test:master-trainer-comprehensive', 'test:master-trainer-debug' ]; for (const script of requiredScripts) { if (packageJson.scripts && packageJson.scripts[script]) { this.pass(`✅ Script "${script}" defined`); } else { this.fail(`❌ Missing script: ${script}`); } } } catch (error) { this.fail(`❌ Failed to validate package.json: ${error.message}`); } } async validatePlaywrightConfig() { console.log('⚙️ Validating Playwright configuration...'); try { const configPath = path.join(__dirname, '..', 'playwright-master-trainer.config.js'); const configExists = await fs.access(configPath).then(() => true).catch(() => false); if (configExists) { this.pass('✅ Playwright master trainer config exists'); // Try to load the config to validate syntax try { const config = require(configPath); if (config.projects && config.projects.length > 0) { this.pass('✅ Playwright config has browser projects'); } else { this.warn('⚠️ Playwright config missing browser projects'); } } catch (error) { this.fail(`❌ Playwright config syntax error: ${error.message}`); } } else { this.fail('❌ Playwright master trainer config missing'); } } catch (error) { this.fail(`❌ Failed to validate Playwright config: ${error.message}`); } } async validateEnvironment() { console.log('🌍 Validating environment configuration...'); // Base URL validation if (this.environment.baseUrl) { this.pass(`✅ Base URL configured: ${this.environment.baseUrl}`); } else { this.fail('❌ BASE_URL not configured'); } // Desktop environment if (this.environment.desktop === 'GNOME') { this.pass('✅ GNOME desktop detected - headed testing available'); } else { this.warn(`⚠️ Non-GNOME desktop (${this.environment.desktop}) - may use headless mode`); } // Display configuration if (this.environment.display) { this.pass(`✅ Display configured: ${this.environment.display}`); } else { this.warn('⚠️ DISPLAY not set - headless mode recommended'); } // Check Node.js version try { const nodeVersion = process.version; const majorVersion = parseInt(nodeVersion.substring(1).split('.')[0]); if (majorVersion >= 16) { this.pass(`✅ Node.js version compatible: ${nodeVersion}`); } else { this.fail(`❌ Node.js version too old: ${nodeVersion} (requires 16+)`); } } catch (error) { this.warn('⚠️ Could not verify Node.js version'); } } async validateTestAccounts() { console.log('🔑 Validating test account configuration...'); const testAccounts = [ { name: 'Primary Master', username: 'test_master', password: 'TestMaster123!' }, { name: 'Alternate Master', username: 'JoeMedosch@gmail.com', password: 'JoeTrainer2025@' } ]; for (const account of testAccounts) { // Basic validation - in a real scenario you might ping the staging server if (account.username && account.password) { this.pass(`✅ ${account.name} account configured: ${account.username}`); } else { this.fail(`❌ ${account.name} account incomplete`); } } // Test staging URL availability try { const url = new URL(this.environment.baseUrl); this.pass(`✅ Staging URL format valid: ${url.hostname}`); } catch (error) { this.fail(`❌ Invalid staging URL: ${this.environment.baseUrl}`); } } async validatePageObjects() { console.log('🎭 Validating page object classes...'); const pageObjects = [ { file: 'MasterTrainerDashboard.js', className: 'MasterTrainerDashboard' }, { file: 'MasterTrainerEvents.js', className: 'MasterTrainerEvents' }, { file: 'MasterTrainerTrainers.js', className: 'MasterTrainerTrainers' } ]; for (const po of pageObjects) { try { const poPath = path.join(__dirname, '..', 'page-objects', 'master-trainer', po.file); const poContent = await fs.readFile(poPath, 'utf8'); if (poContent.includes(`class ${po.className}`)) { this.pass(`✅ Page object ${po.className} properly defined`); } else { this.fail(`❌ Page object ${po.className} class not found in ${po.file}`); } if (poContent.includes('module.exports =')) { this.pass(`✅ Page object ${po.className} properly exported`); } else { this.fail(`❌ Page object ${po.className} not exported`); } } catch (error) { this.fail(`❌ Failed to validate page object ${po.file}: ${error.message}`); } } } async validateDependencies() { console.log('📦 Validating dependencies...'); try { const packagePath = path.join(__dirname, '..', 'package.json'); const packageData = await fs.readFile(packagePath, 'utf8'); const packageJson = JSON.parse(packageData); const requiredDeps = [ '@playwright/test', 'playwright' ]; for (const dep of requiredDeps) { if (packageJson.dependencies && packageJson.dependencies[dep]) { this.pass(`✅ Dependency ${dep} defined`); } else { this.fail(`❌ Missing dependency: ${dep}`); } } // Check if node_modules exists const nodeModulesPath = path.join(__dirname, '..', 'node_modules'); try { await fs.access(nodeModulesPath); this.pass('✅ node_modules directory exists'); } catch (error) { this.fail('❌ node_modules not found - run "npm install"'); } } catch (error) { this.fail(`❌ Failed to validate dependencies: ${error.message}`); } } pass(message) { this.validationResults.passed++; this.validationResults.details.push({ type: 'pass', message }); console.log(` ${message}`); } fail(message) { this.validationResults.failed++; this.validationResults.details.push({ type: 'fail', message }); console.log(` ${message}`); } warn(message) { this.validationResults.warnings++; this.validationResults.details.push({ type: 'warn', message }); console.log(` ${message}`); } printValidationReport() { console.log(''); console.log('📊 Validation Summary'); console.log('===================='); console.log(`✅ Passed: ${this.validationResults.passed}`); console.log(`❌ Failed: ${this.validationResults.failed}`); console.log(`⚠️ Warnings: ${this.validationResults.warnings}`); console.log(`📊 Total: ${this.validationResults.passed + this.validationResults.failed + this.validationResults.warnings}`); console.log(''); if (this.validationResults.warnings > 0) { console.log('⚠️ Warnings (non-blocking):'); const warnings = this.validationResults.details.filter(d => d.type === 'warn'); warnings.forEach(w => console.log(` ${w.message}`)); console.log(''); } if (this.validationResults.failed > 0) { console.log('❌ Failed validations (must fix):'); const failures = this.validationResults.details.filter(d => d.type === 'fail'); failures.forEach(f => console.log(` ${f.message}`)); console.log(''); } } } // Execute validation if called directly if (require.main === module) { const validator = new MasterTrainerSetupValidator(); validator.validate() .then(success => { process.exit(success ? 0 : 1); }) .catch(error => { console.error('Validation error:', error.message); process.exit(1); }); } module.exports = MasterTrainerSetupValidator;