## 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>
		
			
				
	
	
		
			269 lines
		
	
	
		
			No EOL
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			269 lines
		
	
	
		
			No EOL
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| #!/usr/bin/env node
 | |
| 
 | |
| /**
 | |
|  * Complete Organizer Management Test with Full Authentication
 | |
|  */
 | |
| 
 | |
| const { chromium } = require('playwright');
 | |
| 
 | |
| const config = {
 | |
|     BASE_URL: process.env.BASE_URL || 'http://localhost:8080',
 | |
|     HEADLESS: process.env.HEADLESS !== 'false',
 | |
|     USERNAME: 'testtrainer',
 | |
|     PASSWORD: 'TestPass123!'
 | |
| };
 | |
| 
 | |
| async function completeOrganizerTest() {
 | |
|     console.log('🧪 Complete 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();
 | |
|     
 | |
|     // Enable request/response logging for debugging
 | |
|     page.on('response', response => {
 | |
|         if (response.url().includes('/trainer/organizer')) {
 | |
|             console.log(`   Response: ${response.status()} ${response.url()}`);
 | |
|         }
 | |
|     });
 | |
|     
 | |
|     try {
 | |
|         // Step 1: Start fresh with login
 | |
|         console.log('1. Starting fresh login process...');
 | |
|         await page.goto(`${config.BASE_URL}/training-login/`);
 | |
|         await page.waitForLoadState('networkidle');
 | |
|         
 | |
|         // Look for login form
 | |
|         const loginForm = await page.locator('form[action*="wp-login"], #loginform, form.login-form').first();
 | |
|         
 | |
|         if (await loginForm.isVisible()) {
 | |
|             console.log('   Login form found, proceeding with login...');
 | |
|             
 | |
|             // Fill username and password
 | |
|             await page.fill('input[name="log"], input[name="user_login"], #user_login', config.USERNAME);
 | |
|             await page.fill('input[name="pwd"], input[name="user_pass"], #user_pass', config.PASSWORD);
 | |
|             
 | |
|             // Submit form
 | |
|             await page.click('input[type="submit"], button[type="submit"], #wp-submit');
 | |
|             await page.waitForLoadState('networkidle');
 | |
|             
 | |
|             // Wait for redirect
 | |
|             await page.waitForTimeout(3000);
 | |
|             
 | |
|             const postLoginUrl = page.url();
 | |
|             console.log(`   After login URL: ${postLoginUrl}`);
 | |
|             
 | |
|             if (postLoginUrl.includes('trainer/dashboard') || postLoginUrl.includes('dashboard')) {
 | |
|                 console.log('   ✅ Login successful, on dashboard');
 | |
|             } else if (postLoginUrl.includes('login')) {
 | |
|                 console.log('   ❌ Login failed, still on login page');
 | |
|                 
 | |
|                 // Check for error messages
 | |
|                 const errorMsg = await page.locator('.login_error, .message.error, .notice-error').textContent().catch(() => '');
 | |
|                 if (errorMsg) {
 | |
|                     console.log(`   Error message: ${errorMsg}`);
 | |
|                 }
 | |
|                 return;
 | |
|             } else {
 | |
|                 console.log('   ⚠️ Login completed, redirected to different page');
 | |
|             }
 | |
|         } else {
 | |
|             console.log('   No login form found, may already be logged in');
 | |
|         }
 | |
|         
 | |
|         // Step 2: Force navigate to trainer dashboard to establish session
 | |
|         console.log('\n2. Establishing authenticated session...');
 | |
|         const dashResponse = await page.goto(`${config.BASE_URL}/trainer/dashboard/`);
 | |
|         await page.waitForLoadState('networkidle');
 | |
|         
 | |
|         const dashUrl = page.url();
 | |
|         const dashTitle = await page.title();
 | |
|         console.log(`   Dashboard response: ${dashResponse.status()}`);
 | |
|         console.log(`   Dashboard URL: ${dashUrl}`);
 | |
|         console.log(`   Dashboard title: "${dashTitle}"`);
 | |
|         
 | |
|         // If still being redirected to login, the authentication is not working
 | |
|         if (dashUrl.includes('login') || dashTitle.includes('Login')) {
 | |
|             console.log('   ❌ Authentication failed - still being redirected to login');
 | |
|             
 | |
|             // Try alternative approach: direct authentication via WordPress
 | |
|             console.log('   Trying direct WordPress login...');
 | |
|             await page.goto(`${config.BASE_URL}/wp-admin/`);
 | |
|             await page.waitForLoadState('networkidle');
 | |
|             
 | |
|             if (page.url().includes('wp-login.php')) {
 | |
|                 await page.fill('#user_login', config.USERNAME);
 | |
|                 await page.fill('#user_pass', config.PASSWORD);
 | |
|                 await page.click('#wp-submit');
 | |
|                 await page.waitForLoadState('networkidle');
 | |
|                 
 | |
|                 if (page.url().includes('wp-admin')) {
 | |
|                     console.log('   ✅ WordPress admin login successful');
 | |
|                     
 | |
|                     // Now try trainer dashboard again
 | |
|                     await page.goto(`${config.BASE_URL}/trainer/dashboard/`);
 | |
|                     await page.waitForLoadState('networkidle');
 | |
|                     
 | |
|                     const newDashUrl = page.url();
 | |
|                     if (!newDashUrl.includes('login')) {
 | |
|                         console.log('   ✅ Trainer dashboard now accessible');
 | |
|                     } else {
 | |
|                         console.log('   ❌ Still cannot access trainer dashboard');
 | |
|                         return;
 | |
|                     }
 | |
|                 } else {
 | |
|                     console.log('   ❌ WordPress admin login also failed');
 | |
|                     return;
 | |
|                 }
 | |
|             } else {
 | |
|                 console.log('   ✅ Already logged into WordPress admin');
 | |
|             }
 | |
|         } else {
 | |
|             console.log('   ✅ Authenticated session established');
 | |
|         }
 | |
|         
 | |
|         // Step 3: Test organizer list page
 | |
|         console.log('\n3. Testing organizer list page...');
 | |
|         const listResponse = await page.goto(`${config.BASE_URL}/trainer/organizer/list/`);
 | |
|         await page.waitForLoadState('networkidle');
 | |
|         await page.waitForTimeout(2000); // Give shortcodes time to process
 | |
|         
 | |
|         const listUrl = page.url();
 | |
|         const listTitle = await page.title();
 | |
|         console.log(`   Status: ${listResponse.status()}`);
 | |
|         console.log(`   URL: ${listUrl}`);
 | |
|         console.log(`   Title: "${listTitle}"`);
 | |
|         
 | |
|         if (listResponse.status() === 200 && !listUrl.includes('login') && !listTitle.includes('Login')) {
 | |
|             console.log('   ✅ Organizer list page accessible');
 | |
|             
 | |
|             // Check page content
 | |
|             const content = await page.content();
 | |
|             console.log('\n   Content analysis:');
 | |
|             console.log(`   - Page length: ${content.length} characters`);
 | |
|             console.log(`   - Contains shortcode: ${content.includes('[hvac_trainer_organizers_list]') ? 'Yes ❌' : 'No ✅'}`);
 | |
|             console.log(`   - Contains container: ${content.includes('hvac-organizers-list') ? 'Yes ✅' : 'No ❌'}`);
 | |
|             console.log(`   - Contains table: ${content.includes('hvac-organizers-table') ? 'Yes ✅' : 'No ❌'}`);
 | |
|             console.log(`   - Contains "Add New" button: ${content.includes('Add New Organizer') ? 'Yes ✅' : 'No ❌'}`);
 | |
|             
 | |
|             // Check visible elements
 | |
|             const addButton = await page.locator('a[href*="/trainer/organizer/manage/"]').isVisible();
 | |
|             const organizersTable = await page.locator('.hvac-organizers-table').isVisible();
 | |
|             console.log(`   - Add button visible: ${addButton ? 'Yes ✅' : 'No ❌'}`);
 | |
|             console.log(`   - Table visible: ${organizersTable ? 'Yes ✅' : 'No ❌'}`);
 | |
|             
 | |
|         } else {
 | |
|             console.log(`   ❌ Organizer list page not accessible (Status: ${listResponse.status()})`);
 | |
|         }
 | |
|         
 | |
|         // Step 4: Test organizer manage page
 | |
|         console.log('\n4. Testing organizer manage page...');
 | |
|         const manageResponse = await page.goto(`${config.BASE_URL}/trainer/organizer/manage/`);
 | |
|         await page.waitForLoadState('networkidle');
 | |
|         await page.waitForTimeout(2000); // Give shortcodes time to process
 | |
|         
 | |
|         const manageUrl = page.url();
 | |
|         const manageTitle = await page.title();
 | |
|         console.log(`   Status: ${manageResponse.status()}`);
 | |
|         console.log(`   URL: ${manageUrl}`);
 | |
|         console.log(`   Title: "${manageTitle}"`);
 | |
|         
 | |
|         if (manageResponse.status() === 200 && !manageUrl.includes('login') && !manageTitle.includes('Login')) {
 | |
|             console.log('   ✅ Organizer manage page accessible');
 | |
|             
 | |
|             // Check page content
 | |
|             const content = await page.content();
 | |
|             console.log('\n   Content analysis:');
 | |
|             console.log(`   - Page length: ${content.length} characters`);
 | |
|             console.log(`   - Contains shortcode: ${content.includes('[hvac_trainer_organizer_manage]') ? 'Yes ❌' : 'No ✅'}`);
 | |
|             console.log(`   - Contains container: ${content.includes('hvac-organizer-manage') ? 'Yes ✅' : 'No ❌'}`);
 | |
|             console.log(`   - Contains form: ${content.includes('hvac-organizer-form') ? 'Yes ✅' : 'No ❌'}`);
 | |
|             console.log(`   - Contains name field: ${content.includes('org_name') ? 'Yes ✅' : 'No ❌'}`);
 | |
|             
 | |
|             // Check visible elements
 | |
|             const organizerForm = await page.locator('#hvac-organizer-form').isVisible();
 | |
|             const nameField = await page.locator('#org_name').isVisible();
 | |
|             const cityField = await page.locator('#hq_city').isVisible();
 | |
|             const submitButton = await page.locator('button[type="submit"]').isVisible();
 | |
|             
 | |
|             console.log(`   - Form visible: ${organizerForm ? 'Yes ✅' : 'No ❌'}`);
 | |
|             console.log(`   - Name field visible: ${nameField ? 'Yes ✅' : 'No ❌'}`);
 | |
|             console.log(`   - City field visible: ${cityField ? 'Yes ✅' : 'No ❌'}`);
 | |
|             console.log(`   - Submit button visible: ${submitButton ? 'Yes ✅' : 'No ❌'}`);
 | |
|             
 | |
|             // Step 5: Test form functionality if visible
 | |
|             if (organizerForm && nameField) {
 | |
|                 console.log('\n5. Testing form functionality...');
 | |
|                 
 | |
|                 try {
 | |
|                     await page.fill('#org_name', 'Test Organization');
 | |
|                     await page.fill('#hq_city', 'Test City');
 | |
|                     await page.fill('#hq_state', 'Test State');
 | |
|                     await page.selectOption('#hq_country', 'United States');
 | |
|                     
 | |
|                     console.log('   ✅ Form fields can be filled');
 | |
|                     
 | |
|                     // Check if form validation works
 | |
|                     await page.fill('#org_name', '');
 | |
|                     if (submitButton) {
 | |
|                         await page.click('button[type="submit"]');
 | |
|                         await page.waitForTimeout(1000);
 | |
|                         
 | |
|                         const errorMessage = await page.locator('.hvac-error-message').isVisible();
 | |
|                         console.log(`   - Validation errors shown: ${errorMessage ? 'Yes ✅' : 'No ❌'}`);
 | |
|                     }
 | |
|                     
 | |
|                 } catch (error) {
 | |
|                     console.log(`   ❌ Error testing form: ${error.message}`);
 | |
|                 }
 | |
|             } else {
 | |
|                 console.log('\n5. Form not available for testing');
 | |
|             }
 | |
|             
 | |
|         } else {
 | |
|             console.log(`   ❌ Organizer manage page not accessible (Status: ${manageResponse.status()})`);
 | |
|         }
 | |
|         
 | |
|         // Final summary
 | |
|         console.log('\n📊 Test Summary');
 | |
|         console.log('===============');
 | |
|         
 | |
|         const tests = [];
 | |
|         
 | |
|         if (listResponse.status() === 200 && !listUrl.includes('login')) {
 | |
|             tests.push('✅ Organizer list page accessible');
 | |
|         } else {
 | |
|             tests.push('❌ Organizer list page not accessible');
 | |
|         }
 | |
|         
 | |
|         if (manageResponse.status() === 200 && !manageUrl.includes('login')) {
 | |
|             tests.push('✅ Organizer manage page accessible');
 | |
|         } else {
 | |
|             tests.push('❌ Organizer manage page not accessible');
 | |
|         }
 | |
|         
 | |
|         tests.forEach(test => console.log(`   ${test}`));
 | |
|         
 | |
|         const passedTests = tests.filter(t => t.includes('✅')).length;
 | |
|         const totalTests = tests.length;
 | |
|         
 | |
|         console.log(`\nResult: ${passedTests}/${totalTests} tests passed`);
 | |
|         
 | |
|         if (passedTests === totalTests) {
 | |
|             console.log('🎉 Organizer management is working correctly!');
 | |
|         } else {
 | |
|             console.log('⚠️ Some organizer management issues remain');
 | |
|         }
 | |
|         
 | |
|     } catch (error) {
 | |
|         console.error(`❌ Test error: ${error.message}`);
 | |
|     } finally {
 | |
|         await browser.close();
 | |
|     }
 | |
| }
 | |
| 
 | |
| completeOrganizerTest(); |