const { chromium } = require('playwright'); const path = require('path'); // Import WordPress error detector const WordPressErrorDetector = require(path.join(__dirname, 'tests', 'framework', 'utils', 'WordPressErrorDetector')); /** * HVAC Master Trainer - Comprehensive E2E Test Suite * Tests all Master Trainer functionality on staging environment * * Test Coverage: * - Master Dashboard * - Events Overview * - Import/Export Data * - Announcements * - Pending Approvals * - Communication Templates * - Trainer Management * - Profile Editing * * Features WordPress error detection to prevent testing against broken sites */ // Configuration const CONFIG = { baseUrl: process.env.BASE_URL || 'https://upskill-staging.measurequick.com', headless: process.env.HEADLESS === 'true', // Set to false to see browser slowMo: process.env.HEADLESS === 'true' ? 0 : 500, // Slow down for visibility when headed timeout: 30000, viewport: { width: 1280, height: 720 } }; // Test Accounts const ACCOUNTS = { master: { username: 'test_master', password: 'TestMaster123!', email: 'test_master@example.com' }, masterAlt: { username: 'JoeMedosch@gmail.com', password: 'JoeTrainer2025@', email: 'JoeMedosch@gmail.com' }, regularTrainer: { username: 'test_trainer', password: 'TestTrainer123!', email: 'test_trainer@example.com' } }; // Test Results Tracking class TestResults { constructor() { this.results = []; this.startTime = Date.now(); } addResult(category, test, status, details = '') { this.results.push({ category, test, status, details, timestamp: new Date().toISOString() }); const icon = status === 'PASSED' ? 'āœ…' : 'āŒ'; console.log(`${icon} ${category} - ${test}`); if (details) console.log(` ${details}`); } printSummary() { const duration = ((Date.now() - this.startTime) / 1000).toFixed(2); const passed = this.results.filter(r => r.status === 'PASSED').length; const failed = this.results.filter(r => r.status === 'FAILED').length; const total = this.results.length; console.log('\n' + '='.repeat(60)); console.log('šŸ“Š TEST SUMMARY'); console.log('='.repeat(60)); console.log(`Total Tests: ${total}`); console.log(`āœ… Passed: ${passed}`); console.log(`āŒ Failed: ${failed}`); console.log(`ā±ļø Duration: ${duration}s`); console.log(`šŸ“ˆ Success Rate: ${((passed/total)*100).toFixed(1)}%`); if (failed > 0) { console.log('\nāŒ FAILED TESTS:'); this.results .filter(r => r.status === 'FAILED') .forEach(r => console.log(` - ${r.category}: ${r.test}`)); } } exportResults() { const filename = `master-trainer-test-results-${Date.now()}.json`; require('fs').writeFileSync(filename, JSON.stringify(this.results, null, 2)); console.log(`\nšŸ“ Results exported to ${filename}`); } } // Main Test Suite async function runMasterTrainerTests() { console.log('šŸ HVAC Master Trainer - Comprehensive E2E Test Suite\n'); console.log('šŸš€ Initializing Master Trainer Test Suite'); console.log(`šŸ“ Target: ${CONFIG.baseUrl}`); console.log(`šŸ–„ļø Mode: ${CONFIG.headless ? 'Headless' : 'Headed'}`); console.log('='.repeat(60) + '\n'); const results = new TestResults(); const browser = await chromium.launch({ headless: CONFIG.headless, slowMo: CONFIG.slowMo }); const context = await browser.newContext({ viewport: CONFIG.viewport }); const page = await context.newPage(); page.setDefaultTimeout(CONFIG.timeout); try { // CRITICAL: Check for WordPress errors before testing console.log('\nšŸ” Checking WordPress Site Health'); console.log('-'.repeat(40)); await page.goto(CONFIG.baseUrl); await page.waitForLoadState('networkidle'); const errorDetector = new WordPressErrorDetector(page); const errorReport = await errorDetector.getErrorReport(); if (errorReport.hasErrors && errorReport.blockingErrors.length > 0) { console.log('āŒ CRITICAL WordPress Errors Detected:'); errorReport.blockingErrors.forEach(error => { console.log(` - ${error.type}: ${error.message}`); }); throw new Error(`WordPress site has critical errors that block testing. Restore from production and re-seed test data.`); } console.log('āœ… WordPress site health check passed'); // 1. LOGIN AS MASTER TRAINER console.log('\nšŸ” Testing Master Trainer Login'); console.log('-'.repeat(40)); await page.goto(`${CONFIG.baseUrl}/training-login/`); await page.waitForLoadState('networkidle'); try { await page.fill('#username', ACCOUNTS.master.username); await page.fill('#password', ACCOUNTS.master.password); await page.click('button[type="submit"]'); await page.waitForURL('**/master-trainer/master-dashboard/**', { timeout: 10000 }); results.addResult('Authentication', 'Master Trainer Login', 'PASSED', `Redirected to: ${page.url()}`); } catch (error) { // Try alternative master account await page.goto(`${CONFIG.baseUrl}/training-login/`); await page.fill('#username', ACCOUNTS.masterAlt.username); await page.fill('#password', ACCOUNTS.masterAlt.password); await page.click('button[type="submit"]'); await page.waitForURL('**/master-trainer/**', { timeout: 10000 }); results.addResult('Authentication', 'Master Trainer Login', 'PASSED', `Used alternative account: ${ACCOUNTS.masterAlt.username}`); } // 2. MASTER DASHBOARD console.log('\nšŸ“Š Testing Master Dashboard'); console.log('-'.repeat(40)); await page.goto(`${CONFIG.baseUrl}/master-trainer/master-dashboard/`); await page.waitForLoadState('networkidle'); // Check dashboard elements const dashboardTests = [ { selector: '.hvac-master-dashboard', name: 'Dashboard Container' }, { selector: '.dashboard-stats', name: 'Statistics Section' }, { selector: '.trainer-count', name: 'Trainer Count' }, { selector: '.event-count', name: 'Event Count' }, { selector: '.recent-activity', name: 'Recent Activity' } ]; for (const test of dashboardTests) { try { await page.waitForSelector(test.selector, { timeout: 5000 }); results.addResult('Master Dashboard', test.name, 'PASSED'); } catch { results.addResult('Master Dashboard', test.name, 'FAILED'); } } // Get statistics try { const stats = await page.evaluate(() => { const trainerCount = document.querySelector('.trainer-count')?.textContent; const eventCount = document.querySelector('.event-count')?.textContent; return { trainers: trainerCount, events: eventCount }; }); results.addResult('Master Dashboard', 'Statistics Display', 'PASSED', `Trainers: ${stats.trainers}, Events: ${stats.events}`); } catch { results.addResult('Master Dashboard', 'Statistics Display', 'FAILED'); } // 3. EVENTS OVERVIEW console.log('\nšŸ“… Testing Events Overview'); console.log('-'.repeat(40)); await page.goto(`${CONFIG.baseUrl}/master-trainer/events/`); await page.waitForLoadState('networkidle'); try { await page.waitForSelector('.master-events-overview', { timeout: 5000 }); results.addResult('Events Overview', 'Page Load', 'PASSED'); // Check for KPI dashboard const hasKPI = await page.isVisible('.kpi-dashboard'); results.addResult('Events Overview', 'KPI Dashboard', hasKPI ? 'PASSED' : 'FAILED'); // Check for filtering options const hasFilters = await page.isVisible('.event-filters'); results.addResult('Events Overview', 'Event Filters', hasFilters ? 'PASSED' : 'FAILED'); } catch (error) { results.addResult('Events Overview', 'Page Load', 'FAILED', error.message); } // 4. IMPORT/EXPORT DATA console.log('\nšŸ“¤ Testing Import/Export Data'); console.log('-'.repeat(40)); await page.goto(`${CONFIG.baseUrl}/master-trainer/import-export/`); await page.waitForLoadState('networkidle'); try { await page.waitForSelector('.import-export-management', { timeout: 5000 }); results.addResult('Import/Export', 'Page Load', 'PASSED'); // Check for CSV operations const hasCSVImport = await page.isVisible('.csv-import-section'); results.addResult('Import/Export', 'CSV Import Section', hasCSVImport ? 'PASSED' : 'FAILED'); const hasCSVExport = await page.isVisible('.csv-export-section'); results.addResult('Import/Export', 'CSV Export Section', hasCSVExport ? 'PASSED' : 'FAILED'); } catch (error) { results.addResult('Import/Export', 'Page Load', 'FAILED', error.message); } // 5. ANNOUNCEMENTS console.log('\nšŸ“¢ Testing Announcements'); console.log('-'.repeat(40)); await page.goto(`${CONFIG.baseUrl}/master-trainer/announcements/`); await page.waitForLoadState('networkidle'); try { await page.waitForSelector('.announcements-management', { timeout: 5000 }); results.addResult('Announcements', 'Page Load', 'PASSED'); // Check for announcement creation const hasCreateButton = await page.isVisible('.create-announcement'); results.addResult('Announcements', 'Create Button', hasCreateButton ? 'PASSED' : 'FAILED'); // Check for existing announcements const announcementsList = await page.isVisible('.announcements-list'); results.addResult('Announcements', 'Announcements List', announcementsList ? 'PASSED' : 'FAILED'); } catch (error) { results.addResult('Announcements', 'Page Load', 'FAILED', error.message); } // 6. PENDING APPROVALS console.log('\nā³ Testing Pending Approvals'); console.log('-'.repeat(40)); await page.goto(`${CONFIG.baseUrl}/master-trainer/pending-approvals/`); await page.waitForLoadState('networkidle'); try { await page.waitForSelector('.pending-approvals', { timeout: 5000 }); results.addResult('Pending Approvals', 'Page Load', 'PASSED'); // Check for trainer approvals section const hasTrainerApprovals = await page.isVisible('.trainer-approvals'); results.addResult('Pending Approvals', 'Trainer Approvals', hasTrainerApprovals ? 'PASSED' : 'FAILED'); // Check for event approvals section const hasEventApprovals = await page.isVisible('.event-approvals'); results.addResult('Pending Approvals', 'Event Approvals', hasEventApprovals ? 'PASSED' : 'FAILED'); } catch (error) { results.addResult('Pending Approvals', 'Page Load', 'FAILED', error.message); } // 7. COMMUNICATION TEMPLATES console.log('\nšŸ“ Testing Communication Templates'); console.log('-'.repeat(40)); await page.goto(`${CONFIG.baseUrl}/master-trainer/communication-templates/`); await page.waitForLoadState('networkidle'); try { await page.waitForSelector('.communication-templates', { timeout: 5000 }); results.addResult('Communication Templates', 'Page Load', 'PASSED'); // Check for template accordion const hasAccordion = await page.isVisible('.template-accordion'); results.addResult('Communication Templates', 'Template Accordion', hasAccordion ? 'PASSED' : 'FAILED'); // Check for copy functionality const hasCopyButtons = await page.isVisible('.copy-template'); results.addResult('Communication Templates', 'Copy Buttons', hasCopyButtons ? 'PASSED' : 'FAILED'); } catch (error) { results.addResult('Communication Templates', 'Page Load', 'FAILED', error.message); } // 8. TRAINER MANAGEMENT console.log('\nšŸ‘„ Testing Trainer Management'); console.log('-'.repeat(40)); await page.goto(`${CONFIG.baseUrl}/master-trainer/trainers/`); await page.waitForLoadState('networkidle'); try { await page.waitForSelector('.trainer-management', { timeout: 5000 }); results.addResult('Trainer Management', 'Page Load', 'PASSED'); // Check for trainer list const hasTrainerList = await page.isVisible('.trainer-list'); results.addResult('Trainer Management', 'Trainer List', hasTrainerList ? 'PASSED' : 'FAILED'); // Check for edit capabilities const hasEditButtons = await page.isVisible('.edit-trainer'); results.addResult('Trainer Management', 'Edit Buttons', hasEditButtons ? 'PASSED' : 'FAILED'); // Check for role management const hasRoleManagement = await page.isVisible('.role-management'); results.addResult('Trainer Management', 'Role Management', hasRoleManagement ? 'PASSED' : 'FAILED'); } catch (error) { results.addResult('Trainer Management', 'Page Load', 'FAILED', error.message); } // 9. NAVIGATION MENU console.log('\n🧭 Testing Master Navigation Menu'); console.log('-'.repeat(40)); const navigationTests = [ { text: 'Dashboard', url: '/master-trainer/master-dashboard/' }, { text: 'Events', url: '/master-trainer/events/' }, { text: 'Trainers', url: '/master-trainer/trainers/' }, { text: 'Tools', dropdown: true }, { text: 'Reports', dropdown: true } ]; for (const navTest of navigationTests) { try { if (navTest.dropdown) { const dropdown = await page.locator(`.hvac-menu-item:has-text("${navTest.text}")`); await dropdown.hover(); results.addResult('Navigation', `${navTest.text} Dropdown`, 'PASSED'); } else { const link = await page.locator(`a:has-text("${navTest.text}")`).first(); const href = await link.getAttribute('href'); results.addResult('Navigation', navTest.text, 'PASSED', `Link: ${href}`); } } catch { results.addResult('Navigation', navTest.text, 'FAILED'); } } // 10. ROLE-BASED ACCESS CONTROL console.log('\nšŸ”’ Testing Role-Based Access Control'); console.log('-'.repeat(40)); // Test that master trainer can access all pages const masterPages = [ '/master-trainer/master-dashboard/', '/master-trainer/events/', '/master-trainer/import-export/', '/master-trainer/trainers/' ]; for (const pageUrl of masterPages) { try { await page.goto(`${CONFIG.baseUrl}${pageUrl}`); await page.waitForLoadState('networkidle'); const hasAccess = !page.url().includes('login'); results.addResult('Access Control', `Master Access: ${pageUrl}`, hasAccess ? 'PASSED' : 'FAILED'); } catch { results.addResult('Access Control', `Master Access: ${pageUrl}`, 'FAILED'); } } // 11. DATA VALIDATION console.log('\nāœ”ļø Testing Data Validation'); console.log('-'.repeat(40)); // Test trainer count consistency await page.goto(`${CONFIG.baseUrl}/master-trainer/master-dashboard/`); try { const dashboardCount = await page.locator('.trainer-count').textContent(); await page.goto(`${CONFIG.baseUrl}/master-trainer/trainers/`); const listCount = await page.locator('.trainer-list .trainer-item').count(); results.addResult('Data Validation', 'Trainer Count Consistency', 'PASSED', `Dashboard: ${dashboardCount}, List: ${listCount}`); } catch { results.addResult('Data Validation', 'Trainer Count Consistency', 'FAILED'); } // 12. RESPONSIVE DESIGN console.log('\nšŸ“± Testing Responsive Design'); console.log('-'.repeat(40)); // Test mobile viewport await page.setViewportSize({ width: 375, height: 667 }); await page.goto(`${CONFIG.baseUrl}/master-trainer/master-dashboard/`); await page.waitForLoadState('networkidle'); try { const mobileMenu = await page.isVisible('.mobile-menu-toggle'); results.addResult('Responsive Design', 'Mobile Menu', mobileMenu ? 'PASSED' : 'FAILED'); } catch { results.addResult('Responsive Design', 'Mobile Menu', 'FAILED'); } // Restore desktop viewport await page.setViewportSize(CONFIG.viewport); } catch (error) { console.error('\nāŒ Test Suite Error:', error.message); results.addResult('Test Suite', 'Critical Error', 'FAILED', error.message); } finally { // Print summary results.printSummary(); results.exportResults(); // Take final screenshot await page.screenshot({ path: `master-trainer-test-${Date.now()}.png`, fullPage: true }); await browser.close(); } } // Execute tests runMasterTrainerTests().catch(console.error);