## 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>
		
			
				
	
	
		
			289 lines
		
	
	
		
			No EOL
		
	
	
		
			10 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			289 lines
		
	
	
		
			No EOL
		
	
	
		
			10 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| #!/usr/bin/env node
 | ||
| 
 | ||
| /**
 | ||
|  * Training Leads Implementation and Testing Script
 | ||
|  * Tests and validates the training leads functionality
 | ||
|  */
 | ||
| 
 | ||
| const { chromium } = require('playwright');
 | ||
| const fs = require('fs');
 | ||
| 
 | ||
| class TrainingLeadsTestSuite {
 | ||
|     constructor() {
 | ||
|         this.browser = null;
 | ||
|         this.page = null;
 | ||
|         this.baseUrl = process.env.BASE_URL || 'http://localhost:8080';
 | ||
|     }
 | ||
| 
 | ||
|     async setupBrowser() {
 | ||
|         console.log('🚀 Starting Training Leads Test Suite...');
 | ||
|         this.browser = await chromium.launch({ 
 | ||
|             headless: process.env.HEADLESS !== 'false' 
 | ||
|         });
 | ||
|         this.page = await this.browser.newPage();
 | ||
|     }
 | ||
| 
 | ||
|     async testWordPressSetup() {
 | ||
|         console.log('\n📋 Phase 1: Testing WordPress Environment...');
 | ||
|         
 | ||
|         try {
 | ||
|             await this.page.goto(this.baseUrl, { waitUntil: 'networkidle' });
 | ||
|             console.log('✅ WordPress is accessible');
 | ||
|             
 | ||
|             // Check if we can access admin area
 | ||
|             await this.page.goto(`${this.baseUrl}/wp-admin/`, { waitUntil: 'networkidle' });
 | ||
|             const currentUrl = this.page.url();
 | ||
|             
 | ||
|             if (currentUrl.includes('wp-login')) {
 | ||
|                 console.log('ℹ️  Redirected to login - WordPress is working');
 | ||
|             } else {
 | ||
|                 console.log('✅ WordPress admin accessible');
 | ||
|             }
 | ||
|             
 | ||
|         } catch (error) {
 | ||
|             console.error('❌ WordPress setup issue:', error.message);
 | ||
|             return false;
 | ||
|         }
 | ||
|         
 | ||
|         return true;
 | ||
|     }
 | ||
| 
 | ||
|     async testPluginPresence() {
 | ||
|         console.log('\n📋 Phase 2: Testing HVAC Plugin Presence...');
 | ||
|         
 | ||
|         try {
 | ||
|             // Check if custom URL routes work
 | ||
|             await this.page.goto(`${this.baseUrl}/trainer/`, { waitUntil: 'networkidle' });
 | ||
|             const trainerPageContent = await this.page.textContent('body');
 | ||
|             
 | ||
|             if (trainerPageContent.includes('Not Found')) {
 | ||
|                 console.log('❌ HVAC plugin routes not working - plugin may not be active');
 | ||
|                 return false;
 | ||
|             } else {
 | ||
|                 console.log('✅ HVAC plugin routes working');
 | ||
|             }
 | ||
|             
 | ||
|         } catch (error) {
 | ||
|             console.error('❌ Plugin test failed:', error.message);
 | ||
|             return false;
 | ||
|         }
 | ||
|         
 | ||
|         return true;
 | ||
|     }
 | ||
| 
 | ||
|     async testTrainingLeadsPage() {
 | ||
|         console.log('\n📋 Phase 3: Testing Training Leads Page...');
 | ||
|         
 | ||
|         try {
 | ||
|             await this.page.goto(`${this.baseUrl}/trainer/profile/training-leads/`, { 
 | ||
|                 waitUntil: 'networkidle' 
 | ||
|             });
 | ||
|             
 | ||
|             const currentUrl = this.page.url();
 | ||
|             const pageContent = await this.page.textContent('body');
 | ||
|             
 | ||
|             console.log('Current URL:', currentUrl);
 | ||
|             
 | ||
|             if (pageContent.includes('Not Found')) {
 | ||
|                 console.log('❌ Training leads page returns 404');
 | ||
|                 await this.diagnoseRoutingIssue();
 | ||
|                 return false;
 | ||
|             }
 | ||
|             
 | ||
|             if (currentUrl.includes('login')) {
 | ||
|                 console.log('✅ Properly redirects to login for unauthenticated users');
 | ||
|                 return await this.testWithAuthentication();
 | ||
|             }
 | ||
|             
 | ||
|             // Check for training leads content
 | ||
|             const hasTrainingLeadsWrapper = await this.page.locator('.hvac-training-leads-wrapper').count() > 0;
 | ||
|             const hasShortcodeText = pageContent.includes('[hvac_trainer_training_leads]');
 | ||
|             
 | ||
|             if (hasShortcodeText) {
 | ||
|                 console.log('❌ Shortcode not processed - raw shortcode visible');
 | ||
|                 await this.diagnoseShortcodeIssue();
 | ||
|                 return false;
 | ||
|             }
 | ||
|             
 | ||
|             if (hasTrainingLeadsWrapper) {
 | ||
|                 console.log('✅ Training leads page renders correctly');
 | ||
|                 return true;
 | ||
|             }
 | ||
|             
 | ||
|             console.log('❌ Training leads content not found');
 | ||
|             return false;
 | ||
|             
 | ||
|         } catch (error) {
 | ||
|             console.error('❌ Training leads page test failed:', error.message);
 | ||
|             return false;
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     async testWithAuthentication() {
 | ||
|         console.log('\n📋 Phase 4: Testing with Authentication...');
 | ||
|         
 | ||
|         try {
 | ||
|             // Try to login
 | ||
|             const loginForm = await this.page.locator('form').first();
 | ||
|             if (await loginForm.count() > 0) {
 | ||
|                 await this.page.fill('input[name="log"]', 'trainer1');
 | ||
|                 await this.page.fill('input[name="pwd"]', 'password123');
 | ||
|                 await this.page.click('input[type="submit"]');
 | ||
|                 await this.page.waitForNavigation({ waitUntil: 'networkidle' });
 | ||
|             }
 | ||
|             
 | ||
|             // Navigate back to training leads page
 | ||
|             await this.page.goto(`${this.baseUrl}/trainer/profile/training-leads/`, { 
 | ||
|                 waitUntil: 'networkidle' 
 | ||
|             });
 | ||
|             
 | ||
|             const pageContent = await this.page.textContent('body');
 | ||
|             const hasTrainingLeadsWrapper = await this.page.locator('.hvac-training-leads-wrapper').count() > 0;
 | ||
|             
 | ||
|             if (hasTrainingLeadsWrapper) {
 | ||
|                 console.log('✅ Training leads page works after authentication');
 | ||
|                 return true;
 | ||
|             } else {
 | ||
|                 console.log('❌ Authentication successful but training leads page still not working');
 | ||
|                 console.log('Page preview:', pageContent.substring(0, 300));
 | ||
|                 return false;
 | ||
|             }
 | ||
|             
 | ||
|         } catch (error) {
 | ||
|             console.error('❌ Authentication test failed:', error.message);
 | ||
|             return false;
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     async diagnoseRoutingIssue() {
 | ||
|         console.log('\n🔍 Diagnosing routing issue...');
 | ||
|         
 | ||
|         // Check if other trainer pages work
 | ||
|         const testUrls = [
 | ||
|             '/trainer/',
 | ||
|             '/trainer/dashboard/',
 | ||
|             '/trainer/profile/'
 | ||
|         ];
 | ||
|         
 | ||
|         for (const url of testUrls) {
 | ||
|             try {
 | ||
|                 await this.page.goto(`${this.baseUrl}${url}`, { waitUntil: 'networkidle' });
 | ||
|                 const content = await this.page.textContent('body');
 | ||
|                 const works = !content.includes('Not Found');
 | ||
|                 console.log(`- ${url}: ${works ? '✅ Works' : '❌ 404'}`);
 | ||
|             } catch (error) {
 | ||
|                 console.log(`- ${url}: ❌ Error - ${error.message}`);
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     async diagnoseShortcodeIssue() {
 | ||
|         console.log('\n🔍 Diagnosing shortcode processing issue...');
 | ||
|         
 | ||
|         const pageContent = await this.page.textContent('body');
 | ||
|         
 | ||
|         if (pageContent.includes('HVAC_Training_Leads')) {
 | ||
|             console.log('- Class name visible in output - possible PHP error');
 | ||
|         }
 | ||
|         
 | ||
|         if (pageContent.includes('do_shortcode')) {
 | ||
|             console.log('- do_shortcode visible - template processing issue');
 | ||
|         }
 | ||
|         
 | ||
|         if (pageContent.includes('class_exists')) {
 | ||
|             console.log('- class_exists check visible - class loading issue');
 | ||
|         }
 | ||
|         
 | ||
|         // Check for PHP errors in page source
 | ||
|         const htmlContent = await this.page.content();
 | ||
|         if (htmlContent.includes('Fatal error') || htmlContent.includes('Warning:') || htmlContent.includes('Notice:')) {
 | ||
|             console.log('- PHP errors detected in page source');
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     async generateImplementationReport() {
 | ||
|         console.log('\n📊 Generating Implementation Report...');
 | ||
|         
 | ||
|         const report = {
 | ||
|             timestamp: new Date().toISOString(),
 | ||
|             baseUrl: this.baseUrl,
 | ||
|             findings: {
 | ||
|                 wordpressWorking: await this.testWordPressSetup(),
 | ||
|                 pluginActive: await this.testPluginPresence(),
 | ||
|                 trainingLeadsWorking: await this.testTrainingLeadsPage()
 | ||
|             },
 | ||
|             recommendations: []
 | ||
|         };
 | ||
|         
 | ||
|         if (!report.findings.pluginActive) {
 | ||
|             report.recommendations.push('Activate HVAC Plugin in WordPress admin');
 | ||
|             report.recommendations.push('Flush rewrite rules: wp rewrite flush');
 | ||
|         }
 | ||
|         
 | ||
|         if (!report.findings.trainingLeadsWorking) {
 | ||
|             report.recommendations.push('Check HVAC_Training_Leads class initialization');
 | ||
|             report.recommendations.push('Verify shortcode registration');
 | ||
|             report.recommendations.push('Check template file loading');
 | ||
|         }
 | ||
|         
 | ||
|         console.log('\n📋 IMPLEMENTATION REPORT:');
 | ||
|         console.log('='.repeat(50));
 | ||
|         console.log(`WordPress Working: ${report.findings.wordpressWorking ? '✅' : '❌'}`);
 | ||
|         console.log(`Plugin Active: ${report.findings.pluginActive ? '✅' : '❌'}`);
 | ||
|         console.log(`Training Leads Working: ${report.findings.trainingLeadsWorking ? '✅' : '❌'}`);
 | ||
|         
 | ||
|         if (report.recommendations.length > 0) {
 | ||
|             console.log('\n🔧 RECOMMENDATIONS:');
 | ||
|             report.recommendations.forEach((rec, index) => {
 | ||
|                 console.log(`${index + 1}. ${rec}`);
 | ||
|             });
 | ||
|         }
 | ||
|         
 | ||
|         // Save report to file
 | ||
|         fs.writeFileSync(
 | ||
|             '/home/ben/dev/upskill-event-manager/training-leads-test-report.json',
 | ||
|             JSON.stringify(report, null, 2)
 | ||
|         );
 | ||
|         
 | ||
|         return report;
 | ||
|     }
 | ||
| 
 | ||
|     async cleanup() {
 | ||
|         if (this.browser) {
 | ||
|             await this.browser.close();
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     async run() {
 | ||
|         try {
 | ||
|             await this.setupBrowser();
 | ||
|             const report = await this.generateImplementationReport();
 | ||
|             
 | ||
|             if (report.findings.trainingLeadsWorking) {
 | ||
|                 console.log('\n🎉 SUCCESS: Training Leads page is working correctly!');
 | ||
|                 return true;
 | ||
|             } else {
 | ||
|                 console.log('\n🔧 ACTION REQUIRED: Training Leads page needs implementation fixes');
 | ||
|                 return false;
 | ||
|             }
 | ||
|         } catch (error) {
 | ||
|             console.error('❌ Test suite failed:', error);
 | ||
|             return false;
 | ||
|         } finally {
 | ||
|             await this.cleanup();
 | ||
|         }
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| // Run the test suite
 | ||
| if (require.main === module) {
 | ||
|     const testSuite = new TrainingLeadsTestSuite();
 | ||
|     testSuite.run().then(success => {
 | ||
|         process.exit(success ? 0 : 1);
 | ||
|     }).catch(error => {
 | ||
|         console.error('Fatal error:', error);
 | ||
|         process.exit(1);
 | ||
|     });
 | ||
| }
 | ||
| 
 | ||
| module.exports = TrainingLeadsTestSuite; |