upskill-event-manager/tests/e2e/hvac-trainer-events.test.js
Ben 7c9ca65cf2
Some checks are pending
HVAC Plugin CI/CD Pipeline / Security Analysis (push) Waiting to run
HVAC Plugin CI/CD Pipeline / Code Quality & Standards (push) Waiting to run
HVAC Plugin CI/CD Pipeline / Unit Tests (push) Waiting to run
HVAC Plugin CI/CD Pipeline / Integration Tests (push) Waiting to run
HVAC Plugin CI/CD Pipeline / Deploy to Staging (push) Blocked by required conditions
HVAC Plugin CI/CD Pipeline / Deploy to Production (push) Blocked by required conditions
HVAC Plugin CI/CD Pipeline / Notification (push) Blocked by required conditions
Security Monitoring & Compliance / Dependency Vulnerability Scan (push) Waiting to run
Security Monitoring & Compliance / Secrets & Credential Scan (push) Waiting to run
Security Monitoring & Compliance / WordPress Security Analysis (push) Waiting to run
Security Monitoring & Compliance / Static Code Security Analysis (push) Waiting to run
Security Monitoring & Compliance / Security Compliance Validation (push) Waiting to run
Security Monitoring & Compliance / Security Summary Report (push) Blocked by required conditions
Security Monitoring & Compliance / Security Team Notification (push) Blocked by required conditions
feat: add comprehensive test framework and test files
- Add 90+ test files including E2E, unit, and integration tests
- Implement Page Object Model (POM) architecture
- Add Docker testing environment with comprehensive services
- Include modernized test framework with error recovery
- Add specialized test suites for master trainer and trainer workflows
- Update .gitignore to properly track test infrastructure

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-29 23:23:26 -03:00

866 lines
No EOL
32 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* HVAC Trainer Events E2E Test Suite
*
* This comprehensive test suite validates the complete trainer event creation and editing workflow
* using The Events Calendar (TEC) Community Events integration.
*
* Test Coverage:
* - Trainer authentication and access control
* - Event creation through TEC integration
* - Event editing and updates
* - Event management navigation
* - Data persistence and validation
* - Form field validation and error handling
* - Dashboard integration
* - Complete trainer workflow
*/
const { chromium } = require('playwright');
const fs = require('fs');
const path = require('path');
// Test configuration
const CONFIG = {
baseUrl: 'https://upskill-staging.measurequick.com',
credentials: {
username: 'test_trainer',
password: 'TestTrainer123!'
},
timeouts: {
navigation: 30000,
element: 10000,
wait: 3000
},
headless: true,
screenshots: true
};
// Test data for event creation
const TEST_EVENT_DATA = {
title: `Test HVAC Training Event ${Date.now()}`,
description: 'This is a comprehensive test event for HVAC training with detailed description covering all aspects of the training program.',
excerpt: 'Brief summary of the test HVAC training event',
startDate: '2025-09-01',
startTime: '09:00',
endDate: '2025-09-01',
endTime: '17:00',
venue: 'Test Training Center',
venueAddress: '123 Training Street, Test City, Test State 12345',
category: 'Installation Training',
tags: 'hvac, installation, test',
cost: '299.00',
maxAttendees: '25'
};
// Test results tracking
const testResults = {
passed: 0,
failed: 0,
total: 0,
details: []
};
/**
* Utility function to log test results
*/
function logTest(testName, passed, details = '', screenshot = null) {
const status = passed ? '✅ PASS' : '❌ FAIL';
const timestamp = new Date().toISOString();
console.log(`[${timestamp}] ${status} ${testName}`);
if (details) {
console.log(` ${details}`);
}
testResults.total++;
if (passed) {
testResults.passed++;
} else {
testResults.failed++;
}
testResults.details.push({
name: testName,
passed,
details,
screenshot,
timestamp
});
}
/**
* Utility function to take screenshots for debugging
*/
async function takeScreenshot(page, filename, description = '') {
if (!CONFIG.screenshots) return null;
try {
const screenshotPath = path.join(__dirname, '../../screenshots', `${filename}-${Date.now()}.png`);
// Ensure screenshots directory exists
const screenshotsDir = path.dirname(screenshotPath);
if (!fs.existsSync(screenshotsDir)) {
fs.mkdirSync(screenshotsDir, { recursive: true });
}
await page.screenshot({
path: screenshotPath,
fullPage: true
});
console.log(` 📸 Screenshot saved: ${path.basename(screenshotPath)}`);
if (description) {
console.log(` 📝 ${description}`);
}
return screenshotPath;
} catch (error) {
console.log(` ⚠️ Screenshot failed: ${error.message}`);
return null;
}
}
/**
* Wait for element with better error handling
*/
async function waitForElement(page, selector, timeout = CONFIG.timeouts.element) {
try {
await page.waitForSelector(selector, { timeout, state: 'visible' });
return true;
} catch (error) {
console.log(` ⚠️ Element not found: ${selector}`);
return false;
}
}
/**
* Login as trainer with comprehensive validation
*/
async function loginAsTrainer(page) {
console.log('\n🔐 AUTHENTICATION TEST');
console.log('─'.repeat(50));
try {
// Navigate to login page
await page.goto(`${CONFIG.baseUrl}/trainer/training-login/`, {
waitUntil: 'networkidle',
timeout: CONFIG.timeouts.navigation
});
const loginPageLoaded = await page.locator('form').isVisible();
logTest('Login page loads', loginPageLoaded, page.url());
if (!loginPageLoaded) {
await takeScreenshot(page, 'login-page-failed', 'Login page failed to load');
return false;
}
// Fill login credentials
await page.fill('#username, #user_login, input[name="log"]', CONFIG.credentials.username);
await page.fill('#password, #user_pass, input[name="pwd"]', CONFIG.credentials.password);
// Submit login form
await page.click('input[type="submit"], button[type="submit"]');
await page.waitForTimeout(CONFIG.timeouts.wait);
// Verify login success
const currentUrl = page.url();
const isLoggedIn = currentUrl.includes('/trainer/') && !currentUrl.includes('login');
logTest('Login authentication', isLoggedIn, `Final URL: ${currentUrl}`);
if (isLoggedIn) {
await takeScreenshot(page, 'login-success', 'Successfully logged in as trainer');
return true;
} else {
await takeScreenshot(page, 'login-failed', 'Login failed - not redirected to trainer area');
return false;
}
} catch (error) {
logTest('Login process', false, `Login error: ${error.message}`);
await takeScreenshot(page, 'login-error', 'Login process encountered an error');
return false;
}
}
/**
* Test trainer dashboard access and navigation
*/
async function testTrainerDashboard(page) {
console.log('\n📊 TRAINER DASHBOARD TEST');
console.log('─'.repeat(50));
try {
await page.goto(`${CONFIG.baseUrl}/trainer/dashboard/`, {
waitUntil: 'networkidle',
timeout: CONFIG.timeouts.navigation
});
// Check dashboard loads correctly
const dashboardTitle = await page.title();
const hasDashboardContent = await page.locator('h1, h2').first().isVisible();
logTest('Dashboard page loads', hasDashboardContent, `Title: ${dashboardTitle}`);
// Check navigation menu - use first() to avoid strict mode violation
const hasNavigation = await page.locator('.hvac-trainer-nav, .hvac-trainer-menu').first().isVisible();
logTest('Dashboard navigation menu', hasNavigation);
// Check for event management links
const hasEventManageLink = await page.locator('a[href*="event/manage"], a[href*="events"]').first().isVisible();
logTest('Event management link present', hasEventManageLink);
await takeScreenshot(page, 'dashboard-loaded', 'Trainer dashboard successfully loaded');
return true;
} catch (error) {
logTest('Dashboard access', false, `Dashboard error: ${error.message}`);
await takeScreenshot(page, 'dashboard-error', 'Dashboard access failed');
return false;
}
}
/**
* Test event management page access
*/
async function testEventManagePage(page) {
console.log('\n📋 EVENT MANAGEMENT PAGE TEST');
console.log('─'.repeat(50));
try {
await page.goto(`${CONFIG.baseUrl}/trainer/event/manage/`, {
waitUntil: 'networkidle',
timeout: CONFIG.timeouts.navigation
});
// Check page loads
const pageTitle = await page.title();
const hasContent = await page.locator('h1, h2, .hvac-event-manage').first().isVisible();
logTest('Event management page loads', hasContent, `Title: ${pageTitle}`);
// Check for create event button/link
const hasCreateButton = await page.locator('a[href*="add"], a[href*="create"], button:has-text("Create")').first().isVisible();
logTest('Create event button present', hasCreateButton);
// Check for my events link
const hasMyEventsLink = await page.locator('a[href*="events"], a:has-text("My Events")').first().isVisible();
logTest('My Events link present', hasMyEventsLink);
await takeScreenshot(page, 'event-manage-page', 'Event management page loaded');
return true;
} catch (error) {
logTest('Event management page', false, `Event management error: ${error.message}`);
await takeScreenshot(page, 'event-manage-error', 'Event management page failed');
return false;
}
}
/**
* Test event creation workflow
*/
async function testEventCreation(page) {
console.log('\n EVENT CREATION TEST');
console.log('─'.repeat(50));
try {
// Navigate to event creation page (TEC Community Events)
const createUrls = [
`${CONFIG.baseUrl}/events/network/add/`,
`${CONFIG.baseUrl}/trainer/event/create/`,
`${CONFIG.baseUrl}/events/community/add/`
];
let createPageLoaded = false;
let workingUrl = '';
// Try different URLs for event creation
for (const url of createUrls) {
try {
await page.goto(url, {
waitUntil: 'networkidle',
timeout: CONFIG.timeouts.navigation
});
const hasForm = await page.locator('form').first().isVisible({ timeout: 5000 });
if (hasForm) {
createPageLoaded = true;
workingUrl = url;
break;
}
} catch (error) {
console.log(` ⚠️ URL not accessible: ${url}`);
}
}
logTest('Event creation page access', createPageLoaded, `Working URL: ${workingUrl}`);
if (!createPageLoaded) {
await takeScreenshot(page, 'create-event-no-access', 'Cannot access event creation page');
return null;
}
await takeScreenshot(page, 'create-event-form', 'Event creation form loaded');
// Fill out event creation form - using exact TEC field selectors from form analysis
const formFields = {
title: '#post_title',
startDate: '#EventStartDate',
startTime: '#EventStartTime',
endDate: '#EventEndDate',
endTime: '#EventEndTime',
venue: '#saved_tribe_venue',
organizer: '#saved_tribe_organizer'
};
const filledFields = {};
// Fill form fields with better error handling - use .first() to avoid strict mode violations
for (const [fieldName, selector] of Object.entries(formFields)) {
try {
const element = page.locator(selector).first();
const isVisible = await element.isVisible({ timeout: 3000 });
if (isVisible) {
let value;
switch (fieldName) {
case 'title':
value = TEST_EVENT_DATA.title;
break;
case 'startDate':
value = TEST_EVENT_DATA.startDate;
break;
case 'startTime':
value = TEST_EVENT_DATA.startTime;
break;
case 'endDate':
value = TEST_EVENT_DATA.endDate;
break;
case 'endTime':
value = TEST_EVENT_DATA.endTime;
break;
case 'venue':
// For select fields, select by index if it's a dropdown
try {
await element.selectOption({ index: 1 });
filledFields[fieldName] = true;
console.log(`${fieldName} selected`);
continue;
} catch (e) {
value = 'Test Venue';
}
break;
case 'organizer':
// For select fields, select by index if it's a dropdown
try {
await element.selectOption({ index: 1 });
filledFields[fieldName] = true;
console.log(`${fieldName} selected`);
continue;
} catch (e) {
value = 'Test Organizer';
}
break;
default:
value = TEST_EVENT_DATA[fieldName] || 'Test Value';
}
await element.fill(value);
filledFields[fieldName] = true;
console.log(`${fieldName} filled: ${value}`);
} else {
console.log(` ⚠️ Field not visible: ${fieldName} (${selector})`);
}
} catch (error) {
console.log(` ⚠️ Could not fill field: ${fieldName} - ${error.message}`);
}
}
// Try to fill the description field using WordPress rich text editor
try {
// Try to interact with TinyMCE editor
await page.evaluate(() => {
// Try to set content via TinyMCE if available
if (typeof tinymce !== 'undefined' && tinymce.get('tcepostcontent')) {
tinymce.get('tcepostcontent').setContent('Test event description for automated testing');
return true;
}
// Otherwise try to set via textarea directly
const textarea = document.getElementById('tcepostcontent');
if (textarea) {
textarea.value = 'Test event description for automated testing';
textarea.dispatchEvent(new Event('input', { bubbles: true }));
return true;
}
return false;
});
filledFields.description = true;
console.log(' ✓ Description filled via editor');
} catch (error) {
console.log(' ⚠️ Could not fill description field');
}
const fieldsFilledCount = Object.keys(filledFields).length;
logTest('Form fields populated', fieldsFilledCount > 0, `${fieldsFilledCount} fields filled`);
// Handle special fields (dropdowns, etc.)
try {
// Try to set event category
const categorySelect = page.locator('select[name*="category"], #tribe_events_cat');
if (await categorySelect.isVisible({ timeout: 2000 })) {
await categorySelect.selectOption({ index: 1 });
console.log(' ✓ Category selected');
}
} catch (error) {
console.log(' ⚠️ Category field not available');
}
await takeScreenshot(page, 'create-event-filled', 'Event creation form filled out');
// Submit the form
const submitButton = page.locator('input[type="submit"], button[type="submit"], button:has-text("Create"), button:has-text("Publish")');
const hasSubmitButton = await submitButton.first().isVisible();
logTest('Submit button present', hasSubmitButton);
if (hasSubmitButton) {
await submitButton.first().click();
await page.waitForTimeout(CONFIG.timeouts.wait);
// Check for success or errors - use first() to avoid strict mode violations
const currentUrl = page.url();
const hasErrorMessage = await page.locator('.tribe-community-notice-error').first().isVisible({ timeout: 3000 });
const hasSuccessMessage = await page.locator('.tribe-community-notice-success, .success').first().isVisible({ timeout: 3000 });
const submissionSuccessful = !hasErrorMessage && (hasSuccessMessage || currentUrl !== workingUrl);
logTest('Event creation submission', submissionSuccessful,
hasErrorMessage ? 'Form has errors' : `Redirected to: ${currentUrl}`);
await takeScreenshot(page, 'create-event-submitted', 'Event creation form submitted');
// Extract event ID or URL for editing test
if (submissionSuccessful) {
const eventId = currentUrl.match(/event\/(\d+)/)?.[1] ||
currentUrl.match(/post=(\d+)/)?.[1] ||
Date.now().toString();
return eventId;
}
}
return null;
} catch (error) {
logTest('Event creation process', false, `Creation error: ${error.message}`);
await takeScreenshot(page, 'create-event-error', 'Event creation process failed');
return null;
}
}
/**
* Test event editing workflow
*/
async function testEventEditing(page, eventId) {
console.log('\n✏ EVENT EDITING TEST');
console.log('─'.repeat(50));
if (!eventId) {
logTest('Event editing setup', false, 'No event ID available for editing');
return false;
}
try {
// Navigate to edit event page
const editUrls = [
`${CONFIG.baseUrl}/events/network/edit/?event_id=${eventId}`,
`${CONFIG.baseUrl}/events/community/edit/${eventId}/`,
`${CONFIG.baseUrl}/wp-admin/post.php?post=${eventId}&action=edit`
];
let editPageLoaded = false;
let workingUrl = '';
for (const url of editUrls) {
try {
await page.goto(url, {
waitUntil: 'networkidle',
timeout: CONFIG.timeouts.navigation
});
const hasEditForm = await page.locator('form, #post').first().isVisible({ timeout: 5000 });
if (hasEditForm) {
editPageLoaded = true;
workingUrl = url;
break;
}
} catch (error) {
console.log(` ⚠️ Edit URL not accessible: ${url}`);
}
}
logTest('Event edit page access', editPageLoaded, `Working URL: ${workingUrl}`);
if (!editPageLoaded) {
await takeScreenshot(page, 'edit-event-no-access', 'Cannot access event edit page');
return false;
}
await takeScreenshot(page, 'edit-event-form', 'Event edit form loaded');
// Modify event data
const updatedTitle = `${TEST_EVENT_DATA.title} - EDITED`;
const titleField = page.locator('#post_title, input[name="post_title"], #title');
if (await titleField.isVisible({ timeout: 3000 })) {
await titleField.fill(updatedTitle);
console.log(' ✓ Event title updated');
}
// Update description if available
const descriptionField = page.locator('#post_content, textarea[name="post_content"]');
if (await descriptionField.isVisible({ timeout: 3000 })) {
await descriptionField.fill(TEST_EVENT_DATA.description + ' - This event has been edited.');
console.log(' ✓ Event description updated');
}
await takeScreenshot(page, 'edit-event-modified', 'Event edit form modified');
// Submit changes
const updateButton = page.locator('input[type="submit"], button[type="submit"], button:has-text("Update"), button:has-text("Save")');
const hasUpdateButton = await updateButton.first().isVisible();
logTest('Update button present', hasUpdateButton);
if (hasUpdateButton) {
await updateButton.first().click();
await page.waitForTimeout(CONFIG.timeouts.wait);
const currentUrl = page.url();
const hasErrorMessage = await page.locator('.tribe-community-notice-error').first().isVisible({ timeout: 3000 });
const updateSuccessful = !hasErrorMessage;
logTest('Event update submission', updateSuccessful,
hasErrorMessage ? 'Update has errors' : 'Update completed');
await takeScreenshot(page, 'edit-event-submitted', 'Event edit form submitted');
return updateSuccessful;
}
return false;
} catch (error) {
logTest('Event editing process', false, `Editing error: ${error.message}`);
await takeScreenshot(page, 'edit-event-error', 'Event editing process failed');
return false;
}
}
/**
* Test My Events page functionality
*/
async function testMyEventsPage(page) {
console.log('\n📅 MY EVENTS PAGE TEST');
console.log('─'.repeat(50));
try {
const myEventsUrls = [
`${CONFIG.baseUrl}/events/network/`,
`${CONFIG.baseUrl}/trainer/events/`,
`${CONFIG.baseUrl}/events/community/my-events/`
];
let myEventsPageLoaded = false;
let workingUrl = '';
for (const url of myEventsUrls) {
try {
await page.goto(url, {
waitUntil: 'networkidle',
timeout: CONFIG.timeouts.navigation
});
const pageTitle = await page.title();
const hasEventsList = await page.locator('.tribe-events-list, .events-list, table').first().isVisible({ timeout: 5000 });
if (pageTitle.toLowerCase().includes('events') || hasEventsList) {
myEventsPageLoaded = true;
workingUrl = url;
break;
}
} catch (error) {
console.log(` ⚠️ My Events URL not accessible: ${url}`);
}
}
logTest('My Events page access', myEventsPageLoaded, `Working URL: ${workingUrl}`);
if (myEventsPageLoaded) {
// Count events displayed
const eventCount = await page.locator('.tribe-events-list-event, .event-row, tr').count();
logTest('Events list displayed', eventCount >= 0, `${eventCount} events found`);
// Check for event management actions
const hasEditLinks = await page.locator('a:has-text("Edit"), a[href*="edit"]').first().isVisible({ timeout: 3000 });
logTest('Event edit links present', hasEditLinks);
await takeScreenshot(page, 'my-events-page', 'My Events page loaded');
return true;
}
return false;
} catch (error) {
logTest('My Events page', false, `My Events error: ${error.message}`);
await takeScreenshot(page, 'my-events-error', 'My Events page failed');
return false;
}
}
/**
* Test navigation between event pages
*/
async function testEventNavigation(page) {
console.log('\n🧭 EVENT NAVIGATION TEST');
console.log('─'.repeat(50));
try {
// Test navigation from dashboard to event management
await page.goto(`${CONFIG.baseUrl}/trainer/dashboard/`, {
waitUntil: 'networkidle',
timeout: CONFIG.timeouts.navigation
});
const eventManagementLink = page.locator('a[href*="event"], a:has-text("Event"), a:has-text("Manage")').first();
const hasEventManagementLink = await eventManagementLink.isVisible({ timeout: 5000 });
logTest('Dashboard to Event Management navigation', hasEventManagementLink);
if (hasEventManagementLink) {
await eventManagementLink.click();
await page.waitForTimeout(CONFIG.timeouts.wait);
const navigationSuccessful = page.url().includes('event') || page.url().includes('manage');
logTest('Event Management navigation successful', navigationSuccessful, page.url());
}
// Test breadcrumb navigation if available
const hasBreadcrumbs = await page.locator('.breadcrumb, .hvac-breadcrumb, nav[aria-label*="breadcrumb"]').isVisible({ timeout: 3000 });
logTest('Breadcrumb navigation present', hasBreadcrumbs);
await takeScreenshot(page, 'event-navigation', 'Event navigation testing');
return true;
} catch (error) {
logTest('Event navigation', false, `Navigation error: ${error.message}`);
await takeScreenshot(page, 'navigation-error', 'Event navigation failed');
return false;
}
}
/**
* Test form validation and error handling
*/
async function testFormValidation(page) {
console.log('\n🔍 FORM VALIDATION TEST');
console.log('─'.repeat(50));
try {
// Navigate to event creation page
await page.goto(`${CONFIG.baseUrl}/events/network/add/`, {
waitUntil: 'networkidle',
timeout: CONFIG.timeouts.navigation
});
const hasForm = await page.locator('form').first().isVisible({ timeout: 5000 });
if (hasForm) {
// Test empty form submission
const submitButton = page.locator('input[type="submit"], button[type="submit"]').first();
if (await submitButton.isVisible()) {
await submitButton.click();
await page.waitForTimeout(CONFIG.timeouts.wait);
// Check for validation errors - be more specific to avoid strict mode violations
const hasValidationErrors = await page.locator('.tribe-community-notice-error, .required').first().isVisible({ timeout: 3000 });
logTest('Form validation on empty submission', hasValidationErrors, 'Required field validation');
// Test field-specific validation
const titleField = page.locator('#post_title, input[name="post_title"]').first();
if (await titleField.isVisible()) {
await titleField.fill('Test');
await titleField.fill(''); // Clear field
await titleField.blur();
const hasFieldError = await page.locator('.error, .invalid').first().isVisible({ timeout: 2000 });
logTest('Individual field validation', hasFieldError, 'Field-level validation working');
}
}
}
await takeScreenshot(page, 'form-validation', 'Form validation testing');
return hasForm;
} catch (error) {
logTest('Form validation', false, `Validation error: ${error.message}`);
await takeScreenshot(page, 'validation-error', 'Form validation failed');
return false;
}
}
/**
* Main test execution function
*/
async function runHVACTrainerEventsTest() {
console.log('🚀 HVAC TRAINER EVENTS E2E TEST SUITE');
console.log('═'.repeat(70));
console.log(`📅 Test Started: ${new Date().toLocaleString()}`);
console.log(`🌐 Base URL: ${CONFIG.baseUrl}`);
console.log(`👤 Test User: ${CONFIG.credentials.username}`);
console.log('═'.repeat(70));
// Browser setup
const browser = await chromium.launch({
headless: CONFIG.headless,
args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage']
});
const context = await browser.newContext({
ignoreHTTPSErrors: true,
viewport: { width: 1920, height: 1080 },
userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
});
const page = await context.newPage();
// Enable request/response logging for debugging
page.on('requestfailed', request => {
console.log(` ⚠️ Request failed: ${request.url()}`);
});
let eventId = null;
try {
// Test Sequence
const loginSuccessful = await loginAsTrainer(page);
if (loginSuccessful) {
await testTrainerDashboard(page);
await testEventManagePage(page);
// Event creation and editing workflow
eventId = await testEventCreation(page);
if (eventId) {
await testEventEditing(page, eventId);
}
await testMyEventsPage(page);
await testEventNavigation(page);
await testFormValidation(page);
} else {
console.log('⚠️ Skipping remaining tests due to authentication failure');
}
} catch (error) {
console.error('❌ Test suite error:', error.message);
await takeScreenshot(page, 'test-suite-error', 'Critical test suite error');
logTest('Test suite execution', false, `Critical error: ${error.message}`);
} finally {
await browser.close();
}
// Generate comprehensive test report
console.log('\n' + '═'.repeat(70));
console.log('📊 COMPREHENSIVE TEST REPORT');
console.log('═'.repeat(70));
console.log(`📅 Test Completed: ${new Date().toLocaleString()}`);
console.log(`⏱️ Total Tests: ${testResults.total}`);
console.log(`✅ Passed: ${testResults.passed}`);
console.log(`❌ Failed: ${testResults.failed}`);
if (testResults.total > 0) {
const successRate = Math.round((testResults.passed / testResults.total) * 100);
console.log(`📈 Success Rate: ${successRate}%`);
if (successRate >= 80) {
console.log('🎉 TEST SUITE: EXCELLENT PERFORMANCE');
} else if (successRate >= 60) {
console.log('⚠️ TEST SUITE: NEEDS ATTENTION');
} else {
console.log('🚨 TEST SUITE: CRITICAL ISSUES');
}
}
// Detailed results
if (testResults.failed > 0) {
console.log('\n❌ FAILED TESTS:');
console.log('─'.repeat(50));
testResults.details.filter(t => !t.passed).forEach((test, index) => {
console.log(`${index + 1}. ${test.name}`);
if (test.details) console.log(` Details: ${test.details}`);
if (test.screenshot) console.log(` Screenshot: ${path.basename(test.screenshot)}`);
});
}
if (testResults.passed > 0) {
console.log('\n✅ PASSED TESTS:');
console.log('─'.repeat(50));
testResults.details.filter(t => t.passed).forEach((test, index) => {
console.log(`${index + 1}. ${test.name}`);
if (test.details) console.log(` Details: ${test.details}`);
});
}
// Recommendations
console.log('\n🔍 RECOMMENDATIONS:');
console.log('─'.repeat(50));
const authTest = testResults.details.find(t => t.name.includes('Login authentication'));
const createTest = testResults.details.find(t => t.name.includes('Event creation'));
const editTest = testResults.details.find(t => t.name.includes('Event update'));
if (!authTest?.passed) {
console.log('• Fix trainer authentication system');
console.log('• Verify test user credentials and permissions');
}
if (!createTest?.passed) {
console.log('• Debug TEC Community Events integration');
console.log('• Check event creation form accessibility');
console.log('• Verify required plugins are active');
}
if (eventId && !editTest?.passed) {
console.log('• Fix event editing permissions');
console.log('• Debug event update workflow');
}
if (testResults.failed === 0) {
console.log('• All tests passed! System is working correctly');
console.log('• Consider adding more edge case tests');
console.log('• Monitor performance and user experience');
}
console.log('\n' + '═'.repeat(70));
console.log('🏁 TEST SUITE COMPLETE');
console.log('═'.repeat(70));
// Return exit code based on results
process.exit(testResults.failed > 0 ? 1 : 0);
}
// Execute the test suite
if (require.main === module) {
runHVACTrainerEventsTest().catch(error => {
console.error('Fatal test error:', error);
process.exit(1);
});
}
module.exports = {
runHVACTrainerEventsTest,
CONFIG,
TEST_EVENT_DATA
};