/** * HVAC Community Events - E2E Functionality Tests with Bundled Assets * * Comprehensive end-to-end testing to ensure all major user workflows * function correctly with the new bundled asset system. * * @package HVAC_Community_Events * @since 2.0.0 */ const { test, expect } = require('@playwright/test'); const BasePage = require('./page-objects/base/BasePage'); const TrainerDashboard = require('./page-objects/trainer/TrainerDashboard'); const MasterTrainerDashboard = require('./page-objects/master-trainer/MasterTrainerDashboard'); // Test configuration const TEST_CONFIG = { BASE_URL: process.env.BASE_URL || 'http://localhost:8080', TEST_TIMEOUT: 30000, // Test user credentials (should be set up in Docker environment) TRAINER_USER: { username: 'test_trainer', password: 'test_password' }, MASTER_TRAINER_USER: { username: 'master_trainer', password: 'master_password' }, // Expected bundles for different page types EXPECTED_BUNDLES: { TRAINER_DASHBOARD: ['hvac-core.bundle.js', 'hvac-dashboard.bundle.js', 'hvac-trainer.bundle.js'], MASTER_DASHBOARD: ['hvac-core.bundle.js', 'hvac-master.bundle.js'], CERTIFICATES: ['hvac-core.bundle.js', 'hvac-certificates.bundle.js'], EVENTS: ['hvac-core.bundle.js', 'hvac-events.bundle.js'], ADMIN: ['hvac-admin.bundle.js'] } }; /** * Bundled Assets E2E Test Base */ class BundledAssetsE2EBase extends BasePage { constructor(page) { super(page); this.loadedBundles = new Set(); this.bundleLoadErrors = []; this.jsErrors = []; this.networkFailures = []; this.monitoringEnabled = false; } /** * Enable comprehensive asset monitoring */ async enableAssetMonitoring() { if (this.monitoringEnabled) return; // Monitor network requests for bundles this.page.on('response', (response) => { const url = response.url(); if (url.includes('/assets/js/dist/') && url.endsWith('.bundle.js')) { const bundleName = url.split('/').pop(); if (response.ok()) { this.loadedBundles.add(bundleName); console.log(`๐Ÿ“ฆ Bundle loaded: ${bundleName}`); } else { this.bundleLoadErrors.push({ bundle: bundleName, status: response.status(), url: url }); console.error(`โŒ Bundle failed to load: ${bundleName} (${response.status()})`); } } }); // Monitor JavaScript errors this.page.on('pageerror', (error) => { this.jsErrors.push({ message: error.message, stack: error.stack, timestamp: new Date().toISOString() }); console.error(`๐Ÿ› JavaScript error: ${error.message}`); }); // Monitor console errors this.page.on('console', (message) => { if (message.type() === 'error') { console.error(`๐Ÿ”ด Console error: ${message.text()}`); } }); // Monitor network failures this.page.on('requestfailed', (request) => { if (request.url().includes('.bundle.js')) { this.networkFailures.push({ url: request.url(), failure: request.failure()?.errorText, timestamp: new Date().toISOString() }); console.error(`๐ŸŒ Network failure: ${request.url()}`); } }); this.monitoringEnabled = true; } /** * Check if expected bundles are loaded * @param {string[]} expectedBundles */ validateExpectedBundles(expectedBundles) { const results = { expected: expectedBundles, loaded: Array.from(this.loadedBundles), missing: [], unexpected: [], errors: this.bundleLoadErrors }; // Check for missing bundles expectedBundles.forEach(bundle => { if (!this.loadedBundles.has(bundle)) { results.missing.push(bundle); } }); // Check for unexpected bundles (informational) Array.from(this.loadedBundles).forEach(bundle => { if (!expectedBundles.includes(bundle)) { results.unexpected.push(bundle); } }); return results; } /** * Wait for bundles to load and basic functionality to be available */ async waitForBundleInitialization() { // Wait for DOM to be ready await this.page.waitForLoadState('domcontentloaded'); // Wait for bundles to load (network idle) await this.page.waitForLoadState('networkidle', { timeout: 15000 }); // Wait for jQuery and basic HVAC functionality await this.page.waitForFunction(() => { return typeof window.jQuery !== 'undefined' && typeof window.$ !== 'undefined' && (window.hvacBundleData !== undefined || window.hvac !== undefined); }, { timeout: 10000 }); // Small additional wait for bundle initialization await this.page.waitForTimeout(1000); } /** * Generate comprehensive test report */ generateTestReport() { return { bundleMonitoring: { loadedBundles: Array.from(this.loadedBundles), loadErrors: this.bundleLoadErrors, networkFailures: this.networkFailures }, errors: { jsErrors: this.jsErrors, totalErrors: this.jsErrors.length + this.bundleLoadErrors.length }, performance: { bundleCount: this.loadedBundles.size, errorRate: this.bundleLoadErrors.length / Math.max(this.loadedBundles.size, 1) } }; } } /** * Enhanced Trainer Dashboard for Bundle Testing */ class BundledTrainerDashboard extends TrainerDashboard { constructor(page) { super(page); this.bundleMonitor = new BundledAssetsE2EBase(page); } async navigateAndMonitor() { await this.bundleMonitor.enableAssetMonitoring(); await this.navigate(); await this.bundleMonitor.waitForBundleInitialization(); return this.bundleMonitor.validateExpectedBundles(TEST_CONFIG.EXPECTED_BUNDLES.TRAINER_DASHBOARD); } } /** * Enhanced Master Trainer Dashboard for Bundle Testing */ class BundledMasterTrainerDashboard extends MasterTrainerDashboard { constructor(page) { super(page); this.bundleMonitor = new BundledAssetsE2EBase(page); } async navigateAndMonitor() { await this.bundleMonitor.enableAssetMonitoring(); await this.navigate(); await this.bundleMonitor.waitForBundleInitialization(); return this.bundleMonitor.validateExpectedBundles(TEST_CONFIG.EXPECTED_BUNDLES.MASTER_DASHBOARD); } } // ============================================================================== // E2E FUNCTIONALITY TESTS WITH BUNDLED ASSETS // ============================================================================== test.describe('E2E Functionality with Bundled Assets', () => { let trainerDashboard; let masterDashboard; test.beforeEach(async ({ page }) => { trainerDashboard = new BundledTrainerDashboard(page); masterDashboard = new BundledMasterTrainerDashboard(page); }); test('Trainer Dashboard - Complete User Journey with Bundle Validation', async ({ page }) => { console.log('๐ŸŽฏ Testing Trainer Dashboard journey with bundled assets...'); // Navigate to trainer dashboard with bundle monitoring const bundleValidation = await trainerDashboard.navigateAndMonitor(); // Validate bundles loaded correctly expect(bundleValidation.missing.length).toBe(0); console.log('โœ… All expected bundles loaded:', bundleValidation.loaded); // Test core dashboard functionality await trainerDashboard.waitForDashboardLoad(); // Test navigation with bundled assets const navigationWorking = await page.evaluate(() => { // Test if navigation JavaScript is working const navElements = document.querySelectorAll('nav a, .navigation a, .menu a'); return navElements.length > 0; }); expect(navigationWorking).toBe(true); // Test dashboard-specific functionality const dashboardFunctions = await page.evaluate(() => { const results = { jQueryLoaded: typeof window.jQuery !== 'undefined', hvacDataLoaded: typeof window.hvacBundleData !== 'undefined', dashboardModulesLoaded: typeof window.hvacDashboard !== 'undefined' || document.querySelector('.dashboard-widgets, .trainer-dashboard') !== null }; return results; }); expect(dashboardFunctions.jQueryLoaded).toBe(true); expect(dashboardFunctions.hvacDataLoaded).toBe(true); console.log('โœ… Dashboard functionality validated'); // Test interactive elements const interactiveElements = await page.locator('.button, .btn, input[type="submit"], a[href]').count(); expect(interactiveElements).toBeGreaterThan(0); // Generate test report const report = trainerDashboard.bundleMonitor.generateTestReport(); console.log('๐Ÿ“Š Test Report:', JSON.stringify(report, null, 2)); // No critical errors should occur expect(report.errors.jsErrors.length).toBeLessThan(3); // Allow minor non-critical errors }); test('Master Trainer Dashboard - Administrative Functions with Bundle Validation', async ({ page }) => { console.log('๐ŸŽฏ Testing Master Trainer Dashboard with bundled assets...'); // Navigate with bundle monitoring const bundleValidation = await masterDashboard.navigateAndMonitor(); // Validate expected bundles expect(bundleValidation.missing.length).toBe(0); console.log('โœ… Master trainer bundles loaded:', bundleValidation.loaded); // Test master trainer specific functionality const masterFunctions = await page.evaluate(() => { return { hasAdminInterface: document.querySelector('.master-dashboard, .admin-interface') !== null, hasTrainerManagement: document.querySelector('.trainer-management, .manage-trainers') !== null, hasEventManagement: document.querySelector('.event-management, .manage-events') !== null, hasReports: document.querySelector('.reports, .analytics') !== null }; }); // At least some master trainer functionality should be present const masterFunctionCount = Object.values(masterFunctions).filter(Boolean).length; expect(masterFunctionCount).toBeGreaterThan(0); console.log('โœ… Master trainer functionality detected:', masterFunctions); // Test administrative actions const adminElements = await page.locator('.admin-action, .manage-action, .approve-btn').count(); console.log(`Found ${adminElements} administrative elements`); // Generate report const report = masterDashboard.bundleMonitor.generateTestReport(); expect(report.errors.totalErrors).toBeLessThan(3); }); test('Event Creation - Complete Workflow with Bundle Validation', async ({ page }) => { console.log('๐ŸŽฏ Testing Event Creation workflow with bundled assets...'); const bundleMonitor = new BundledAssetsE2EBase(page); await bundleMonitor.enableAssetMonitoring(); // Navigate to event creation page await page.goto(`${TEST_CONFIG.BASE_URL}/events/community/add/`); await bundleMonitor.waitForBundleInitialization(); // Validate event-related bundles const bundleValidation = bundleMonitor.validateExpectedBundles(TEST_CONFIG.EXPECTED_BUNDLES.EVENTS); console.log('Event page bundles:', bundleValidation.loaded); // Test event form functionality const eventFormWorking = await page.evaluate(() => { const eventForm = document.querySelector('#tribe-community-events, .event-form, form[action*="event"]'); const titleField = document.querySelector('#EventTitle, input[name*="title"], input[name*="event"]'); const contentField = document.querySelector('#EventContent, textarea[name*="content"], textarea[name*="description"]'); return { formExists: eventForm !== null, titleFieldExists: titleField !== null, contentFieldExists: contentField !== null, formElementsCount: eventForm ? eventForm.querySelectorAll('input, textarea, select').length : 0 }; }); expect(eventFormWorking.formExists).toBe(true); console.log('โœ… Event form validation:', eventFormWorking); // Test JavaScript form enhancements const formEnhancements = await page.evaluate(() => { return { datepickersInitialized: document.querySelectorAll('.hasDatepicker, input[data-datepicker]').length > 0, validationActive: typeof window.hvacEventValidation !== 'undefined' || document.querySelectorAll('.required, [required]').length > 0, ajaxEnabled: typeof window.hvacBundleData !== 'undefined' && window.hvacBundleData.ajax_url !== undefined }; }); console.log('โœ… Form enhancements:', formEnhancements); // Generate report const report = bundleMonitor.generateTestReport(); expect(report.errors.totalErrors).toBeLessThan(3); }); test('Certificate Generation - Functionality with Bundle Validation', async ({ page }) => { console.log('๐ŸŽฏ Testing Certificate Generation with bundled assets...'); const bundleMonitor = new BundledAssetsE2EBase(page); await bundleMonitor.enableAssetMonitoring(); // Navigate to certificate page await page.goto(`${TEST_CONFIG.BASE_URL}/trainer/certificates/`); await bundleMonitor.waitForBundleInitialization(); // Validate certificate bundles const bundleValidation = bundleMonitor.validateExpectedBundles(TEST_CONFIG.EXPECTED_BUNDLES.CERTIFICATES); console.log('Certificate page bundles:', bundleValidation.loaded); // Test certificate functionality const certificateFunctions = await page.evaluate(() => { return { hasCertificateInterface: document.querySelector('.certificate-interface, .generate-certificate') !== null, hasCertificateList: document.querySelector('.certificate-list, .certificates') !== null, hasGenerateButtons: document.querySelectorAll('.generate-btn, .create-certificate').length > 0, hasPdfSupport: typeof window.jsPDF !== 'undefined' || document.querySelector('canvas, .pdf-preview') !== null }; }); console.log('โœ… Certificate functionality:', certificateFunctions); // Test certificate-specific JavaScript const certificateJS = await page.evaluate(() => { return { certificateModuleLoaded: typeof window.hvacCertificates !== 'undefined', canvasSupported: typeof HTMLCanvasElement !== 'undefined', downloadSupported: typeof document.createElement('a').download !== 'undefined' }; }); expect(certificateJS.canvasSupported).toBe(true); expect(certificateJS.downloadSupported).toBe(true); console.log('โœ… Certificate JavaScript support:', certificateJS); // Generate report const report = bundleMonitor.generateTestReport(); expect(report.errors.totalErrors).toBeLessThan(3); }); test('Mobile Responsive - Bundle Loading on Mobile Viewport', async ({ page }) => { console.log('๐Ÿ“ฑ Testing mobile responsive bundle loading...'); // Set mobile viewport await page.setViewportSize({ width: 375, height: 667 }); const bundleMonitor = new BundledAssetsE2EBase(page); await bundleMonitor.enableAssetMonitoring(); // Test trainer dashboard on mobile await page.goto(`${TEST_CONFIG.BASE_URL}/trainer/dashboard/`); await bundleMonitor.waitForBundleInitialization(); const bundleValidation = bundleMonitor.validateExpectedBundles(TEST_CONFIG.EXPECTED_BUNDLES.TRAINER_DASHBOARD); expect(bundleValidation.missing.length).toBe(0); // Test mobile-specific functionality const mobileFunctions = await page.evaluate(() => { return { touchEventsSupported: 'ontouchstart' in window, responsiveElementsPresent: document.querySelectorAll('.mobile-nav, .hamburger, .collapse').length > 0, viewportMetaExists: document.querySelector('meta[name="viewport"]') !== null, mobileOptimizations: document.querySelectorAll('.hidden-mobile, .visible-mobile, .mobile-only').length > 0 }; }); console.log('๐Ÿ“ฑ Mobile functionality:', mobileFunctions); // Test mobile navigation const mobileNavigation = await page.evaluate(() => { const navToggle = document.querySelector('.nav-toggle, .menu-toggle, .hamburger'); if (navToggle) { navToggle.click(); return { toggleFound: true, toggleWorked: true }; } return { toggleFound: false, toggleWorked: false }; }); console.log('๐Ÿ“ฑ Mobile navigation test:', mobileNavigation); // Generate report const report = bundleMonitor.generateTestReport(); expect(report.errors.totalErrors).toBeLessThan(3); }); test('Cross-Browser Bundle Compatibility', async ({ page, browserName }) => { console.log(`๐ŸŒ Testing bundle compatibility on ${browserName}...`); const bundleMonitor = new BundledAssetsE2EBase(page); await bundleMonitor.enableAssetMonitoring(); // Test on trainer dashboard await page.goto(`${TEST_CONFIG.BASE_URL}/trainer/dashboard/`); await bundleMonitor.waitForBundleInitialization(); // Check browser-specific bundle loading const browserSupport = await page.evaluate((browser) => { const userAgent = navigator.userAgent; const isSafari = userAgent.includes('Safari') && !userAgent.includes('Chrome'); return { browser: browser, userAgent: userAgent, isSafari: isSafari, modernFeaturesSupported: { promises: typeof Promise !== 'undefined', arrow_functions: (() => true)() === true, const_let: typeof window.testConst === 'undefined', // const should be scoped templateLiterals: `test`.length === 4 }, jqueryLoaded: typeof window.jQuery !== 'undefined', bundleDataAvailable: typeof window.hvacBundleData !== 'undefined' }; }, browserName); console.log(`๐ŸŒ ${browserName} support:`, browserSupport); // All browsers should support modern features after bundling expect(browserSupport.modernFeaturesSupported.promises).toBe(true); expect(browserSupport.jqueryLoaded).toBe(true); // Safari should load Safari compatibility bundle const bundleValidation = bundleMonitor.validateExpectedBundles(TEST_CONFIG.EXPECTED_BUNDLES.TRAINER_DASHBOARD); if (browserName === 'webkit' || browserSupport.isSafari) { // Safari should have compatibility bundle const safariBundle = bundleMonitor.loadedBundles.has('hvac-safari-compat.bundle.js'); console.log(`๐ŸฆŽ Safari compatibility bundle loaded: ${safariBundle}`); } // Generate cross-browser report const report = bundleMonitor.generateTestReport(); console.log(`๐Ÿ“Š ${browserName} bundle report:`, report.bundleMonitoring); expect(report.errors.totalErrors).toBeLessThan(3); }); test('Bundle Performance Under Load', async ({ page }) => { console.log('โšก Testing bundle performance under load...'); const bundleMonitor = new BundledAssetsE2EBase(page); await bundleMonitor.enableAssetMonitoring(); // Navigate to heavy page (master trainer dashboard) const startTime = Date.now(); await page.goto(`${TEST_CONFIG.BASE_URL}/master-trainer/master-dashboard/`); await bundleMonitor.waitForBundleInitialization(); const loadTime = Date.now() - startTime; console.log(`๐Ÿ“Š Page loaded in ${loadTime}ms`); // Measure bundle loading performance const performanceMetrics = await page.evaluate(() => { const bundleResources = performance.getEntriesByType('resource') .filter(entry => entry.name.includes('.bundle.js')); return { bundleCount: bundleResources.length, totalBundleSize: bundleResources.reduce((sum, entry) => sum + (entry.transferSize || 0), 0), averageLoadTime: bundleResources.reduce((sum, entry) => sum + entry.duration, 0) / bundleResources.length, slowestBundle: bundleResources.reduce((slowest, entry) => entry.duration > (slowest?.duration || 0) ? entry : slowest, null), fastestBundle: bundleResources.reduce((fastest, entry) => entry.duration < (fastest?.duration || Infinity) ? entry : fastest, null) }; }); console.log('๐Ÿ“Š Performance metrics:', performanceMetrics); // Performance expectations expect(performanceMetrics.bundleCount).toBeGreaterThan(0); expect(performanceMetrics.averageLoadTime).toBeLessThan(2000); // 2 seconds average expect(loadTime).toBeLessThan(10000); // 10 seconds total // Test rapid navigation between pages const navigationTests = [ '/trainer/dashboard/', '/trainer/profile/', '/trainer/events/', '/master-trainer/master-dashboard/' ]; for (const url of navigationTests) { const navStart = Date.now(); await page.goto(`${TEST_CONFIG.BASE_URL}${url}`); await page.waitForLoadState('networkidle'); const navTime = Date.now() - navStart; console.log(`โšก Navigation to ${url}: ${navTime}ms`); expect(navTime).toBeLessThan(5000); // 5 seconds per navigation } // Generate performance report const report = bundleMonitor.generateTestReport(); expect(report.performance.errorRate).toBeLessThan(0.1); // Less than 10% error rate }); }); console.log('๐Ÿงช HVAC E2E Bundled Assets Test Suite Loaded'); console.log('๐ŸŽฏ Test Coverage:'); console.log(' โœ… Trainer Dashboard journey with bundle validation'); console.log(' โœ… Master Trainer administrative functions'); console.log(' โœ… Event creation workflow'); console.log(' โœ… Certificate generation functionality'); console.log(' ๐Ÿ“ฑ Mobile responsive bundle loading'); console.log(' ๐ŸŒ Cross-browser compatibility testing'); console.log(' โšก Performance testing under load');