## 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>
130 lines
No EOL
4.6 KiB
JavaScript
130 lines
No EOL
4.6 KiB
JavaScript
const { chromium } = require('playwright');
|
|
|
|
console.log('🔧 FIND A TRAINER MODAL DEBUG');
|
|
console.log('============================');
|
|
|
|
const BASE_URL = process.env.BASE_URL || 'https://upskill-staging.measurequick.com';
|
|
|
|
(async () => {
|
|
let browser;
|
|
|
|
try {
|
|
browser = await chromium.launch({
|
|
headless: false, // Keep visible for debugging
|
|
timeout: 30000
|
|
});
|
|
|
|
const page = await browser.newPage();
|
|
|
|
console.log('🌐 Loading Find a Trainer page...');
|
|
await page.goto(`${BASE_URL}/find-a-trainer/`);
|
|
await page.waitForLoadState('networkidle', { timeout: 20000 });
|
|
|
|
// Check initial modal state
|
|
console.log('\n🔍 Initial modal state...');
|
|
const modalExists = await page.locator('#hvac-filter-modal').count();
|
|
console.log(`Modal element exists: ${modalExists > 0}`);
|
|
|
|
if (modalExists > 0) {
|
|
const modalStyle = await page.locator('#hvac-filter-modal').getAttribute('style');
|
|
console.log(`Modal initial style: ${modalStyle}`);
|
|
|
|
const computedStyle = await page.locator('#hvac-filter-modal').evaluate(el => {
|
|
const computed = window.getComputedStyle(el);
|
|
return {
|
|
display: computed.display,
|
|
visibility: computed.visibility,
|
|
opacity: computed.opacity
|
|
};
|
|
});
|
|
console.log(`Modal computed styles:`, computedStyle);
|
|
}
|
|
|
|
// Check filter button and click
|
|
console.log('\n🔘 Testing filter button click...');
|
|
const formatButton = await page.locator('.hvac-filter-btn[data-filter="training_format"]');
|
|
const buttonExists = await formatButton.count();
|
|
console.log(`Training Format button exists: ${buttonExists > 0}`);
|
|
|
|
if (buttonExists > 0) {
|
|
console.log('🖱️ Clicking Training Format button...');
|
|
await formatButton.click();
|
|
|
|
// Wait a moment for any AJAX/JS to execute
|
|
await page.waitForTimeout(2000);
|
|
|
|
// Check modal state after click
|
|
console.log('\n📋 Modal state after click...');
|
|
const modalVisible = await page.locator('#hvac-filter-modal').isVisible();
|
|
console.log(`Modal visible: ${modalVisible}`);
|
|
|
|
const modalStyleAfter = await page.locator('#hvac-filter-modal').getAttribute('style');
|
|
console.log(`Modal style after click: ${modalStyleAfter}`);
|
|
|
|
// Check if AJAX was called
|
|
const hasLoading = await formatButton.getAttribute('class');
|
|
console.log(`Button classes after click: ${hasLoading}`);
|
|
|
|
// Try to manually show the modal for debugging
|
|
console.log('\n🔧 Manual modal display test...');
|
|
await page.locator('#hvac-filter-modal').evaluate(el => {
|
|
el.style.display = 'flex';
|
|
el.style.visibility = 'visible';
|
|
el.style.opacity = '1';
|
|
});
|
|
|
|
await page.waitForTimeout(1000);
|
|
const manualVisible = await page.locator('#hvac-filter-modal').isVisible();
|
|
console.log(`Modal visible after manual style change: ${manualVisible}`);
|
|
|
|
// Check if modal content was populated
|
|
const modalTitle = await page.locator('.hvac-filter-modal-title').textContent();
|
|
const optionsCount = await page.locator('.hvac-filter-option').count();
|
|
console.log(`Modal title: "${modalTitle}"`);
|
|
console.log(`Filter options count: ${optionsCount}`);
|
|
}
|
|
|
|
// Check console logs for errors
|
|
console.log('\n🔍 Checking JavaScript console...');
|
|
page.on('console', msg => {
|
|
console.log(` JS ${msg.type()}: ${msg.text()}`);
|
|
});
|
|
|
|
// Check if AJAX endpoint is working
|
|
console.log('\n🔄 Testing AJAX endpoint directly...');
|
|
const ajaxResponse = await page.evaluate(async () => {
|
|
const formData = new FormData();
|
|
formData.append('action', 'hvac_get_filter_options');
|
|
formData.append('filter_type', 'training_format');
|
|
|
|
try {
|
|
const response = await fetch('/wp-admin/admin-ajax.php', {
|
|
method: 'POST',
|
|
body: formData
|
|
});
|
|
|
|
const text = await response.text();
|
|
return {
|
|
status: response.status,
|
|
ok: response.ok,
|
|
response: text.substring(0, 200) + '...'
|
|
};
|
|
} catch (e) {
|
|
return { error: e.message };
|
|
}
|
|
});
|
|
|
|
console.log('AJAX Response:', ajaxResponse);
|
|
|
|
// Keep browser open for manual inspection
|
|
console.log('\n⏳ Keeping browser open for 30 seconds for manual inspection...');
|
|
await page.waitForTimeout(30000);
|
|
|
|
} catch (error) {
|
|
console.error('\n💥 Error:', error.message);
|
|
} finally {
|
|
if (browser) {
|
|
await browser.close();
|
|
}
|
|
}
|
|
})(); |