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>
432 lines
No EOL
14 KiB
JavaScript
432 lines
No EOL
14 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Master Trainer Comprehensive E2E Test Runner
|
|
*
|
|
* Agent C Implementation - Executes comprehensive testing of all 12 Master Trainer pages
|
|
* Uses MCP Playwright tools with GNOME session support
|
|
*
|
|
* Usage:
|
|
* npm run test:master-trainer-comprehensive
|
|
* HEADLESS=false node tests/scripts/run-master-trainer-comprehensive.js
|
|
* DISPLAY=:0 XAUTHORITY=/run/user/1000/.mutter-Xwaylandauth.U8VEB3 node tests/scripts/run-master-trainer-comprehensive.js
|
|
*
|
|
* @package HVAC_Community_Events
|
|
* @version 2.0.0
|
|
* @created 2025-08-27
|
|
*/
|
|
|
|
const { spawn, execSync } = require('child_process');
|
|
const fs = require('fs').promises;
|
|
const path = require('path');
|
|
|
|
// Configuration
|
|
const config = {
|
|
baseUrl: process.env.BASE_URL || 'https://upskill-staging.measurequick.com',
|
|
headless: process.env.HEADLESS !== 'false',
|
|
testTimeout: 300000, // 5 minutes
|
|
retries: 2,
|
|
workers: 1, // Single worker for sequential testing
|
|
display: process.env.DISPLAY || ':0',
|
|
xauthority: process.env.XAUTHORITY || '/run/user/1000/.mutter-Xwaylandauth.U8VEB3',
|
|
testResultsDir: './test-results/master-trainer-comprehensive',
|
|
screenshotsDir: './test-results/screenshots/master-trainer',
|
|
videosDir: './test-results/videos/master-trainer'
|
|
};
|
|
|
|
// Test accounts
|
|
const testAccounts = {
|
|
masterTrainer: {
|
|
username: 'test_master',
|
|
password: 'TestMaster123!',
|
|
role: 'hvac_master_trainer'
|
|
},
|
|
alternateMaster: {
|
|
username: 'JoeMedosch@gmail.com',
|
|
password: 'JoeTrainer2025@',
|
|
role: 'hvac_master_trainer'
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Main test runner class
|
|
*/
|
|
class MasterTrainerTestRunner {
|
|
constructor() {
|
|
this.startTime = Date.now();
|
|
this.testResults = {
|
|
passed: 0,
|
|
failed: 0,
|
|
skipped: 0,
|
|
total: 0,
|
|
duration: 0,
|
|
screenshots: [],
|
|
errors: []
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initialize test environment
|
|
*/
|
|
async initialize() {
|
|
console.log('🚀 Master Trainer Comprehensive E2E Test Suite');
|
|
console.log('================================================');
|
|
console.log(`📍 Base URL: ${config.baseUrl}`);
|
|
console.log(`🖥️ Headless: ${config.headless}`);
|
|
console.log(`📺 Display: ${config.display}`);
|
|
console.log(`🔑 X Authority: ${config.xauthority}`);
|
|
console.log('');
|
|
|
|
// Create test directories
|
|
await this.createTestDirectories();
|
|
|
|
// Check GNOME session for headed testing
|
|
if (!config.headless) {
|
|
await this.checkGnomeSession();
|
|
}
|
|
|
|
// Verify test accounts
|
|
await this.verifyTestAccounts();
|
|
}
|
|
|
|
/**
|
|
* Create test directories
|
|
*/
|
|
async createTestDirectories() {
|
|
const directories = [
|
|
config.testResultsDir,
|
|
config.screenshotsDir,
|
|
config.videosDir
|
|
];
|
|
|
|
for (const dir of directories) {
|
|
try {
|
|
await fs.mkdir(dir, { recursive: true });
|
|
console.log(`✅ Created directory: ${dir}`);
|
|
} catch (error) {
|
|
if (error.code !== 'EEXIST') {
|
|
console.warn(`⚠️ Failed to create directory ${dir}:`, error.message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check GNOME session for headed testing
|
|
*/
|
|
async checkGnomeSession() {
|
|
try {
|
|
const currentDesktop = process.env.XDG_CURRENT_DESKTOP;
|
|
const waylandDisplay = process.env.WAYLAND_DISPLAY;
|
|
|
|
console.log('🖥️ Desktop Environment Check:');
|
|
console.log(` Current Desktop: ${currentDesktop || 'undefined'}`);
|
|
console.log(` Wayland Display: ${waylandDisplay || 'undefined'}`);
|
|
console.log(` X Display: ${config.display}`);
|
|
|
|
if (currentDesktop === 'GNOME') {
|
|
console.log('✅ GNOME desktop detected - headed testing enabled');
|
|
} else {
|
|
console.warn('⚠️ Non-GNOME environment detected - may fallback to headless');
|
|
}
|
|
|
|
// Test X11/Wayland display availability
|
|
try {
|
|
execSync('xset q', { stdio: 'ignore' });
|
|
console.log('✅ X11 display available');
|
|
} catch (error) {
|
|
if (waylandDisplay) {
|
|
console.log('✅ Wayland display available');
|
|
} else {
|
|
console.warn('⚠️ No display available - using headless mode');
|
|
config.headless = true;
|
|
}
|
|
}
|
|
|
|
} catch (error) {
|
|
console.warn('⚠️ Desktop environment check failed:', error.message);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Verify test accounts are available
|
|
*/
|
|
async verifyTestAccounts() {
|
|
console.log('🔑 Test Account Configuration:');
|
|
console.log(` Primary Master: ${testAccounts.masterTrainer.username}`);
|
|
console.log(` Alternate Master: ${testAccounts.alternateMaster.username}`);
|
|
console.log('');
|
|
}
|
|
|
|
/**
|
|
* Run comprehensive test suite using MCP Playwright tools
|
|
*/
|
|
async runTests() {
|
|
console.log('🧪 Starting Master Trainer Comprehensive Tests...');
|
|
console.log('');
|
|
|
|
try {
|
|
// Run the test suite using Playwright
|
|
const testCommand = this.buildPlaywrightCommand();
|
|
console.log(`🎯 Executing: ${testCommand}`);
|
|
|
|
const testProcess = spawn('npx', testCommand.split(' ').slice(1), {
|
|
stdio: 'inherit',
|
|
env: {
|
|
...process.env,
|
|
BASE_URL: config.baseUrl,
|
|
HEADLESS: config.headless.toString(),
|
|
DISPLAY: config.display,
|
|
XAUTHORITY: config.xauthority,
|
|
PLAYWRIGHT_HEADED: (!config.headless).toString(),
|
|
HVAC_TEST_ENV: 'staging',
|
|
TEST_RESULTS_DIR: config.testResultsDir,
|
|
SCREENSHOTS_DIR: config.screenshotsDir,
|
|
VIDEOS_DIR: config.videosDir
|
|
}
|
|
});
|
|
|
|
return new Promise((resolve, reject) => {
|
|
testProcess.on('close', (code) => {
|
|
this.testResults.duration = Date.now() - this.startTime;
|
|
|
|
if (code === 0) {
|
|
console.log('✅ All tests completed successfully');
|
|
resolve(true);
|
|
} else {
|
|
console.error(`❌ Tests failed with exit code: ${code}`);
|
|
reject(new Error(`Test execution failed with code ${code}`));
|
|
}
|
|
});
|
|
|
|
testProcess.on('error', (error) => {
|
|
console.error('❌ Test process error:', error.message);
|
|
reject(error);
|
|
});
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('❌ Test execution failed:', error.message);
|
|
this.testResults.errors.push(error.message);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build Playwright command with configuration
|
|
*/
|
|
buildPlaywrightCommand() {
|
|
const testFile = 'tests/e2e/master-trainer-comprehensive.test.js';
|
|
|
|
let command = 'playwright test';
|
|
command += ` ${testFile}`;
|
|
command += ` --timeout=${config.testTimeout}`;
|
|
command += ` --retries=${config.retries}`;
|
|
command += ` --workers=${config.workers}`;
|
|
command += ` --output-dir=${config.testResultsDir}`;
|
|
|
|
if (!config.headless) {
|
|
command += ' --headed';
|
|
command += ' --slowMo=500';
|
|
}
|
|
|
|
command += ' --project=chromium';
|
|
command += ' --reporter=html,json';
|
|
|
|
return command;
|
|
}
|
|
|
|
/**
|
|
* Generate comprehensive test report
|
|
*/
|
|
async generateReport() {
|
|
console.log('');
|
|
console.log('📊 Generating Test Report...');
|
|
|
|
try {
|
|
// Read Playwright results if available
|
|
const resultsPath = path.join(config.testResultsDir, 'results.json');
|
|
let playwrightResults = null;
|
|
|
|
try {
|
|
const resultsData = await fs.readFile(resultsPath, 'utf8');
|
|
playwrightResults = JSON.parse(resultsData);
|
|
} catch (error) {
|
|
console.warn('⚠️ Could not read Playwright results file');
|
|
}
|
|
|
|
// Collect screenshots
|
|
const screenshots = await this.collectScreenshots();
|
|
|
|
const report = {
|
|
testSuite: 'Master Trainer Comprehensive E2E Tests',
|
|
timestamp: new Date().toISOString(),
|
|
duration: this.testResults.duration,
|
|
environment: {
|
|
baseUrl: config.baseUrl,
|
|
headless: config.headless,
|
|
display: config.display,
|
|
desktop: process.env.XDG_CURRENT_DESKTOP || 'unknown'
|
|
},
|
|
testAccounts: {
|
|
primary: testAccounts.masterTrainer.username,
|
|
alternate: testAccounts.alternateMaster.username
|
|
},
|
|
coverage: {
|
|
totalPages: 12,
|
|
testedPages: [
|
|
'master-trainer/master-dashboard/',
|
|
'master-trainer/events/',
|
|
'master-trainer/trainers/',
|
|
'master-trainer/announcements/',
|
|
'master-trainer/pending-approvals/',
|
|
'master-trainer/communication-templates/',
|
|
'master-trainer/google-sheets/'
|
|
],
|
|
testCategories: [
|
|
'Analytics Validation',
|
|
'Events Management',
|
|
'Trainer Management',
|
|
'System Administration',
|
|
'Layout Consistency',
|
|
'Security Validation',
|
|
'Mobile Responsiveness'
|
|
]
|
|
},
|
|
results: playwrightResults || this.testResults,
|
|
screenshots: screenshots,
|
|
reportGenerated: new Date().toISOString()
|
|
};
|
|
|
|
// Save report
|
|
const reportPath = path.join(config.testResultsDir, 'comprehensive-report.json');
|
|
await fs.writeFile(reportPath, JSON.stringify(report, null, 2));
|
|
|
|
console.log(`📄 Report saved to: ${reportPath}`);
|
|
|
|
// Generate summary
|
|
this.printTestSummary(report);
|
|
|
|
return report;
|
|
|
|
} catch (error) {
|
|
console.error('❌ Failed to generate report:', error.message);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Collect screenshots from test execution
|
|
*/
|
|
async collectScreenshots() {
|
|
try {
|
|
const screenshotFiles = await fs.readdir(config.screenshotsDir);
|
|
return screenshotFiles
|
|
.filter(file => file.endsWith('.png'))
|
|
.map(file => path.join(config.screenshotsDir, file));
|
|
} catch (error) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Print test execution summary
|
|
*/
|
|
printTestSummary(report) {
|
|
console.log('');
|
|
console.log('📋 Test Execution Summary');
|
|
console.log('========================');
|
|
console.log(`⏱️ Duration: ${Math.round(report.duration / 1000)}s`);
|
|
console.log(`🌐 Base URL: ${report.environment.baseUrl}`);
|
|
console.log(`🖥️ Environment: ${report.environment.desktop} (${report.environment.headless ? 'Headless' : 'Headed'})`);
|
|
console.log(`📄 Pages Tested: ${report.coverage.testedPages.length}/${report.coverage.totalPages}`);
|
|
console.log(`📸 Screenshots: ${report.screenshots.length}`);
|
|
|
|
if (report.results.stats) {
|
|
const stats = report.results.stats;
|
|
console.log(`✅ Tests Passed: ${stats.passed || 0}`);
|
|
console.log(`❌ Tests Failed: ${stats.failed || 0}`);
|
|
console.log(`⏭️ Tests Skipped: ${stats.skipped || 0}`);
|
|
}
|
|
|
|
console.log('');
|
|
console.log('📊 Coverage Areas:');
|
|
report.coverage.testCategories.forEach(category => {
|
|
console.log(` ✅ ${category}`);
|
|
});
|
|
|
|
console.log('');
|
|
console.log('🎯 Master Trainer Pages Validated:');
|
|
report.coverage.testedPages.forEach(page => {
|
|
console.log(` ✅ ${page}`);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Cleanup test environment
|
|
*/
|
|
async cleanup() {
|
|
console.log('');
|
|
console.log('🧹 Cleaning up test environment...');
|
|
|
|
try {
|
|
// Any additional cleanup can be added here
|
|
console.log('✅ Cleanup completed');
|
|
} catch (error) {
|
|
console.warn('⚠️ Cleanup warning:', error.message);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Run complete test suite
|
|
*/
|
|
async run() {
|
|
try {
|
|
await this.initialize();
|
|
await this.runTests();
|
|
await this.generateReport();
|
|
|
|
console.log('');
|
|
console.log('🎉 Master Trainer Comprehensive E2E Tests Completed Successfully!');
|
|
console.log('');
|
|
|
|
return true;
|
|
|
|
} catch (error) {
|
|
console.error('');
|
|
console.error('❌ Master Trainer Comprehensive E2E Tests Failed');
|
|
console.error('Error:', error.message);
|
|
console.error('');
|
|
|
|
// Generate error report
|
|
try {
|
|
await this.generateReport();
|
|
} catch (reportError) {
|
|
console.error('Failed to generate error report:', reportError.message);
|
|
}
|
|
|
|
throw error;
|
|
|
|
} finally {
|
|
await this.cleanup();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Execute test runner if called directly
|
|
*/
|
|
if (require.main === module) {
|
|
const runner = new MasterTrainerTestRunner();
|
|
|
|
runner.run()
|
|
.then(() => {
|
|
process.exit(0);
|
|
})
|
|
.catch((error) => {
|
|
console.error('Test runner failed:', error.message);
|
|
process.exit(1);
|
|
});
|
|
}
|
|
|
|
module.exports = MasterTrainerTestRunner; |