import { test, expect, Page } from '@playwright/test'; /** * Comprehensive E2E Test Suite for HVAC Community Events Plugin * * This test suite covers all user-facing pages and navigation flows: * - Login flow * - All trainer pages (/trainer/ hierarchy) * - All master trainer pages (/master-trainer/ hierarchy) * - Navigation between pages * - Authentication and authorization * - Visual verification via screenshots */ // Test users configuration const TEST_USERS = { trainer: { username: 'test_trainer', password: 'password123', email: 'test_trainer@example.com' }, masterTrainer: { username: 'devadmin', password: 'devadmin123', email: 'admin@example.com' } }; // Page URLs to test const TRAINER_PAGES = [ { url: '/trainer/dashboard/', title: 'Trainer Dashboard', description: 'Personal trainer dashboard with stats' }, { url: '/trainer/my-profile/', title: 'Trainer Profile', description: 'View and edit trainer profile' }, { url: '/trainer/registration/', title: 'Trainer Registration', description: 'New trainer registration form' }, { url: '/trainer/documentation/', title: 'Trainer Documentation', description: 'Help and documentation' }, { url: '/trainer/event/manage/', title: 'Manage Event', description: 'Create and edit events' }, { url: '/trainer/event/summary/', title: 'Event Summary', description: 'Event details and attendee management' }, { url: '/trainer/email-attendees/', title: 'Email Attendees', description: 'Send emails to attendees' }, { url: '/trainer/certificate-reports/', title: 'Certificate Reports', description: 'View issued certificates' }, { url: '/trainer/generate-certificates/', title: 'Generate Certificates', description: 'Create new certificates' }, { url: '/trainer/communication-templates/', title: 'Communication Templates', description: 'Manage email templates' }, { url: '/trainer/communication-schedules/', title: 'Communication Schedules', description: 'Schedule automated communications' }, { url: '/trainer/attendee-profile/', title: 'Attendee Profile', description: 'View attendee profiles' } ]; const MASTER_TRAINER_PAGES = [ { url: '/master-trainer/dashboard/', title: 'Master Dashboard', description: 'System-wide analytics and management' }, { url: '/master-trainer/google-sheets/', title: 'Google Sheets Integration', description: 'Google Sheets integration' }, { url: '/master-trainer/certificate-fix/', title: 'Certificate System Diagnostics', description: 'Certificate diagnostics (restricted)' } ]; const AUTH_PAGES = [ { url: '/training-login/', title: 'Trainer Login', description: 'Login page for all trainers' } ]; // Helper functions async function loginAsUser(page: Page, userType: 'trainer' | 'masterTrainer') { const user = TEST_USERS[userType]; // Navigate to login page await page.goto('/training-login/'); await expect(page).toHaveTitle(/Login|Trainer/); // Fill login form await page.fill('input[name="log"], input[type="text"]', user.username); await page.fill('input[name="pwd"], input[type="password"]', user.password); // Submit login await page.click('input[type="submit"], button[type="submit"], .login-submit, #wp-submit'); // Wait for redirect to dashboard await page.waitForURL('**/trainer/dashboard/**', { timeout: 10000 }); // Verify successful login await expect(page.locator('body')).not.toContainText('Invalid username or password'); } async function takePageScreenshot(page: Page, testName: string, pageName: string) { await page.screenshot({ path: `test-results/screenshots/${testName}-${pageName}.png`, fullPage: true }); } async function verifyPageBasicElements(page: Page, expectedTitle: string, description: string) { // Wait for page to load await page.waitForLoadState('networkidle'); // Check page is accessible (not showing generic error) await expect(page.locator('body')).not.toContainText('Page not found'); await expect(page.locator('body')).not.toContainText('404'); await expect(page.locator('body')).not.toContainText('Fatal error'); // Check for basic WordPress structure const hasWpAdmin = await page.locator('#wpadminbar').isVisible().catch(() => false); const hasContent = await page.locator('.entry-content, .content, main, #content').isVisible().catch(() => false); // At least one should be visible expect(hasWpAdmin || hasContent).toBe(true); // Check for plugin-specific elements const hasPluginContent = await page.locator('[class*="hvac"], [id*="hvac"], [class*="community"], [class*="event"]').isVisible().catch(() => false); // Log findings for debugging console.log(`Page: ${expectedTitle} - Has WP Admin: ${hasWpAdmin}, Has Content: ${hasContent}, Has Plugin Content: ${hasPluginContent}`); } // Main test suites test.describe('HVAC Plugin Authentication', () => { test('Login page loads and displays correctly', async ({ page }) => { await page.goto('/training-login/'); // Take screenshot await takePageScreenshot(page, 'auth', 'login-page'); // Verify basic elements await verifyPageBasicElements(page, 'Trainer Login', 'Login page for all trainers'); // Check for login form elements const hasUsernameField = await page.locator('input[name="log"], input[type="text"]').isVisible().catch(() => false); const hasPasswordField = await page.locator('input[name="pwd"], input[type="password"]').isVisible().catch(() => false); const hasSubmitButton = await page.locator('input[type="submit"], button[type="submit"], .login-submit').isVisible().catch(() => false); expect(hasUsernameField || hasPasswordField || hasSubmitButton).toBe(true); console.log(`Login form elements - Username: ${hasUsernameField}, Password: ${hasPasswordField}, Submit: ${hasSubmitButton}`); }); test('Login flow works for trainer', async ({ page }) => { await loginAsUser(page, 'trainer'); // Should be redirected to dashboard expect(page.url()).toContain('/trainer/dashboard/'); // Take screenshot of successful login await takePageScreenshot(page, 'auth', 'trainer-logged-in'); await verifyPageBasicElements(page, 'Trainer Dashboard', 'Post-login dashboard'); }); test('Login flow works for master trainer', async ({ page }) => { await loginAsUser(page, 'masterTrainer'); // Should be redirected to dashboard expect(page.url()).toContain('/trainer/dashboard/'); // Take screenshot of successful login await takePageScreenshot(page, 'auth', 'master-trainer-logged-in'); await verifyPageBasicElements(page, 'Trainer Dashboard', 'Post-login dashboard for master trainer'); }); }); test.describe('HVAC Plugin Trainer Pages', () => { test.beforeEach(async ({ page }) => { await loginAsUser(page, 'trainer'); }); for (const pageConfig of TRAINER_PAGES) { test(`${pageConfig.title} page loads correctly`, async ({ page }) => { await page.goto(pageConfig.url); // Take screenshot for visual verification const screenshotName = pageConfig.title.toLowerCase().replace(/\s+/g, '-'); await takePageScreenshot(page, 'trainer', screenshotName); // Verify basic page elements await verifyPageBasicElements(page, pageConfig.title, pageConfig.description); // Check URL is correct expect(page.url()).toContain(pageConfig.url); console.log(`✓ Verified ${pageConfig.title} page at ${pageConfig.url}`); }); } }); test.describe('HVAC Plugin Master Trainer Pages', () => { test.beforeEach(async ({ page }) => { await loginAsUser(page, 'masterTrainer'); }); for (const pageConfig of MASTER_TRAINER_PAGES) { test(`${pageConfig.title} page loads correctly`, async ({ page }) => { await page.goto(pageConfig.url); // Take screenshot for visual verification const screenshotName = pageConfig.title.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, ''); await takePageScreenshot(page, 'master-trainer', screenshotName); // Verify basic page elements await verifyPageBasicElements(page, pageConfig.title, pageConfig.description); // Check URL is correct expect(page.url()).toContain(pageConfig.url); console.log(`✓ Verified ${pageConfig.title} page at ${pageConfig.url}`); }); } }); test.describe('HVAC Plugin Navigation', () => { test('Dashboard navigation buttons work for trainer', async ({ page }) => { await loginAsUser(page, 'trainer'); // Navigate to dashboard await page.goto('/trainer/dashboard/'); await takePageScreenshot(page, 'navigation', 'trainer-dashboard-before-navigation'); // Test navigation to key pages const navigationTests = [ { selector: 'a[href*="manage"], .create-event, [href*="event/manage"]', expectedUrl: '/trainer/event/manage/' }, { selector: 'a[href*="generate-certificates"], .generate-certificates', expectedUrl: '/trainer/generate-certificates/' }, { selector: 'a[href*="certificate-reports"], .certificate-reports', expectedUrl: '/trainer/certificate-reports/' }, { selector: 'a[href*="my-profile"], .profile, [href*="trainer-profile"]', expectedUrl: '/trainer/my-profile/' } ]; for (const navTest of navigationTests) { // Go back to dashboard await page.goto('/trainer/dashboard/'); // Look for navigation element const navElement = await page.locator(navTest.selector).first(); const isVisible = await navElement.isVisible().catch(() => false); if (isVisible) { await navElement.click(); await page.waitForLoadState('networkidle'); // Verify we navigated correctly expect(page.url()).toContain(navTest.expectedUrl); // Take screenshot const pageName = navTest.expectedUrl.split('/').filter(s => s).pop() || 'unknown'; await takePageScreenshot(page, 'navigation', `navigated-to-${pageName}`); console.log(`✓ Navigation to ${navTest.expectedUrl} successful`); } else { console.log(`! Navigation element not found for ${navTest.expectedUrl}: ${navTest.selector}`); } } }); test('Master trainer can access restricted pages', async ({ page }) => { await loginAsUser(page, 'masterTrainer'); // Navigate to master trainer specific pages await page.goto('/master-trainer/dashboard/'); await takePageScreenshot(page, 'navigation', 'master-dashboard-access'); // Verify access to Google Sheets page await page.goto('/master-trainer/google-sheets/'); await takePageScreenshot(page, 'navigation', 'google-sheets-access'); // These should not show access denied await expect(page.locator('body')).not.toContainText('Access denied'); await expect(page.locator('body')).not.toContainText('Unauthorized'); console.log('✓ Master trainer can access restricted pages'); }); test('Regular trainer cannot access master trainer pages', async ({ page }) => { await loginAsUser(page, 'trainer'); // Try to access master trainer pages - should be redirected or show error await page.goto('/master-trainer/dashboard/'); const isAccessDenied = await page.locator('body').textContent().then(text => text?.includes('Access denied') || text?.includes('Unauthorized') || text?.includes('Permission denied') || page.url().includes('/trainer/dashboard/') // Redirected back ); await takePageScreenshot(page, 'navigation', 'trainer-master-access-denied'); // Should either show access denied or redirect to trainer dashboard expect(isAccessDenied).toBe(true); console.log('✓ Regular trainer properly denied access to master trainer pages'); }); }); test.describe('HVAC Plugin Legacy URL Redirects', () => { test.beforeEach(async ({ page }) => { await loginAsUser(page, 'trainer'); }); test('Legacy URLs redirect to new hierarchical structure', async ({ page }) => { const legacyRedirects = [ { from: '/hvac-dashboard/', to: '/trainer/dashboard/' }, { from: '/manage-event/', to: '/trainer/event/manage/' }, { from: '/trainer-profile/', to: '/trainer/my-profile/' }, { from: '/certificate-reports/', to: '/trainer/certificate-reports/' }, { from: '/generate-certificates/', to: '/trainer/generate-certificates/' } ]; for (const redirect of legacyRedirects) { await page.goto(redirect.from); await page.waitForLoadState('networkidle'); // Should be redirected to new URL expect(page.url()).toContain(redirect.to); await takePageScreenshot(page, 'redirects', `legacy-${redirect.from.replace(/[^a-z0-9]/g, '-')}`); console.log(`✓ Legacy URL ${redirect.from} redirects to ${redirect.to}`); } }); }); test.describe('HVAC Plugin Visual Verification', () => { test('Generate comprehensive visual documentation', async ({ page }) => { // Login as trainer await loginAsUser(page, 'trainer'); // Take screenshot of each major page for documentation const documentationPages = [ '/trainer/dashboard/', '/trainer/event/manage/', '/trainer/my-profile/', '/trainer/certificate-reports/', '/trainer/generate-certificates/' ]; for (const pageUrl of documentationPages) { await page.goto(pageUrl); await page.waitForLoadState('networkidle'); const pageName = pageUrl.split('/').filter(s => s).pop() || 'unknown'; await takePageScreenshot(page, 'documentation', `trainer-${pageName}`); } // Login as master trainer for master pages await loginAsUser(page, 'masterTrainer'); const masterPages = [ '/master-trainer/dashboard/', '/master-trainer/google-sheets/' ]; for (const pageUrl of masterPages) { await page.goto(pageUrl); await page.waitForLoadState('networkidle'); const pageName = pageUrl.split('/').filter(s => s).pop() || 'unknown'; await takePageScreenshot(page, 'documentation', `master-${pageName}`); } console.log('✓ Generated comprehensive visual documentation'); }); });