#!/usr/bin/env node
/**
* COMPREHENSIVE E2E STAGING TEST SUITE
*
* Complete functional testing of the HVAC Community Events WordPress plugin staging site
* to identify bugs, blank pages, and optimization opportunities.
*
* Based on zen testgen analysis and comprehensive testing plan.
*
* Test Coverage:
* - Role-based access control validation
* - Page content verification (not just HTTP status)
* - Dashboard functionality testing
* - Public trainer directory testing
* - Mobile responsiveness verification
* - JavaScript error detection
* - Security validation
* - Performance monitoring
*
* Uses MCP Playwright browser tools for real UI interaction
*/
const { chromium } = require('playwright');
const path = require('path');
const fs = require('fs');
// Import WordPress error detector if available
let WordPressErrorDetector;
try {
WordPressErrorDetector = require(path.join(__dirname, 'tests', 'framework', 'utils', 'WordPressErrorDetector'));
} catch (e) {
console.log('ā ļø WordPress error detector not available, continuing without it');
}
// Configuration
const CONFIG = {
baseUrl: process.env.BASE_URL || 'https://upskill-staging.measurequick.com',
headless: process.env.HEADLESS !== 'false', // Default to false for debugging
slowMo: process.env.HEADLESS === 'false' ? 500 : 0,
timeout: 30000,
viewport: { width: 1280, height: 720 }
};
// Test Accounts (update these based on staging environment)
const TEST_ACCOUNTS = {
guest: null, // No credentials for guest testing
trainer: {
username: process.env.TRAINER_USERNAME || 'test_trainer',
password: process.env.TRAINER_PASSWORD || 'TestTrainer123!'
},
masterTrainer: {
username: process.env.MASTER_USERNAME || 'test_master',
password: process.env.MASTER_PASSWORD || 'TestMaster123!'
}
};
// Pages to test organized by access level
const TEST_PAGES = {
public: [
{ path: '/training-login/', name: 'Training Login', expectContent: 'login' },
{ path: '/trainer/registration/', name: 'Trainer Registration', expectContent: 'registration' },
{ path: '/find-a-trainer/', name: 'Find a Trainer', expectContent: 'find a trainer' }
],
trainer: [
{ path: '/trainer/dashboard/', name: 'Trainer Dashboard', expectContent: 'trainer dashboard' },
{ path: '/trainer/profile/', name: 'Trainer Profile', expectContent: 'profile' },
{ path: '/trainer/event/manage/', name: 'Manage Events', expectContent: 'event' },
{ path: '/trainer/certificate-reports/', name: 'Certificate Reports', expectContent: 'certificate' },
{ path: '/trainer/resources/', name: 'Training Resources', expectContent: 'resources' },
{ path: '/trainer/venue/list/', name: 'Venue List', expectContent: 'venue' },
{ path: '/trainer/organizer/manage/', name: 'Organizer Management', expectContent: 'organizer' }
],
masterTrainer: [
{ path: '/master-trainer/master-dashboard/', name: 'Master Dashboard', expectContent: 'master' },
{ path: '/master-trainer/pending-approvals/', name: 'Pending Approvals', expectContent: 'approvals' },
{ path: '/master-trainer/announcements/', name: 'Announcements', expectContent: 'announcements' },
{ path: '/master-trainer/google-sheets/', name: 'Google Sheets', expectContent: 'sheets' },
{ path: '/master-trainer/trainers/', name: 'Manage Trainers', expectContent: 'trainers' },
{ path: '/master-trainer/import-export/', name: 'Import/Export', expectContent: 'import' }
]
};
// Test Results Tracker
class TestResults {
constructor() {
this.results = [];
this.startTime = Date.now();
this.categories = {
'ACCESS_CONTROL': 0,
'CONTENT_VERIFICATION': 0,
'FUNCTIONALITY': 0,
'MOBILE_RESPONSIVE': 0,
'SECURITY': 0,
'PERFORMANCE': 0,
'JAVASCRIPT': 0
};
}
addResult(category, test, status, details = '', url = '') {
this.results.push({
category,
test,
status,
details,
url,
timestamp: new Date().toISOString()
});
if (this.categories[category] !== undefined) {
this.categories[category]++;
}
const icon = status === 'PASSED' ? 'ā
' : 'ā';
const urlInfo = url ? ` [${url}]` : '';
console.log(`${icon} ${category} - ${test}${urlInfo}`);
if (details) console.log(` ${details}`);
}
printSummary() {
const duration = ((Date.now() - this.startTime) / 1000).toFixed(2);
const passed = this.results.filter(r => r.status === 'PASSED').length;
const failed = this.results.filter(r => r.status === 'FAILED').length;
const total = this.results.length;
console.log('\n' + '='.repeat(80));
console.log('š COMPREHENSIVE E2E TEST SUMMARY');
console.log('='.repeat(80));
console.log(`š Base URL: ${CONFIG.baseUrl}`);
console.log(`ā±ļø Duration: ${duration}s`);
console.log(`š Total Tests: ${total}`);
console.log(`ā
Passed: ${passed}`);
console.log(`ā Failed: ${failed}`);
console.log(`š Success Rate: ${total > 0 ? ((passed/total)*100).toFixed(1) : 0}%`);
console.log('\nš CATEGORY BREAKDOWN:');
Object.entries(this.categories).forEach(([category, count]) => {
const categoryResults = this.results.filter(r => r.category === category);
const categoryPassed = categoryResults.filter(r => r.status === 'PASSED').length;
const categoryFailed = categoryResults.filter(r => r.status === 'FAILED').length;
if (count > 0) {
console.log(` ${category}: ${categoryPassed}/${count} passed (${categoryFailed} failed)`);
}
});
if (failed > 0) {
console.log('\nā FAILED TESTS:');
this.results
.filter(r => r.status === 'FAILED')
.forEach(r => {
console.log(` - ${r.category}: ${r.test}`);
if (r.url) console.log(` URL: ${r.url}`);
if (r.details) console.log(` Details: ${r.details}`);
});
}
console.log('\n' + '='.repeat(80));
}
exportResults() {
const filename = `staging-test-results-${Date.now()}.json`;
const exportData = {
config: CONFIG,
summary: {
total: this.results.length,
passed: this.results.filter(r => r.status === 'PASSED').length,
failed: this.results.filter(r => r.status === 'FAILED').length,
duration: ((Date.now() - this.startTime) / 1000).toFixed(2)
},
categoryBreakdown: this.categories,
results: this.results
};
fs.writeFileSync(filename, JSON.stringify(exportData, null, 2));
console.log(`š Results exported to ${filename}`);
return filename;
}
}
// Utility Functions
class TestHelpers {
static async loginUser(page, username, password) {
try {
await page.goto(`${CONFIG.baseUrl}/training-login/`);
await page.fill('input[name="log"]', username);
await page.fill('input[name="pwd"]', password);
await page.click('input[type="submit"]');
// Wait for redirect after login
await page.waitForTimeout(2000);
// Check if login was successful
const currentUrl = page.url();
return !currentUrl.includes('training-login');
} catch (error) {
console.error(`Login failed for ${username}:`, error.message);
return false;
}
}
static async checkWordPressErrors(page) {
if (!WordPressErrorDetector) return { hasErrors: false, errors: [] };
try {
return await WordPressErrorDetector.checkForErrors(page);
} catch (error) {
return { hasErrors: false, errors: [], note: 'Error detector unavailable' };
}
}
static async checkJavaScriptErrors(page) {
const errors = [];
page.on('console', msg => {
if (msg.type() === 'error') {
errors.push(msg.text());
}
});
return errors;
}
static async checkPageContent(page, expectedContent, pageName) {
try {
// Check page loads
await page.waitForLoadState('networkidle', { timeout: 10000 });
// Check for basic content
const bodyContent = await page.textContent('body');
if (!bodyContent || bodyContent.trim().length < 100) {
return { valid: false, reason: 'Page appears to be blank or minimal content' };
}
// Check for expected content
const hasExpectedContent = bodyContent.toLowerCase().includes(expectedContent.toLowerCase());
if (!hasExpectedContent) {
return { valid: false, reason: `Expected content "${expectedContent}" not found` };
}
// Check for common error indicators
const errorIndicators = ['404', 'not found', 'error occurred', 'access denied', 'fatal error'];
const hasError = errorIndicators.some(indicator =>
bodyContent.toLowerCase().includes(indicator)
);
if (hasError) {
return { valid: false, reason: 'Page contains error indicators' };
}
return { valid: true, reason: 'Page loaded with expected content' };
} catch (error) {
return { valid: false, reason: `Page load error: ${error.message}` };
}
}
static async checkMobileResponsive(page) {
const viewports = [
{ width: 375, height: 667, name: 'Mobile' },
{ width: 768, height: 1024, name: 'Tablet' }
];
const results = [];
for (const viewport of viewports) {
try {
await page.setViewportSize(viewport);
await page.waitForTimeout(1000);
// Check if content fits viewport
const bodyWidth = await page.evaluate(() => document.body.scrollWidth);
const hasHorizontalScroll = bodyWidth > viewport.width + 50; // 50px tolerance
results.push({
viewport: viewport.name,
responsive: !hasHorizontalScroll,
actualWidth: bodyWidth,
viewportWidth: viewport.width
});
} catch (error) {
results.push({
viewport: viewport.name,
responsive: false,
error: error.message
});
}
}
// Reset to desktop
await page.setViewportSize(CONFIG.viewport);
return results;
}
}
// Main Test Runner
async function runComprehensiveTests() {
console.log('š Starting Comprehensive E2E Testing on Staging Environment');
console.log(`š Base URL: ${CONFIG.baseUrl}`);
console.log(`šļø Headless Mode: ${CONFIG.headless}`);
const results = new TestResults();
const browser = await chromium.launch({
headless: CONFIG.headless,
slowMo: CONFIG.slowMo
});
try {
// Test 1: Public Pages Access Control
console.log('\nš Testing Public Pages Access Control...');
await testPublicPagesAccess(browser, results);
// Test 2: Trainer Pages Access Control
console.log('\nš Testing Trainer Pages Access Control...');
await testTrainerPagesAccess(browser, results);
// Test 3: Master Trainer Pages Access Control
console.log('\nš Testing Master Trainer Pages Access Control...');
await testMasterTrainerPagesAccess(browser, results);
// Test 4: Content Verification
console.log('\nš Testing Page Content Verification...');
await testPageContentVerification(browser, results);
// Test 5: Dashboard Functionality
console.log('\nš Testing Dashboard Functionality...');
await testDashboardFunctionality(browser, results);
// Test 6: Public Directory Functionality
console.log('\nš Testing Public Directory Functionality...');
await testPublicDirectoryFunctionality(browser, results);
// Test 7: Mobile Responsiveness
console.log('\nš Testing Mobile Responsiveness...');
await testMobileResponsiveness(browser, results);
// Test 8: Security Validation
console.log('\nš Testing Security Validation...');
await testSecurityValidation(browser, results);
// Test 9: Performance Monitoring
console.log('\nš Testing Performance Monitoring...');
await testPerformanceMonitoring(browser, results);
} catch (error) {
console.error('ā Test execution failed:', error);
results.addResult('GENERAL', 'Test Execution', 'FAILED', error.message);
} finally {
await browser.close();
}
// Print and export results
results.printSummary();
results.exportResults();
// Exit with appropriate code
const failedCount = results.results.filter(r => r.status === 'FAILED').length;
process.exit(failedCount > 0 ? 1 : 0);
}
// Test Implementations
async function testPublicPagesAccess(browser, results) {
const context = await browser.newContext();
const page = await context.newPage();
try {
for (const pageInfo of TEST_PAGES.public) {
try {
await page.goto(`${CONFIG.baseUrl}${pageInfo.path}`, { waitUntil: 'networkidle' });
// Check WordPress errors
const wpErrors = await TestHelpers.checkWordPressErrors(page);
if (wpErrors.hasErrors) {
results.addResult('ACCESS_CONTROL', `Public Access - ${pageInfo.name}`, 'FAILED',
`WordPress errors: ${wpErrors.errors.join(', ')}`, pageInfo.path);
continue;
}
// Check content
const contentCheck = await TestHelpers.checkPageContent(page, pageInfo.expectContent, pageInfo.name);
if (contentCheck.valid) {
results.addResult('ACCESS_CONTROL', `Public Access - ${pageInfo.name}`, 'PASSED',
'Page accessible with expected content', pageInfo.path);
} else {
results.addResult('ACCESS_CONTROL', `Public Access - ${pageInfo.name}`, 'FAILED',
contentCheck.reason, pageInfo.path);
}
} catch (error) {
results.addResult('ACCESS_CONTROL', `Public Access - ${pageInfo.name}`, 'FAILED',
error.message, pageInfo.path);
}
}
} finally {
await context.close();
}
}
async function testTrainerPagesAccess(browser, results) {
// Test guest access (should be denied/redirected)
await testGuestAccessToProtectedPages(browser, results, TEST_PAGES.trainer, 'Trainer');
// Test trainer access
const context = await browser.newContext();
const page = await context.newPage();
try {
// Login as trainer
const loginSuccess = await TestHelpers.loginUser(page, TEST_ACCOUNTS.trainer.username, TEST_ACCOUNTS.trainer.password);
if (!loginSuccess) {
results.addResult('ACCESS_CONTROL', 'Trainer Login', 'FAILED', 'Could not login as trainer');
return;
}
results.addResult('ACCESS_CONTROL', 'Trainer Login', 'PASSED', 'Successfully logged in as trainer');
// Test each trainer page
for (const pageInfo of TEST_PAGES.trainer) {
try {
await page.goto(`${CONFIG.baseUrl}${pageInfo.path}`, { waitUntil: 'networkidle' });
const wpErrors = await TestHelpers.checkWordPressErrors(page);
if (wpErrors.hasErrors) {
results.addResult('ACCESS_CONTROL', `Trainer Access - ${pageInfo.name}`, 'FAILED',
`WordPress errors: ${wpErrors.errors.join(', ')}`, pageInfo.path);
continue;
}
const contentCheck = await TestHelpers.checkPageContent(page, pageInfo.expectContent, pageInfo.name);
if (contentCheck.valid) {
results.addResult('ACCESS_CONTROL', `Trainer Access - ${pageInfo.name}`, 'PASSED',
'Trainer can access with expected content', pageInfo.path);
} else {
results.addResult('ACCESS_CONTROL', `Trainer Access - ${pageInfo.name}`, 'FAILED',
contentCheck.reason, pageInfo.path);
}
} catch (error) {
results.addResult('ACCESS_CONTROL', `Trainer Access - ${pageInfo.name}`, 'FAILED',
error.message, pageInfo.path);
}
}
} finally {
await context.close();
}
}
async function testMasterTrainerPagesAccess(browser, results) {
// Test guest access (should be denied/redirected)
await testGuestAccessToProtectedPages(browser, results, TEST_PAGES.masterTrainer, 'Master Trainer');
// Test regular trainer access (should be denied)
await testTrainerAccessToMasterPages(browser, results);
// Test master trainer access
const context = await browser.newContext();
const page = await context.newPage();
try {
const loginSuccess = await TestHelpers.loginUser(page, TEST_ACCOUNTS.masterTrainer.username, TEST_ACCOUNTS.masterTrainer.password);
if (!loginSuccess) {
results.addResult('ACCESS_CONTROL', 'Master Trainer Login', 'FAILED', 'Could not login as master trainer');
return;
}
results.addResult('ACCESS_CONTROL', 'Master Trainer Login', 'PASSED', 'Successfully logged in as master trainer');
for (const pageInfo of TEST_PAGES.masterTrainer) {
try {
await page.goto(`${CONFIG.baseUrl}${pageInfo.path}`, { waitUntil: 'networkidle' });
const wpErrors = await TestHelpers.checkWordPressErrors(page);
if (wpErrors.hasErrors) {
results.addResult('ACCESS_CONTROL', `Master Access - ${pageInfo.name}`, 'FAILED',
`WordPress errors: ${wpErrors.errors.join(', ')}`, pageInfo.path);
continue;
}
const contentCheck = await TestHelpers.checkPageContent(page, pageInfo.expectContent, pageInfo.name);
if (contentCheck.valid) {
results.addResult('ACCESS_CONTROL', `Master Access - ${pageInfo.name}`, 'PASSED',
'Master trainer can access with expected content', pageInfo.path);
} else {
results.addResult('ACCESS_CONTROL', `Master Access - ${pageInfo.name}`, 'FAILED',
contentCheck.reason, pageInfo.path);
}
} catch (error) {
results.addResult('ACCESS_CONTROL', `Master Access - ${pageInfo.name}`, 'FAILED',
error.message, pageInfo.path);
}
}
} finally {
await context.close();
}
}
async function testGuestAccessToProtectedPages(browser, results, pages, pageType) {
const context = await browser.newContext();
const page = await context.newPage();
try {
for (const pageInfo of pages) {
try {
await page.goto(`${CONFIG.baseUrl}${pageInfo.path}`, { waitUntil: 'networkidle' });
const currentUrl = page.url();
if (currentUrl.includes('training-login') || currentUrl.includes('access-denied')) {
results.addResult('ACCESS_CONTROL', `Guest Denied - ${pageType} ${pageInfo.name}`, 'PASSED',
'Correctly redirected guest user', pageInfo.path);
} else {
const bodyContent = await page.textContent('body');
if (bodyContent.toLowerCase().includes('access denied')) {
results.addResult('ACCESS_CONTROL', `Guest Denied - ${pageType} ${pageInfo.name}`, 'PASSED',
'Correctly denied guest access', pageInfo.path);
} else {
results.addResult('ACCESS_CONTROL', `Guest Denied - ${pageType} ${pageInfo.name}`, 'FAILED',
'Guest user can access protected page', pageInfo.path);
}
}
} catch (error) {
results.addResult('ACCESS_CONTROL', `Guest Denied - ${pageType} ${pageInfo.name}`, 'FAILED',
error.message, pageInfo.path);
}
}
} finally {
await context.close();
}
}
async function testTrainerAccessToMasterPages(browser, results) {
const context = await browser.newContext();
const page = await context.newPage();
try {
const loginSuccess = await TestHelpers.loginUser(page, TEST_ACCOUNTS.trainer.username, TEST_ACCOUNTS.trainer.password);
if (!loginSuccess) {
results.addResult('ACCESS_CONTROL', 'Trainer Access to Master Pages', 'FAILED', 'Could not login as trainer');
return;
}
for (const pageInfo of TEST_PAGES.masterTrainer) {
try {
await page.goto(`${CONFIG.baseUrl}${pageInfo.path}`, { waitUntil: 'networkidle' });
const bodyContent = await page.textContent('body');
if (bodyContent.toLowerCase().includes('access denied') ||
bodyContent.toLowerCase().includes('insufficient permissions')) {
results.addResult('ACCESS_CONTROL', `Trainer Denied - ${pageInfo.name}`, 'PASSED',
'Correctly denied trainer access to master page', pageInfo.path);
} else {
results.addResult('ACCESS_CONTROL', `Trainer Denied - ${pageInfo.name}`, 'FAILED',
'Regular trainer can access master trainer page', pageInfo.path);
}
} catch (error) {
results.addResult('ACCESS_CONTROL', `Trainer Denied - ${pageInfo.name}`, 'FAILED',
error.message, pageInfo.path);
}
}
} finally {
await context.close();
}
}
async function testPageContentVerification(browser, results) {
const context = await browser.newContext();
const page = await context.newPage();
try {
// Test high-priority pages with detailed content verification
const priorityPages = [
{ path: '/find-a-trainer/', checks: ['.hvac-find-trainer-page', '.hvac-trainer-grid', 'h1'] },
{ path: '/training-login/', checks: ['form', 'input[name="log"]', 'input[name="pwd"]'] }
];
for (const pageTest of priorityPages) {
try {
await page.goto(`${CONFIG.baseUrl}${pageTest.path}`, { waitUntil: 'networkidle' });
let allChecksPass = true;
const failedChecks = [];
for (const selector of pageTest.checks) {
try {
await page.waitForSelector(selector, { timeout: 5000 });
} catch (error) {
allChecksPass = false;
failedChecks.push(selector);
}
}
if (allChecksPass) {
results.addResult('CONTENT_VERIFICATION', `Content Check - ${pageTest.path}`, 'PASSED',
'All required elements present', pageTest.path);
} else {
results.addResult('CONTENT_VERIFICATION', `Content Check - ${pageTest.path}`, 'FAILED',
`Missing elements: ${failedChecks.join(', ')}`, pageTest.path);
}
} catch (error) {
results.addResult('CONTENT_VERIFICATION', `Content Check - ${pageTest.path}`, 'FAILED',
error.message, pageTest.path);
}
}
} finally {
await context.close();
}
}
async function testDashboardFunctionality(browser, results) {
const context = await browser.newContext();
const page = await context.newPage();
try {
const loginSuccess = await TestHelpers.loginUser(page, TEST_ACCOUNTS.trainer.username, TEST_ACCOUNTS.trainer.password);
if (!loginSuccess) {
results.addResult('FUNCTIONALITY', 'Dashboard Login Required', 'FAILED', 'Could not login for dashboard tests');
return;
}
await page.goto(`${CONFIG.baseUrl}/trainer/dashboard/`, { waitUntil: 'networkidle' });
// Test statistics display
try {
await page.waitForSelector('.hvac-stat-card', { timeout: 5000 });
const statCards = await page.$$('.hvac-stat-card');
if (statCards.length >= 3) {
results.addResult('FUNCTIONALITY', 'Dashboard Statistics', 'PASSED',
`Found ${statCards.length} stat cards`, '/trainer/dashboard/');
} else {
results.addResult('FUNCTIONALITY', 'Dashboard Statistics', 'FAILED',
`Only found ${statCards.length} stat cards`, '/trainer/dashboard/');
}
} catch (error) {
results.addResult('FUNCTIONALITY', 'Dashboard Statistics', 'FAILED',
'No stat cards found', '/trainer/dashboard/');
}
// Test events table
try {
await page.waitForSelector('.events-table', { timeout: 5000 });
results.addResult('FUNCTIONALITY', 'Dashboard Events Table', 'PASSED',
'Events table is present', '/trainer/dashboard/');
} catch (error) {
results.addResult('FUNCTIONALITY', 'Dashboard Events Table', 'FAILED',
'Events table not found', '/trainer/dashboard/');
}
// Test search functionality
try {
const searchInput = page.locator('#hvac-event-search');
await searchInput.fill('test search');
results.addResult('FUNCTIONALITY', 'Dashboard Search', 'PASSED',
'Search input is functional', '/trainer/dashboard/');
} catch (error) {
results.addResult('FUNCTIONALITY', 'Dashboard Search', 'FAILED',
'Search input not functional', '/trainer/dashboard/');
}
} finally {
await context.close();
}
}
async function testPublicDirectoryFunctionality(browser, results) {
const context = await browser.newContext();
const page = await context.newPage();
try {
await page.goto(`${CONFIG.baseUrl}/find-a-trainer/`, { waitUntil: 'networkidle' });
// Test trainer cards display
try {
await page.waitForSelector('.hvac-trainer-card', { timeout: 5000 });
const trainerCards = await page.$$('.hvac-trainer-card');
if (trainerCards.length > 0) {
results.addResult('FUNCTIONALITY', 'Directory Trainer Cards', 'PASSED',
`Found ${trainerCards.length} trainer cards`, '/find-a-trainer/');
} else {
results.addResult('FUNCTIONALITY', 'Directory Trainer Cards', 'FAILED',
'No trainer cards found', '/find-a-trainer/');
}
} catch (error) {
results.addResult('FUNCTIONALITY', 'Directory Trainer Cards', 'FAILED',
'Could not locate trainer cards', '/find-a-trainer/');
}
// Test search functionality
try {
const searchInput = page.locator('#hvac-trainer-search');
await searchInput.fill('test');
results.addResult('FUNCTIONALITY', 'Directory Search', 'PASSED',
'Search input is functional', '/find-a-trainer/');
} catch (error) {
results.addResult('FUNCTIONALITY', 'Directory Search', 'FAILED',
'Search input not functional', '/find-a-trainer/');
}
// Test filter buttons
try {
await page.waitForSelector('button[data-filter]', { timeout: 5000 });
const filterButtons = await page.$$('button[data-filter]');
if (filterButtons.length > 0) {
results.addResult('FUNCTIONALITY', 'Directory Filters', 'PASSED',
`Found ${filterButtons.length} filter buttons`, '/find-a-trainer/');
} else {
results.addResult('FUNCTIONALITY', 'Directory Filters', 'FAILED',
'No filter buttons found', '/find-a-trainer/');
}
} catch (error) {
results.addResult('FUNCTIONALITY', 'Directory Filters', 'FAILED',
'Could not locate filter buttons', '/find-a-trainer/');
}
} finally {
await context.close();
}
}
async function testMobileResponsiveness(browser, results) {
const context = await browser.newContext();
const page = await context.newPage();
try {
const testPages = [
'/find-a-trainer/',
'/training-login/',
'/trainer/dashboard/' // This will redirect to login for guest
];
for (const testPath of testPages) {
try {
await page.goto(`${CONFIG.baseUrl}${testPath}`, { waitUntil: 'networkidle' });
const mobileResults = await TestHelpers.checkMobileResponsive(page);
let allResponsive = true;
const issues = [];
for (const result of mobileResults) {
if (!result.responsive) {
allResponsive = false;
issues.push(`${result.viewport}: ${result.error || 'Not responsive'}`);
}
}
if (allResponsive) {
results.addResult('MOBILE_RESPONSIVE', `Mobile Check - ${testPath}`, 'PASSED',
'Responsive on all tested viewports', testPath);
} else {
results.addResult('MOBILE_RESPONSIVE', `Mobile Check - ${testPath}`, 'FAILED',
`Issues: ${issues.join(', ')}`, testPath);
}
} catch (error) {
results.addResult('MOBILE_RESPONSIVE', `Mobile Check - ${testPath}`, 'FAILED',
error.message, testPath);
}
}
} finally {
await context.close();
}
}
async function testSecurityValidation(browser, results) {
const context = await browser.newContext();
const page = await context.newPage();
try {
// Test XSS prevention in search
await page.goto(`${CONFIG.baseUrl}/find-a-trainer/?search=`,
{ waitUntil: 'networkidle' });
const searchInput = page.locator('#hvac-trainer-search');
const inputValue = await searchInput.inputValue();
if (inputValue.includes('