## 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(); |