import { STAGING_URL, PATHS, TIMEOUTS } from './config/staging-config'; import { test, expect, Page } from '@playwright/test'; import { LoginPage } from './pages/LoginPage'; import { DashboardPage } from './pages/DashboardPage'; import { ProfilePage } from './pages/ProfilePage'; import { EventSummaryPage } from './pages/EventSummaryPage'; import { ModifyEventPage } from './pages/ModifyEventPage'; import { CreateEventPage } from './pages/CreateEventPage'; import fs from 'fs'; import path from 'path'; // Base URL for the staging environment // STAGING_URL is now imported from config // Test user credentials const TEST_USER = { username: 'test_trainer', password: 'Test123!' }; // Output directory for screenshots const SCREENSHOTS_DIR = path.join(__dirname, 'test-results', 'verification-screenshots'); // Ensure screenshots directory exists if (!fs.existsSync(SCREENSHOTS_DIR)) { fs.mkdirSync(SCREENSHOTS_DIR, { recursive: true }); } // Helper function to take and save screenshots with a timestamp async function saveScreenshot(page: Page, name: string): Promise { const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const filename = `${name}-${timestamp}.png`; const filepath = path.join(SCREENSHOTS_DIR, filename); await page.screenshot({ path: filepath, fullPage: true }); return filepath; } // Helper function to check basic page content and get UI element count async function checkPageContent(page: Page): Promise<{ hasErrors: boolean, errorMessages: string[], elementCounts: { [key: string]: number } }> { const result = { hasErrors: false, errorMessages: [], elementCounts: { headings: 0, buttons: 0, links: 0, inputs: 0, tables: 0, images: 0 } }; // Check for common error messages const errorElements = [ 'text="Error"', 'text="404"', 'text="Page not found"', 'text="Access denied"', '.error-message', '.notice-error' ]; for (const selector of errorElements) { const errorElement = page.locator(selector); if (await errorElement.count() > 0) { result.hasErrors = true; const errorText = await errorElement.textContent() || 'Error detected'; result.errorMessages.push(errorText.trim()); } } // Count UI elements result.elementCounts.headings = await page.locator('h1, h2, h3, h4, h5, h6').count(); result.elementCounts.buttons = await page.locator('button, input[type="submit"], .button, a.btn').count(); result.elementCounts.links = await page.locator('a').count(); result.elementCounts.inputs = await page.locator('input, textarea, select').count(); result.elementCounts.tables = await page.locator('table').count(); result.elementCounts.images = await page.locator('img').count(); return result; } test.describe('HVAC Community Events Plugin Page Verification', () => { let loginPage: LoginPage; test.beforeEach(async ({ page }) => { loginPage = new LoginPage(page); // Increase timeouts for potentially slow pages page.context().setDefaultNavigationTimeout(60000); // Base URL setup await page.goto(STAGING_URL); }); test('1. Verify Community Login Page', async ({ page }) => { // Navigate to login page await loginPage.navigateToLogin(); // Take screenshot const screenshotPath = await saveScreenshot(page, 'login-page'); // Verify URL await expect(page).toHaveURL(/.*community-login/); // Verify login form elements const formVisible = await loginPage.isLoginFormVisible(); expect(formVisible).toBeTruthy(); // Check page content const contentCheck = await checkPageContent(page); console.log('Login Page Verification:'); console.log(`- URL: ${page.url()}`); console.log(`- Login form visible: ${formVisible}`); console.log(`- UI elements: ${JSON.stringify(contentCheck.elementCounts)}`); console.log(`- Has errors: ${contentCheck.hasErrors}`); if (contentCheck.hasErrors) { console.log(`- Error messages: ${contentCheck.errorMessages.join(', ')}`); } console.log(`- Screenshot saved to: ${screenshotPath}`); }); test('2-9. Verify Authenticated Pages', async ({ page }) => { // Login first await loginPage.navigateToLogin(); await loginPage.login(TEST_USER.username, TEST_USER.password); // List of pages to check const pagesToCheck = [ { name: 'Trainer Dashboard', path: '/hvac-dashboard/' }, { name: 'Trainer Profile', path: '/trainer-profile/' }, { name: 'Create Event', path: '/manage-event/' }, // The following may need event_id which we'll handle later { name: 'Event Summary', path: '/event-summary/' }, { name: 'Modify Event', path: '/manage-event/' }, { name: 'Email Attendees', path: '/email-attendees/' }, { name: 'Certificate Reports', path: '/certificate-reports/' }, { name: 'Generate Certificates', path: '/generate-certificates/' } ]; // Track results for all pages const results = []; // Check if we have an event on the dashboard we can use for event-specific pages await page.goto(PATHS.dashboard); await page.waitForLoadState('networkidle'); // Try to get an event ID if there are events let eventId = null; const eventsTable = page.locator('.event-table-row'); const eventCount = await eventsTable.count(); if (eventCount > 0) { // Click on the first event to get its ID from the URL await eventsTable.first().click(); await page.waitForLoadState('networkidle'); // Extract event ID from URL const url = page.url(); const match = url.match(/event_id=(\d+)/); if (match && match[1]) { eventId = match[1]; console.log(`Found event ID: ${eventId}`); } } // Now check each page for (const pageInfo of pagesToCheck) { let fullPath = pageInfo.path; // For pages that need an event ID, add it if we have one if (eventId && ( pageInfo.name === 'Event Summary' || pageInfo.name === 'Modify Event' || pageInfo.name === 'Email Attendees' )) { fullPath += `?event_id=${eventId}`; } // Navigate to page await page.goto(`${STAGING_URL}${fullPath}`); await page.waitForLoadState('networkidle'); // Take screenshot const screenshotPath = await saveScreenshot(page, pageInfo.name.toLowerCase().replace(/\s+/g, '-')); // Check page content const contentCheck = await checkPageContent(page); // Store results results.push({ name: pageInfo.name, url: page.url(), status: contentCheck.hasErrors ? 'Has errors' : 'OK', errors: contentCheck.errorMessages, uiElements: contentCheck.elementCounts, screenshotPath }); } // Output results console.log('\nPage Verification Results:'); console.log('=========================\n'); for (const result of results) { console.log(`${result.name}:`); console.log(`- URL: ${result.url}`); console.log(`- Status: ${result.status}`); console.log(`- UI elements: ${JSON.stringify(result.uiElements)}`); if (result.errors.length > 0) { console.log(`- Error messages: ${result.errors.join(', ')}`); } console.log(`- Screenshot saved to: ${result.screenshotPath}`); console.log('---'); } }); });