## Major Enhancements ### 🏗️ Architecture & Infrastructure - Implement comprehensive Docker testing infrastructure with hermetic environment - Add Forgejo Actions CI/CD pipeline for automated deployments - Create Page Object Model (POM) testing architecture reducing test duplication by 90% - Establish security-first development patterns with input validation and output escaping ### 🧪 Testing Framework Modernization - Migrate 146+ tests from 80 duplicate files to centralized architecture - Add comprehensive E2E test suites for all user roles and workflows - Implement WordPress error detection with automatic site health monitoring - Create robust browser lifecycle management with proper cleanup ### 📚 Documentation & Guides - Add comprehensive development best practices guide - Create detailed administrator setup documentation - Establish user guides for trainers and master trainers - Document security incident reports and migration guides ### 🔧 Core Plugin Features - Enhance trainer profile management with certification system - Improve find trainer functionality with advanced filtering - Strengthen master trainer area with content management - Add comprehensive venue and organizer management ### 🛡️ Security & Reliability - Implement security-first patterns throughout codebase - Add comprehensive input validation and output escaping - Create secure credential management system - Establish proper WordPress role-based access control ### 🎯 WordPress Integration - Strengthen singleton pattern implementation across all classes - Enhance template hierarchy with proper WordPress integration - Improve page manager with hierarchical URL structure - Add comprehensive shortcode and menu system ### 🔍 Developer Experience - Add extensive debugging and troubleshooting tools - Create comprehensive test data seeding scripts - Implement proper error handling and logging - Establish consistent code patterns and standards ### 📊 Performance & Optimization - Optimize database queries and caching strategies - Improve asset loading and script management - Enhance template rendering performance - Streamline user experience across all interfaces 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
309 lines
No EOL
13 KiB
JavaScript
309 lines
No EOL
13 KiB
JavaScript
#!/usr/bin/env node
|
||
|
||
/**
|
||
* Comprehensive Organizer Management Test
|
||
* Tests the complete organizer management workflow including authentication
|
||
*/
|
||
|
||
const { chromium } = require('playwright');
|
||
|
||
// Configuration
|
||
const config = {
|
||
BASE_URL: process.env.BASE_URL || 'http://localhost:8080',
|
||
HEADLESS: process.env.HEADLESS !== 'false',
|
||
USERNAME: process.env.TEST_USERNAME || 'testtrainer',
|
||
PASSWORD: process.env.TEST_PASSWORD || 'TestPass123!'
|
||
};
|
||
|
||
async function runComprehensiveOrganizerTest() {
|
||
console.log('🧪 Comprehensive Organizer Management Test');
|
||
console.log('==========================================\n');
|
||
|
||
const browser = await chromium.launch({
|
||
headless: config.HEADLESS,
|
||
args: ['--no-sandbox', '--disable-setuid-sandbox']
|
||
});
|
||
|
||
const page = await browser.newPage();
|
||
|
||
let testResults = {
|
||
passed: 0,
|
||
failed: 0,
|
||
skipped: 0,
|
||
details: []
|
||
};
|
||
|
||
try {
|
||
// Test 1: Login as trainer
|
||
console.log('1. Testing trainer login...');
|
||
|
||
try {
|
||
await page.goto(`${config.BASE_URL}/community-login/`);
|
||
await page.waitForLoadState('networkidle');
|
||
|
||
// Check if login form exists
|
||
const loginForm = await page.locator('#loginform');
|
||
if (await loginForm.isVisible()) {
|
||
await page.fill('#user_login', config.USERNAME);
|
||
await page.fill('#user_pass', config.PASSWORD);
|
||
await page.click('#wp-submit');
|
||
await page.waitForLoadState('networkidle');
|
||
|
||
// Check if redirected to trainer dashboard
|
||
const currentUrl = page.url();
|
||
if (currentUrl.includes('/trainer/dashboard/')) {
|
||
console.log(' ✅ Login successful');
|
||
testResults.passed++;
|
||
testResults.details.push('Login: ✅ Successful');
|
||
} else {
|
||
console.log(' ❌ Login failed - not redirected to dashboard');
|
||
testResults.failed++;
|
||
testResults.details.push('Login: ❌ Not redirected to dashboard');
|
||
}
|
||
} else {
|
||
console.log(' ⏭️ Login form not found - may already be logged in');
|
||
testResults.skipped++;
|
||
testResults.details.push('Login: ⏭️ Form not found');
|
||
}
|
||
} catch (error) {
|
||
console.log(` ❌ Login error: ${error.message}`);
|
||
testResults.failed++;
|
||
testResults.details.push(`Login: ❌ Error - ${error.message}`);
|
||
}
|
||
|
||
// Test 2: Access organizer list page
|
||
console.log('\n2. Testing organizer list page access...');
|
||
|
||
try {
|
||
await page.goto(`${config.BASE_URL}/trainer/organizer/list/`);
|
||
await page.waitForLoadState('networkidle');
|
||
|
||
const response = await page.goto(`${config.BASE_URL}/trainer/organizer/list/`, { waitUntil: 'networkidle' });
|
||
const status = response.status();
|
||
|
||
if (status === 200) {
|
||
const pageTitle = await page.locator('h1').textContent();
|
||
if (pageTitle && pageTitle.includes('Organizers')) {
|
||
console.log(' ✅ Organizer list page accessible');
|
||
testResults.passed++;
|
||
testResults.details.push('Organizer List: ✅ Accessible');
|
||
} else {
|
||
console.log(' ❌ Page accessible but title incorrect');
|
||
testResults.failed++;
|
||
testResults.details.push('Organizer List: ❌ Incorrect title');
|
||
}
|
||
} else {
|
||
console.log(` ❌ Organizer list page returned ${status}`);
|
||
testResults.failed++;
|
||
testResults.details.push(`Organizer List: ❌ Status ${status}`);
|
||
}
|
||
} catch (error) {
|
||
console.log(` ❌ Error accessing organizer list: ${error.message}`);
|
||
testResults.failed++;
|
||
testResults.details.push(`Organizer List: ❌ ${error.message}`);
|
||
}
|
||
|
||
// Test 3: Access organizer manage page
|
||
console.log('\n3. Testing organizer manage page access...');
|
||
|
||
try {
|
||
await page.goto(`${config.BASE_URL}/trainer/organizer/manage/`);
|
||
await page.waitForLoadState('networkidle');
|
||
|
||
const response = await page.goto(`${config.BASE_URL}/trainer/organizer/manage/`, { waitUntil: 'networkidle' });
|
||
const status = response.status();
|
||
|
||
if (status === 200) {
|
||
const pageTitle = await page.locator('h1').textContent();
|
||
if (pageTitle && (pageTitle.includes('Create') || pageTitle.includes('Organizer'))) {
|
||
console.log(' ✅ Organizer manage page accessible');
|
||
testResults.passed++;
|
||
testResults.details.push('Organizer Manage: ✅ Accessible');
|
||
} else {
|
||
console.log(' ❌ Page accessible but title incorrect');
|
||
testResults.failed++;
|
||
testResults.details.push('Organizer Manage: ❌ Incorrect title');
|
||
}
|
||
} else {
|
||
console.log(` ❌ Organizer manage page returned ${status}`);
|
||
testResults.failed++;
|
||
testResults.details.push(`Organizer Manage: ❌ Status ${status}`);
|
||
}
|
||
} catch (error) {
|
||
console.log(` ❌ Error accessing organizer manage: ${error.message}`);
|
||
testResults.failed++;
|
||
testResults.details.push(`Organizer Manage: ❌ ${error.message}`);
|
||
}
|
||
|
||
// Test 4: Check shortcode processing
|
||
console.log('\n4. Testing shortcode processing...');
|
||
|
||
try {
|
||
const content = await page.content();
|
||
const hasUnprocessedShortcode = content.includes('[hvac_trainer_organizer_manage]');
|
||
const hasFormContainer = content.includes('hvac-organizer-manage');
|
||
|
||
if (!hasUnprocessedShortcode && hasFormContainer) {
|
||
console.log(' ✅ Shortcode processed correctly');
|
||
testResults.passed++;
|
||
testResults.details.push('Shortcode: ✅ Processed correctly');
|
||
} else if (hasUnprocessedShortcode) {
|
||
console.log(' ❌ Shortcode not processed');
|
||
testResults.failed++;
|
||
testResults.details.push('Shortcode: ❌ Not processed');
|
||
} else {
|
||
console.log(' ❌ Form container not found');
|
||
testResults.failed++;
|
||
testResults.details.push('Shortcode: ❌ Form container not found');
|
||
}
|
||
} catch (error) {
|
||
console.log(` ❌ Error checking shortcode: ${error.message}`);
|
||
testResults.failed++;
|
||
testResults.details.push(`Shortcode: ❌ ${error.message}`);
|
||
}
|
||
|
||
// Test 5: Check form elements
|
||
console.log('\n5. Testing form elements...');
|
||
|
||
try {
|
||
const form = await page.locator('#hvac-organizer-form');
|
||
|
||
if (await form.isVisible()) {
|
||
console.log(' ✅ Main form visible');
|
||
|
||
// Check required fields
|
||
const requiredFields = ['org_name', 'hq_city', 'hq_state', 'hq_country'];
|
||
let fieldsFound = 0;
|
||
|
||
for (const field of requiredFields) {
|
||
const fieldElement = await page.locator(`#${field}`);
|
||
if (await fieldElement.isVisible()) {
|
||
fieldsFound++;
|
||
}
|
||
}
|
||
|
||
if (fieldsFound === requiredFields.length) {
|
||
console.log(' ✅ All required fields present');
|
||
testResults.passed++;
|
||
testResults.details.push('Form Fields: ✅ All present');
|
||
} else {
|
||
console.log(` ❌ Only ${fieldsFound}/${requiredFields.length} required fields found`);
|
||
testResults.failed++;
|
||
testResults.details.push(`Form Fields: ❌ Only ${fieldsFound}/${requiredFields.length} found`);
|
||
}
|
||
} else {
|
||
console.log(' ❌ Main form not visible');
|
||
testResults.failed++;
|
||
testResults.details.push('Form Fields: ❌ Form not visible');
|
||
}
|
||
} catch (error) {
|
||
console.log(` ❌ Error checking form elements: ${error.message}`);
|
||
testResults.failed++;
|
||
testResults.details.push(`Form Elements: ❌ ${error.message}`);
|
||
}
|
||
|
||
// Test 6: Check assets loading
|
||
console.log('\n6. Testing assets loading...');
|
||
|
||
try {
|
||
const content = await page.content();
|
||
const cssLoaded = content.includes('hvac-organizers.css') || content.includes('hvac-organizers-style');
|
||
const jsLoaded = content.includes('hvac-organizers.js');
|
||
|
||
if (cssLoaded && jsLoaded) {
|
||
console.log(' ✅ CSS and JS assets loaded');
|
||
testResults.passed++;
|
||
testResults.details.push('Assets: ✅ CSS and JS loaded');
|
||
} else if (cssLoaded) {
|
||
console.log(' ⚠️ CSS loaded but JS missing');
|
||
testResults.failed++;
|
||
testResults.details.push('Assets: ❌ JS missing');
|
||
} else if (jsLoaded) {
|
||
console.log(' ⚠️ JS loaded but CSS missing');
|
||
testResults.failed++;
|
||
testResults.details.push('Assets: ❌ CSS missing');
|
||
} else {
|
||
console.log(' ❌ Neither CSS nor JS loaded');
|
||
testResults.failed++;
|
||
testResults.details.push('Assets: ❌ Neither CSS nor JS loaded');
|
||
}
|
||
} catch (error) {
|
||
console.log(` ❌ Error checking assets: ${error.message}`);
|
||
testResults.failed++;
|
||
testResults.details.push(`Assets: ❌ ${error.message}`);
|
||
}
|
||
|
||
// Test 7: Check navigation
|
||
console.log('\n7. Testing navigation elements...');
|
||
|
||
try {
|
||
const hasNavigation = await page.locator('.hvac-menu, .trainer-menu').isVisible();
|
||
const hasBreadcrumbs = await page.locator('.hvac-breadcrumb, .breadcrumb').isVisible();
|
||
|
||
let navScore = 0;
|
||
if (hasNavigation) {
|
||
console.log(' ✅ Navigation menu found');
|
||
navScore++;
|
||
}
|
||
if (hasBreadcrumbs) {
|
||
console.log(' ✅ Breadcrumbs found');
|
||
navScore++;
|
||
}
|
||
|
||
if (navScore === 2) {
|
||
testResults.passed++;
|
||
testResults.details.push('Navigation: ✅ Menu and breadcrumbs present');
|
||
} else if (navScore === 1) {
|
||
testResults.passed++;
|
||
testResults.details.push('Navigation: ⚠️ Partial navigation present');
|
||
} else {
|
||
testResults.failed++;
|
||
testResults.details.push('Navigation: ❌ No navigation elements found');
|
||
}
|
||
} catch (error) {
|
||
console.log(` ❌ Error checking navigation: ${error.message}`);
|
||
testResults.failed++;
|
||
testResults.details.push(`Navigation: ❌ ${error.message}`);
|
||
}
|
||
|
||
} catch (globalError) {
|
||
console.log(`💥 Global test error: ${globalError.message}`);
|
||
testResults.failed++;
|
||
testResults.details.push(`Global: ❌ ${globalError.message}`);
|
||
} finally {
|
||
await browser.close();
|
||
}
|
||
|
||
// Print results
|
||
console.log('\n📊 Test Results Summary');
|
||
console.log('=======================');
|
||
console.log(`✅ Passed: ${testResults.passed}`);
|
||
console.log(`❌ Failed: ${testResults.failed}`);
|
||
console.log(`⏭️ Skipped: ${testResults.skipped}`);
|
||
|
||
const total = testResults.passed + testResults.failed;
|
||
const successRate = total > 0 ? Math.round((testResults.passed / total) * 100) : 0;
|
||
console.log(`📈 Success Rate: ${successRate}%`);
|
||
|
||
console.log('\n📋 Detailed Results:');
|
||
testResults.details.forEach(detail => {
|
||
console.log(` ${detail}`);
|
||
});
|
||
|
||
if (successRate >= 80) {
|
||
console.log('\n🎉 Organizer management functionality is working well!');
|
||
} else if (successRate >= 50) {
|
||
console.log('\n⚠️ Organizer management has some issues but basic functionality works.');
|
||
} else {
|
||
console.log('\n❌ Organizer management needs significant fixes.');
|
||
}
|
||
|
||
return testResults;
|
||
}
|
||
|
||
// Run the test
|
||
if (require.main === module) {
|
||
runComprehensiveOrganizerTest().catch(console.error);
|
||
}
|
||
|
||
module.exports = runComprehensiveOrganizerTest; |