#!/usr/bin/env node /** * Comprehensive E2E Test for HVAC Event Edit Functionality * Tests complete event creation, editing, and field population * * @package HVAC_Community_Events * @version 2.0.0 */ const { chromium } = require('@playwright/test'); const fs = require('fs').promises; const path = require('path'); // Configuration const CONFIG = { baseUrl: 'https://upskill-staging.measurequick.com', credentials: { trainer: { email: 'test_trainer@example.com', password: 'TestTrainer123!' }, master: { email: 'test_master@example.com', password: 'TestMaster123!' }, admin: { email: 'ben@upskillhvac.com', password: process.env.ADMIN_PASSWORD || '' } }, screenshotDir: 'screenshots/e2e-test', timeout: 60000 }; // Test data const TEST_EVENT = { title: `E2E Test Event ${Date.now()}`, description: 'This is a comprehensive E2E test event for verifying all functionality.', venue: 'Dallas Training Center', organizer: 'HVAC Training Solutions', cost: '399', startDate: '2025-09-01', endDate: '2025-09-02', startTime: '09:00', endTime: '17:00', website: 'https://example.com/test-event', maxAttendees: '30' }; // Test results tracking const RESULTS = { startTime: Date.now(), tests: [], passed: 0, failed: 0, screenshots: [] }; // Helper functions async function takeScreenshot(page, name) { try { await fs.mkdir(CONFIG.screenshotDir, { recursive: true }); const filename = `${name}-${Date.now()}.png`; const filepath = path.join(CONFIG.screenshotDir, filename); await page.screenshot({ path: filepath, fullPage: true }); RESULTS.screenshots.push(filepath); console.log(`šŸ“ø Screenshot: ${filename}`); return filepath; } catch (error) { console.log(`āš ļø Screenshot failed: ${error.message}`); } } async function logTest(name, status, details = '') { const icon = status === 'passed' ? 'āœ…' : 'āŒ'; console.log(`${icon} ${name}: ${status.toUpperCase()} ${details}`); RESULTS.tests.push({ name, status, details, timestamp: Date.now() }); if (status === 'passed') { RESULTS.passed++; } else { RESULTS.failed++; } } async function login(page, credentials) { try { console.log('\nšŸ” Logging in...'); await page.goto(`${CONFIG.baseUrl}/wp-login.php`); await page.fill('#user_login', credentials.email); await page.fill('#user_pass', credentials.password); await page.click('#wp-submit'); // Wait for redirect await page.waitForURL(url => { const urlString = typeof url === 'string' ? url : url.toString(); return !urlString.includes('wp-login'); }, { timeout: 10000 }); const currentUrl = page.url(); if (currentUrl.includes('dashboard') || currentUrl.includes('admin')) { await logTest('Login', 'passed', credentials.email); return true; } else { await logTest('Login', 'failed', 'Unexpected redirect'); return false; } } catch (error) { await logTest('Login', 'failed', error.message); return false; } } async function testWordPressAdmin(page) { console.log('\nšŸ“Š Testing WordPress Admin Event Management...'); try { // Navigate to events list await page.goto(`${CONFIG.baseUrl}/wp-admin/edit.php?post_type=tribe_events`); await page.waitForLoadState('domcontentloaded'); await takeScreenshot(page, 'admin-events-list'); // Count existing events const eventRows = await page.$$('tbody#the-list tr'); console.log(`Found ${eventRows.length} existing events`); if (eventRows.length > 0) { await logTest('Admin Events List', 'passed', `${eventRows.length} events found`); // Test editing first event const editLink = await page.$('tbody#the-list tr:first-child .row-actions .edit a'); if (editLink) { await editLink.click(); await page.waitForLoadState('networkidle'); await takeScreenshot(page, 'admin-edit-form'); // Check if fields are populated const titleField = await page.$('#title'); if (titleField) { const currentTitle = await titleField.inputValue(); console.log(`Current title: ${currentTitle}`); // Update title const newTitle = currentTitle + ' (Updated E2E)'; await titleField.fill(newTitle); // Check other fields const fields = { 'Start Date': '#EventStartDate', 'End Date': '#EventEndDate', 'Cost': '#EventCost', 'Venue': '#venue-name, select[name="venue[VenueID]"]' }; for (const [name, selector] of Object.entries(fields)) { const field = await page.$(selector); if (field) { const value = await field.inputValue().catch(() => ''); console.log(` ${name}: ${value || 'N/A'}`); } } // Save changes const updateButton = await page.$('#publish'); if (updateButton) { await updateButton.click(); await page.waitForSelector('.notice-success, .updated', { timeout: 10000 }); await takeScreenshot(page, 'admin-updated'); await logTest('Admin Event Edit', 'passed', 'Event updated successfully'); } } else { await logTest('Admin Event Edit', 'failed', 'Title field not found'); } } } else { await logTest('Admin Events List', 'failed', 'No events found'); } // Test creating new event console.log('\nšŸ“ Testing event creation in admin...'); await page.goto(`${CONFIG.baseUrl}/wp-admin/post-new.php?post_type=tribe_events`); await page.waitForLoadState('domcontentloaded'); await takeScreenshot(page, 'admin-new-event'); // Fill new event form const titleField = await page.$('#title'); if (titleField) { await titleField.fill(TEST_EVENT.title); // Fill description const contentFrame = await page.$('#content_ifr'); if (contentFrame) { const frame = await contentFrame.contentFrame(); await frame.fill('#tinymce', TEST_EVENT.description); } else { const contentArea = await page.$('#content'); if (contentArea) { await contentArea.fill(TEST_EVENT.description); } } // Set dates const startDate = await page.$('#EventStartDate'); if (startDate) await startDate.fill(TEST_EVENT.startDate); const endDate = await page.$('#EventEndDate'); if (endDate) await endDate.fill(TEST_EVENT.endDate); // Set cost const cost = await page.$('#EventCost'); if (cost) await cost.fill(TEST_EVENT.cost); // Publish const publishButton = await page.$('#publish'); if (publishButton) { await publishButton.click(); await page.waitForSelector('.notice-success, .updated', { timeout: 10000 }); await takeScreenshot(page, 'admin-created'); await logTest('Admin Event Creation', 'passed', 'New event created'); } } else { await logTest('Admin Event Creation', 'failed', 'Form fields not found'); } } catch (error) { await logTest('WordPress Admin Test', 'failed', error.message); await takeScreenshot(page, 'admin-error'); } } async function testTrainerPages(page) { console.log('\nšŸŽÆ Testing HVAC Trainer Event Pages...'); try { // Navigate to trainer dashboard await page.goto(`${CONFIG.baseUrl}/trainer/dashboard/`); await page.waitForLoadState('domcontentloaded'); await takeScreenshot(page, 'trainer-dashboard'); const dashboardVisible = await page.locator('.hvac-dashboard-header, h1').first().isVisible(); if (dashboardVisible) { await logTest('Trainer Dashboard', 'passed'); } else { await logTest('Trainer Dashboard', 'failed', 'Dashboard not visible'); } // Test events list await page.goto(`${CONFIG.baseUrl}/trainer/events/`); await page.waitForLoadState('domcontentloaded'); await takeScreenshot(page, 'trainer-events-list'); // Check page content const pageContent = await page.locator('body').textContent(); if (pageContent.includes('404')) { await logTest('Trainer Events List', 'failed', '404 error'); } else if (pageContent.includes('event') || pageContent.includes('Event')) { await logTest('Trainer Events List', 'passed'); // Look for edit links const editLinks = await page.$$('a[href*="edit"]'); if (editLinks.length > 0) { console.log(`Found ${editLinks.length} edit links`); // Click first edit link await editLinks[0].click(); await page.waitForLoadState('networkidle'); await takeScreenshot(page, 'trainer-edit-page'); // Check if on edit page const editPageContent = await page.locator('body').textContent(); if (editPageContent.includes('Edit') || editPageContent.includes('Update')) { await logTest('Trainer Event Edit Page', 'passed'); } else { await logTest('Trainer Event Edit Page', 'failed', 'Edit form not found'); } } } else { await logTest('Trainer Events List', 'failed', 'No event content'); } // Test event creation page await page.goto(`${CONFIG.baseUrl}/trainer/events/create/`); await page.waitForLoadState('domcontentloaded'); await takeScreenshot(page, 'trainer-create-page'); const createPageContent = await page.locator('body').textContent(); if (createPageContent.includes('404')) { await logTest('Trainer Create Event Page', 'failed', '404 error'); } else { await logTest('Trainer Create Event Page', 'passed'); } } catch (error) { await logTest('Trainer Pages Test', 'failed', error.message); await takeScreenshot(page, 'trainer-error'); } } async function testCommunityPages(page) { console.log('\n🌐 Testing TEC Community Pages...'); const communityUrls = [ '/community/', '/community/add/', '/community/list/', '/events/community/', '/events/community/add/', '/events/community/list/' ]; for (const url of communityUrls) { try { await page.goto(`${CONFIG.baseUrl}${url}`); await page.waitForLoadState('domcontentloaded'); const content = await page.locator('body').textContent(); if (content.includes('404') || content.includes('not found')) { await logTest(`Community ${url}`, 'failed', '404'); } else if (content.includes('login') || content.includes('Login')) { await logTest(`Community ${url}`, 'failed', 'Login required'); } else { await logTest(`Community ${url}`, 'passed'); } } catch (error) { await logTest(`Community ${url}`, 'failed', error.message); } } } async function generateReport() { const duration = ((Date.now() - RESULTS.startTime) / 1000).toFixed(1); const successRate = RESULTS.tests.length > 0 ? ((RESULTS.passed / RESULTS.tests.length) * 100).toFixed(1) : 0; let report = `# HVAC Event Edit E2E Test Report\n\n`; report += `**Date:** ${new Date().toISOString()}\n`; report += `**Environment:** ${CONFIG.baseUrl}\n`; report += `**Duration:** ${duration} seconds\n\n`; report += `## Summary\n\n`; report += `- **Total Tests:** ${RESULTS.tests.length}\n`; report += `- **Passed:** ${RESULTS.passed} āœ…\n`; report += `- **Failed:** ${RESULTS.failed} āŒ\n`; report += `- **Success Rate:** ${successRate}%\n\n`; report += `## Test Results\n\n`; report += `| Test | Status | Details |\n`; report += `|------|--------|---------|\n`; for (const test of RESULTS.tests) { const icon = test.status === 'passed' ? 'āœ…' : 'āŒ'; report += `| ${test.name} | ${icon} ${test.status} | ${test.details} |\n`; } report += `\n## Screenshots\n\n`; report += `${RESULTS.screenshots.length} screenshots captured:\n\n`; for (const screenshot of RESULTS.screenshots) { report += `- ${path.basename(screenshot)}\n`; } report += `\n## Assessment\n\n`; if (successRate >= 80) { report += `### āœ… SYSTEM READY\n\n`; report += `The event editing functionality is working well with ${successRate}% success rate.\n`; } else if (successRate >= 60) { report += `### āš ļø PARTIAL FUNCTIONALITY\n\n`; report += `Some features are working but improvements needed. Success rate: ${successRate}%\n`; } else { report += `### āŒ NEEDS ATTENTION\n\n`; report += `Significant issues detected. Success rate: ${successRate}%\n`; } // Save report await fs.mkdir('reports', { recursive: true }); const reportFile = `reports/e2e-test-report-${Date.now()}.md`; await fs.writeFile(reportFile, report); return { reportFile, successRate }; } // Main test execution async function runFullE2ETest() { console.log('šŸš€ HVAC EVENT EDIT FULL E2E TEST'); console.log('═'.repeat(60)); console.log(`Environment: ${CONFIG.baseUrl}`); console.log(`Time: ${new Date().toLocaleString()}`); console.log('═'.repeat(60)); const browser = await chromium.launch({ headless: true, timeout: CONFIG.timeout }); const context = await browser.newContext({ viewport: { width: 1280, height: 720 } }); const page = await context.newPage(); try { // Test 1: Admin functionality (if password provided) if (CONFIG.credentials.admin.password) { console.log('\nšŸ‘¤ Testing with Admin Account...'); if (await login(page, CONFIG.credentials.admin)) { await testWordPressAdmin(page); } } else { console.log('\nāš ļø Skipping admin tests (no password provided)'); } // Test 2: Trainer functionality console.log('\nšŸ‘¤ Testing with Trainer Account...'); if (await login(page, CONFIG.credentials.trainer)) { await testTrainerPages(page); await testCommunityPages(page); } // Test 3: Master trainer functionality console.log('\nšŸ‘¤ Testing with Master Trainer Account...'); if (await login(page, CONFIG.credentials.master)) { await testTrainerPages(page); } } catch (error) { console.error('\nāŒ Fatal error:', error.message); await takeScreenshot(page, 'fatal-error'); } finally { await browser.close(); } // Generate final report console.log('\n' + '═'.repeat(60)); console.log('šŸ“Š GENERATING FINAL REPORT'); console.log('═'.repeat(60)); const { reportFile, successRate } = await generateReport(); console.log(`\nTotal Tests: ${RESULTS.tests.length}`); console.log(`āœ… Passed: ${RESULTS.passed}`); console.log(`āŒ Failed: ${RESULTS.failed}`); console.log(`Success Rate: ${successRate}%`); console.log(`\nšŸ“„ Full report: ${reportFile}`); console.log(`šŸ“ø Screenshots: ${CONFIG.screenshotDir}/`); if (successRate >= 80) { console.log('\nšŸŽ‰ EVENT EDITING FUNCTIONALITY VERIFIED!'); } else if (successRate >= 60) { console.log('\nāš ļø PARTIAL SUCCESS - Some features need attention'); } else { console.log('\nāŒ SIGNIFICANT ISSUES - Review needed'); } console.log('═'.repeat(60)); process.exit(RESULTS.failed > 3 ? 1 : 0); } // Handle command line arguments const args = process.argv.slice(2); if (args.includes('--help')) { console.log(` HVAC Event Edit E2E Test Usage: node test-full-event-e2e.js [options] Options: --admin-pass PASSWORD Admin password for full testing --help Show this help message Examples: node test-full-event-e2e.js node test-full-event-e2e.js --admin-pass MyPassword123 ADMIN_PASSWORD=MyPassword123 node test-full-event-e2e.js `); process.exit(0); } // Check for admin password in arguments const passIndex = args.indexOf('--admin-pass'); if (passIndex !== -1 && args[passIndex + 1]) { CONFIG.credentials.admin.password = args[passIndex + 1]; } // Run the tests runFullE2ETest().catch(error => { console.error('Test execution failed:', error); process.exit(1); });