/** * Comprehensive E2E Tests for HVAC Plugin Functionality * * Tests all recent fixes and enhancements: * 1. Certificate Reports page functionality * 2. Generate Certificates page functionality * 3. Navigation updates (no My Events links) * 4. Create Event page behavior * 5. PHP error monitoring */ import { test, expect } from './fixtures/auth'; import { CommonActions } from './utils/common-actions'; test.describe('HVAC Plugin Comprehensive Functionality Tests', () => { test.beforeEach(async ({ page }) => { // Monitor for PHP errors throughout all tests page.on('console', (msg) => { if (msg.type() === 'error' && msg.text().includes('PHP')) { console.error('PHP Error detected:', msg.text()); } }); }); test('Dashboard Navigation - Verify correct links and no My Events', async ({ authenticatedPage: page }) => { test.setTimeout(30000); const actions = new CommonActions(page); await actions.navigateAndWait('/hvac-dashboard/'); await actions.screenshot('dashboard-navigation'); // Check that My Events links are removed const myEventsLinks = await page.locator('a[href*="my-events"]').count(); expect(myEventsLinks).toBe(0); console.log('✅ No My Events links found on dashboard'); // Verify all navigation buttons are present const navButtons = [ { text: 'Create Event', exists: true }, { text: 'Certificate Reports', exists: true }, { text: 'Generate Certificates', exists: true }, { text: 'View Profile', exists: true }, { text: 'Help', exists: true }, { text: 'My Events', exists: false } // Should NOT exist ]; for (const button of navButtons) { const count = await page.locator(`.hvac-dashboard-nav a:has-text("${button.text}")`).count(); if (button.exists) { expect(count).toBeGreaterThan(0); console.log(`✅ ${button.text} button found`); } else { expect(count).toBe(0); console.log(`✅ ${button.text} button correctly absent`); } } }); test('Certificate Reports - Full functionality test', async ({ authenticatedPage: page }) => { test.setTimeout(45000); const actions = new CommonActions(page); await actions.navigateAndWait('/certificate-reports/'); await actions.screenshot('certificate-reports-loaded'); // Check page elements await expect(page.locator('h1').first()).toContainText('Certificate Reports'); // Verify statistics section const statsSection = page.locator('.hvac-certificate-stats'); await expect(statsSection).toBeVisible(); const statCards = await page.locator('.hvac-stat-card').count(); expect(statCards).toBe(4); // Total, Active, Revoked, Emailed console.log('✅ All 4 statistics cards present'); // Check each stat card has a value const statValues = await page.locator('.hvac-stat-value').allTextContents(); expect(statValues.length).toBe(4); statValues.forEach((value, index) => { expect(value).toMatch(/^\d+$/); // Should be a number }); console.log(`✅ Statistics values: Total=${statValues[0]}, Active=${statValues[1]}, Revoked=${statValues[2]}, Emailed=${statValues[3]}`); // Verify filters section const filtersSection = page.locator('.hvac-filters-section'); await expect(filtersSection).toBeVisible(); // Check event filter const eventFilter = page.locator('#filter_event'); await expect(eventFilter).toBeVisible(); const eventOptions = await eventFilter.locator('option').count(); expect(eventOptions).toBeGreaterThan(0); console.log(`✅ Event filter has ${eventOptions} options`); // Check status filter const statusFilter = page.locator('#filter_status'); await expect(statusFilter).toBeVisible(); const statusOptions = await statusFilter.locator('option').count(); expect(statusOptions).toBe(3); // All, Active, Revoked console.log('✅ Status filter has correct options'); // Test filter functionality if (eventOptions > 1) { await eventFilter.selectOption({ index: 1 }); await page.click('button:has-text("Apply Filters")'); await page.waitForLoadState('networkidle'); await actions.screenshot('certificate-reports-filtered'); console.log('✅ Filter functionality working'); } // Check certificate display area const hasTable = await page.locator('.hvac-certificate-table').isVisible().catch(() => false); const hasNoResults = await page.locator('.hvac-no-certificates').isVisible().catch(() => false); expect(hasTable || hasNoResults).toBe(true); console.log(`✅ Certificate display area present (table: ${hasTable}, no results: ${hasNoResults})`); }); test('Generate Certificates - Complete workflow test', async ({ authenticatedPage: page }) => { test.setTimeout(60000); const actions = new CommonActions(page); await actions.navigateAndWait('/generate-certificates/'); await actions.screenshot('generate-certificates-initial'); // Verify page structure await expect(page.locator('h1').first()).toContainText('Generate Certificates'); // Step 1: Event Selection const eventSelect = page.locator('#event_id'); await expect(eventSelect).toBeVisible(); const eventOptions = await eventSelect.locator('option').count(); expect(eventOptions).toBeGreaterThan(1); console.log(`✅ Event dropdown has ${eventOptions} options`); // Select first real event const firstEventValue = await eventSelect.locator('option').nth(1).getAttribute('value'); await eventSelect.selectOption({ value: firstEventValue! }); console.log(`✅ Selected event ID: ${firstEventValue}`); // Wait for page reload with event parameter await page.waitForURL(/event_id=/); await page.waitForLoadState('networkidle'); await actions.screenshot('generate-certificates-event-selected'); // Step 2: Verify attendees section const attendeesSection = page.locator('#step-select-attendees'); await expect(attendeesSection).toBeVisible(); console.log('✅ Attendees section visible'); // Check form elements const certificateForm = page.locator('#generate-certificates-form'); await expect(certificateForm).toBeVisible(); // Verify nonce field exists (security) const nonceField = await page.locator('input[name="hvac_certificate_nonce"]').count(); expect(nonceField).toBe(1); console.log('✅ Security nonce field present'); // Check attendee display const hasAttendeesTable = await page.locator('.hvac-attendees-table').isVisible().catch(() => false); const hasEmptyMessage = await page.locator('.hvac-empty-state').isVisible().catch(() => false); expect(hasAttendeesTable || hasEmptyMessage).toBe(true); console.log(`✅ Attendee display present (table: ${hasAttendeesTable}, empty: ${hasEmptyMessage})`); if (hasAttendeesTable) { // Verify table structure await expect(page.locator('.hvac-attendees-table thead')).toBeVisible(); await expect(page.locator('.hvac-attendees-table tbody')).toBeVisible(); // Check action buttons const actionButtons = [ '#select-all-attendees', '#select-checked-in', '#deselect-all-attendees' ]; for (const button of actionButtons) { await expect(page.locator(button)).toBeVisible(); } console.log('✅ All attendee action buttons present'); // Test select all functionality await page.click('#select-all-attendees'); const checkedCount = await page.locator('.attendee-checkbox:checked').count(); expect(checkedCount).toBeGreaterThan(0); console.log(`✅ Select all functionality working (${checkedCount} selected)`); // Check generate button const generateButton = page.locator('button[name="generate_certificates"]'); await expect(generateButton).toBeVisible(); await expect(generateButton).toHaveText('Generate Certificates'); console.log('✅ Generate certificates button present'); } // Verify certificate preview section const previewSection = page.locator('.hvac-certificate-preview'); await expect(previewSection).toBeVisible(); console.log('✅ Certificate preview section present'); }); test('Create Event page - Verify shortcode handling', async ({ authenticatedPage: page }) => { test.setTimeout(30000); const actions = new CommonActions(page); await actions.navigateAndWait('/manage-event/'); await actions.screenshot('create-event-page'); // Check page title await expect(page.locator('h1').first()).toContainText(/Create.*Event|Manage.*Event/i); // Get page content const bodyText = await page.locator('body').textContent(); // Check for shortcode or form if (bodyText?.includes('[tribe_community_events')) { console.log('✅ Page shows TEC shortcode (Community Events not active)'); expect(bodyText).toContain('[tribe_community_events'); // Verify it's displayed as content, not an error const hasError = await page.locator('.error, .hvac-error').count(); expect(hasError).toBe(0); console.log('✅ No error messages displayed'); } else { // Check for any form that would allow event creation const forms = await page.locator('form').count(); const hasEventFields = await page.locator('input[name*="event"], input[name*="Event"], #event_title, #post_title').count(); console.log(`✅ Page has ${forms} forms and ${hasEventFields} event-related fields`); if (forms > 0) { expect(hasEventFields).toBeGreaterThan(0); console.log('✅ Event creation form detected'); } } }); test('Trainer Profile - Verify navigation updates', async ({ authenticatedPage: page }) => { test.setTimeout(30000); const actions = new CommonActions(page); await actions.navigateAndWait('/trainer-profile/'); await actions.screenshot('trainer-profile-navigation'); // Check no My Events links const myEventsLinks = await page.locator('a[href*="my-events"]').count(); expect(myEventsLinks).toBe(0); console.log('✅ No My Events links on trainer profile'); // Verify Certificate Reports link exists const certReportsLink = await page.locator('a:has-text("Certificate Reports")').count(); expect(certReportsLink).toBeGreaterThan(0); console.log('✅ Certificate Reports link present on trainer profile'); // Check other navigation elements const expectedLinks = ['Dashboard', 'Create Event', 'Certificate Reports', 'Help', 'Logout']; for (const linkText of expectedLinks) { const linkExists = await page.locator(`.hvac-dashboard-nav a:has-text("${linkText}")`).count() > 0; if (linkExists) { console.log(`✅ ${linkText} link found`); } } }); test('My Events page removal verification', async ({ authenticatedPage: page }) => { test.setTimeout(20000); const actions = new CommonActions(page); // Attempt to navigate to my-events const response = await page.goto('/my-events/', { waitUntil: 'networkidle' }); const status = response?.status() || 0; const finalUrl = page.url(); console.log(`My Events page status: ${status}`); console.log(`Final URL: ${finalUrl}`); // The page might still exist but should not be linked anywhere if (status === 200 && finalUrl.includes('/my-events/')) { console.log('⚠️ My Events page still exists but is not linked in navigation'); // Verify it's not linked from any main pages const pagesToCheck = ['/hvac-dashboard/', '/trainer-profile/']; for (const pageUrl of pagesToCheck) { await actions.navigateAndWait(pageUrl); const myEventsLinksOnPage = await page.locator('a[href*="my-events"]').count(); expect(myEventsLinksOnPage).toBe(0); console.log(`✅ No My Events links on ${pageUrl}`); } } else { console.log('✅ My Events page not accessible or redirects'); } }); test('PHP Error Monitoring - No errors across all pages', async ({ authenticatedPage: page }) => { test.setTimeout(45000); const actions = new CommonActions(page); const phpErrors: string[] = []; // Enhanced error monitoring page.on('console', (msg) => { if (msg.type() === 'error') { const text = msg.text(); if (text.includes('PHP') || text.includes('Fatal') || text.includes('Warning') || text.includes('Notice')) { phpErrors.push(`[${msg.type()}] ${text}`); } } }); // Test all main pages const pagesToTest = [ { url: '/hvac-dashboard/', name: 'Dashboard' }, { url: '/certificate-reports/', name: 'Certificate Reports' }, { url: '/generate-certificates/', name: 'Generate Certificates' }, { url: '/manage-event/', name: 'Create Event' }, { url: '/trainer-profile/', name: 'Trainer Profile' } ]; for (const pageInfo of pagesToTest) { console.log(`Testing ${pageInfo.name}...`); await actions.navigateAndWait(pageInfo.url); await page.waitForTimeout(1000); // Give time for any errors to appear // Additional test for Generate Certificates with event selection if (pageInfo.url === '/generate-certificates/') { const eventOptions = await page.locator('#event_id option').count(); if (eventOptions > 1) { await page.selectOption('#event_id', { index: 1 }); await page.waitForTimeout(2000); } } } // Report results if (phpErrors.length > 0) { console.error('❌ PHP Errors detected:'); phpErrors.forEach(error => console.error(error)); expect(phpErrors.length).toBe(0); } else { console.log('✅ No PHP errors detected across all pages'); } }); test('Complete User Journey - Event to Certificate', async ({ authenticatedPage: page }) => { test.setTimeout(60000); const actions = new CommonActions(page); console.log('Starting complete user journey test...'); // 1. Dashboard await actions.navigateAndWait('/hvac-dashboard/'); await expect(page.locator('h1:has-text("Dashboard")')).toBeVisible(); console.log('✅ Step 1: Dashboard loaded'); // 2. Navigate to Certificate Reports await page.click('a:has-text("Certificate Reports")'); await page.waitForLoadState('networkidle'); await expect(page.locator('h1:has-text("Certificate Reports")')).toBeVisible(); const initialStats = await page.locator('.hvac-stat-value').first().textContent(); console.log(`✅ Step 2: Certificate Reports loaded (Total certificates: ${initialStats})`); // 3. Navigate to Generate Certificates await page.click('a:has-text("Generate Certificates")'); await page.waitForLoadState('networkidle'); await expect(page.locator('h1:has-text("Generate Certificates")')).toBeVisible(); console.log('✅ Step 3: Generate Certificates loaded'); // 4. Select an event const eventOptions = await page.locator('#event_id option').count(); if (eventOptions > 1) { await page.selectOption('#event_id', { index: 1 }); await page.waitForURL(/event_id=/); await expect(page.locator('#step-select-attendees')).toBeVisible(); console.log('✅ Step 4: Event selected and attendees loaded'); } // 5. Return to dashboard await page.click('a[href*="hvac-dashboard"]').first(); await page.waitForLoadState('networkidle'); await expect(page.locator('h1:has-text("Dashboard")')).toBeVisible(); console.log('✅ Step 5: Returned to dashboard'); // 6. Check Create Event await page.click('a:has-text("Create Event")'); await page.waitForLoadState('networkidle'); await expect(page.locator('h1').first()).toContainText(/Event/i); console.log('✅ Step 6: Create Event page accessed'); console.log('✅ Complete user journey test passed!'); }); });