Some checks are pending
HVAC Plugin CI/CD Pipeline / Security Analysis (push) Waiting to run
HVAC Plugin CI/CD Pipeline / Code Quality & Standards (push) Waiting to run
HVAC Plugin CI/CD Pipeline / Unit Tests (push) Waiting to run
HVAC Plugin CI/CD Pipeline / Integration Tests (push) Waiting to run
HVAC Plugin CI/CD Pipeline / Deploy to Staging (push) Blocked by required conditions
HVAC Plugin CI/CD Pipeline / Deploy to Production (push) Blocked by required conditions
HVAC Plugin CI/CD Pipeline / Notification (push) Blocked by required conditions
Security Monitoring & Compliance / Dependency Vulnerability Scan (push) Waiting to run
Security Monitoring & Compliance / Secrets & Credential Scan (push) Waiting to run
Security Monitoring & Compliance / WordPress Security Analysis (push) Waiting to run
Security Monitoring & Compliance / Static Code Security Analysis (push) Waiting to run
Security Monitoring & Compliance / Security Compliance Validation (push) Waiting to run
Security Monitoring & Compliance / Security Summary Report (push) Blocked by required conditions
Security Monitoring & Compliance / Security Team Notification (push) Blocked by required conditions
- Add 90+ test files including E2E, unit, and integration tests - Implement Page Object Model (POM) architecture - Add Docker testing environment with comprehensive services - Include modernized test framework with error recovery - Add specialized test suites for master trainer and trainer workflows - Update .gitignore to properly track test infrastructure 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
364 lines
No EOL
14 KiB
JavaScript
364 lines
No EOL
14 KiB
JavaScript
#!/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; |