## 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>
332 lines
No EOL
14 KiB
JavaScript
332 lines
No EOL
14 KiB
JavaScript
/**
|
||
* Test script for the new trainer certification system
|
||
*
|
||
* This script will:
|
||
* 1. Create sample certification data via WordPress CLI
|
||
* 2. Test the trainer profile display with Playwright
|
||
* 3. Verify the new certification cards are working
|
||
*/
|
||
|
||
const { chromium } = require('playwright');
|
||
const { execSync } = require('child_process');
|
||
|
||
// Configuration
|
||
const BASE_URL = process.env.BASE_URL || 'https://upskill-staging.measurequick.com';
|
||
const HEADLESS = process.env.HEADLESS !== 'false';
|
||
|
||
// Test data for certifications
|
||
const testCertifications = [
|
||
{
|
||
trainer_id: null, // Will be set after finding a test trainer
|
||
certification_type: 'measureQuick Certified Trainer',
|
||
status: 'active',
|
||
issue_date: '2024-01-15',
|
||
expiration_date: '2026-01-15',
|
||
certification_number: 'MQT-2024-001',
|
||
notes: 'Initial certification - Test data'
|
||
},
|
||
{
|
||
trainer_id: null,
|
||
certification_type: 'measureQuick Certified Champion',
|
||
status: 'active',
|
||
issue_date: '2024-06-01',
|
||
expiration_date: '2025-01-15', // Expiring soon
|
||
certification_number: 'MQC-2024-015',
|
||
notes: 'Champion level certification - Test data'
|
||
},
|
||
{
|
||
trainer_id: null,
|
||
certification_type: 'measureQuick Certified Trainer',
|
||
status: 'expired',
|
||
issue_date: '2022-03-10',
|
||
expiration_date: '2024-03-10', // Already expired
|
||
certification_number: 'MQT-2022-045',
|
||
notes: 'Previous certification - Test data'
|
||
}
|
||
];
|
||
|
||
async function createSampleCertifications() {
|
||
console.log('🏗️ Creating sample certification data...');
|
||
|
||
try {
|
||
// First, find a test trainer user
|
||
console.log('🔍 Finding test trainer...');
|
||
const trainers = execSync(`
|
||
UPSKILL_STAGING_URL="${BASE_URL}" wp-cli.phar --url=$UPSKILL_STAGING_URL --ssh=root@upskill-staging.measurequick.com user list --role=hvac_trainer --fields=ID,user_login,user_email --format=json
|
||
`, { encoding: 'utf8' });
|
||
|
||
const trainersList = JSON.parse(trainers);
|
||
if (trainersList.length === 0) {
|
||
throw new Error('No trainers found to test with');
|
||
}
|
||
|
||
const testTrainer = trainersList[0];
|
||
console.log(`✅ Using test trainer: ${testTrainer.user_login} (ID: ${testTrainer.ID})`);
|
||
|
||
// Update test certification data with trainer ID
|
||
testCertifications.forEach(cert => {
|
||
cert.trainer_id = testTrainer.ID;
|
||
});
|
||
|
||
// Create sample certifications via WordPress
|
||
for (let i = 0; i < testCertifications.length; i++) {
|
||
const cert = testCertifications[i];
|
||
console.log(`📝 Creating certification ${i + 1}: ${cert.certification_type} (${cert.status})`);
|
||
|
||
try {
|
||
// Create the certification post via WP-CLI
|
||
const result = execSync(`
|
||
UPSKILL_STAGING_URL="${BASE_URL}" wp-cli.phar --url=$UPSKILL_STAGING_URL --ssh=root@upskill-staging.measurequick.com post create --post_type=trainer_certification --post_title="${cert.certification_type} - ${testTrainer.user_login}" --post_status=publish --meta_input='{"trainer_id":"${cert.trainer_id}","certification_type":"${cert.certification_type}","status":"${cert.status}","issue_date":"${cert.issue_date}","expiration_date":"${cert.expiration_date}","certification_number":"${cert.certification_number}","notes":"${cert.notes}"}' --porcelain
|
||
`, { encoding: 'utf8' });
|
||
|
||
const postId = result.trim();
|
||
console.log(`✅ Created certification post ID: ${postId}`);
|
||
|
||
} catch (error) {
|
||
console.log(`⚠️ Certification creation via WP-CLI failed, trying alternative method...`);
|
||
console.log(`Error: ${error.message}`);
|
||
|
||
// Alternative: Create via PHP script
|
||
const phpScript = `
|
||
<?php
|
||
// Load WordPress
|
||
require_once('/var/www/html/wp-config.php');
|
||
|
||
// Create certification post
|
||
$post_data = array(
|
||
'post_type' => 'trainer_certification',
|
||
'post_title' => '${cert.certification_type} - ${testTrainer.user_login}',
|
||
'post_status' => 'publish'
|
||
);
|
||
|
||
$post_id = wp_insert_post($post_data);
|
||
|
||
if ($post_id) {
|
||
update_post_meta($post_id, 'trainer_id', ${cert.trainer_id});
|
||
update_post_meta($post_id, 'certification_type', '${cert.certification_type}');
|
||
update_post_meta($post_id, 'status', '${cert.status}');
|
||
update_post_meta($post_id, 'issue_date', '${cert.issue_date}');
|
||
update_post_meta($post_id, 'expiration_date', '${cert.expiration_date}');
|
||
update_post_meta($post_id, 'certification_number', '${cert.certification_number}');
|
||
update_post_meta($post_id, 'notes', '${cert.notes}');
|
||
|
||
echo "Created certification post ID: " . $post_id . "\\n";
|
||
} else {
|
||
echo "Failed to create certification post\\n";
|
||
}
|
||
?>`;
|
||
|
||
// Save PHP script temporarily
|
||
require('fs').writeFileSync('/tmp/create_cert.php', phpScript);
|
||
|
||
// Execute PHP script on server
|
||
try {
|
||
const phpResult = execSync(`
|
||
ssh root@upskill-staging.measurequick.com 'cat > /tmp/create_cert.php' < /tmp/create_cert.php &&
|
||
ssh root@upskill-staging.measurequick.com 'cd /var/www/html && php /tmp/create_cert.php && rm /tmp/create_cert.php'
|
||
`, { encoding: 'utf8' });
|
||
|
||
console.log(`📋 PHP result: ${phpResult.trim()}`);
|
||
} catch (phpError) {
|
||
console.log(`❌ PHP script failed: ${phpError.message}`);
|
||
}
|
||
}
|
||
}
|
||
|
||
return {
|
||
trainerId: testTrainer.ID,
|
||
trainerLogin: testTrainer.user_login,
|
||
certificationsCreated: testCertifications.length
|
||
};
|
||
|
||
} catch (error) {
|
||
console.error('❌ Failed to create sample certifications:', error.message);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
async function testCertificationDisplay(testTrainer) {
|
||
console.log('🎭 Testing certification display with Playwright...');
|
||
|
||
const browser = await chromium.launch({ headless: HEADLESS });
|
||
const page = await browser.newPage();
|
||
|
||
try {
|
||
// Navigate to trainer profile or find-a-trainer page
|
||
console.log('📍 Navigating to find-a-trainer page...');
|
||
await page.goto(`${BASE_URL}/find-a-trainer/`);
|
||
await page.waitForLoadState('networkidle');
|
||
|
||
// Take screenshot of initial state
|
||
await page.screenshot({ path: '/tmp/certification-test-initial.png' });
|
||
console.log('📸 Screenshot saved: /tmp/certification-test-initial.png');
|
||
|
||
// Look for trainer profiles on the page
|
||
console.log('🔍 Looking for trainer profiles...');
|
||
await page.waitForTimeout(3000); // Allow JS to load
|
||
|
||
// Check if certification cards are being displayed
|
||
const certificationCards = await page.locator('.hvac-certification-card').count();
|
||
console.log(`🎴 Found ${certificationCards} certification cards`);
|
||
|
||
const certificationGrids = await page.locator('.hvac-certifications-grid').count();
|
||
console.log(`📱 Found ${certificationGrids} certification grids`);
|
||
|
||
// Check for legacy certification display
|
||
const legacyCerts = await page.locator('.hvac-certification-section').count();
|
||
console.log(`📜 Found ${legacyCerts} legacy certification sections`);
|
||
|
||
// Try to find specific trainer profile
|
||
if (testTrainer && testTrainer.trainerLogin) {
|
||
console.log(`🎯 Looking for specific trainer: ${testTrainer.trainerLogin}`);
|
||
|
||
// Look for trainer name or profile link
|
||
const trainerElements = await page.locator(`text=${testTrainer.trainerLogin}`).count();
|
||
console.log(`👤 Found ${trainerElements} references to trainer ${testTrainer.trainerLogin}`);
|
||
}
|
||
|
||
// Check console for any JavaScript errors
|
||
const consoleMessages = [];
|
||
page.on('console', msg => {
|
||
consoleMessages.push(`${msg.type()}: ${msg.text()}`);
|
||
});
|
||
|
||
// Reload page to catch any console messages
|
||
await page.reload();
|
||
await page.waitForLoadState('networkidle');
|
||
await page.waitForTimeout(2000);
|
||
|
||
if (consoleMessages.length > 0) {
|
||
console.log('📝 Console messages:');
|
||
consoleMessages.forEach(msg => console.log(` ${msg}`));
|
||
}
|
||
|
||
// Take final screenshot
|
||
await page.screenshot({ path: '/tmp/certification-test-final.png', fullPage: true });
|
||
console.log('📸 Full page screenshot saved: /tmp/certification-test-final.png');
|
||
|
||
// Test results
|
||
const results = {
|
||
certificationCards,
|
||
certificationGrids,
|
||
legacyCerts,
|
||
consoleErrors: consoleMessages.filter(msg => msg.startsWith('error:')).length,
|
||
testTrainer: testTrainer || null
|
||
};
|
||
|
||
return results;
|
||
|
||
} catch (error) {
|
||
console.error('❌ Test failed:', error.message);
|
||
await page.screenshot({ path: '/tmp/certification-test-error.png' });
|
||
console.log('📸 Error screenshot saved: /tmp/certification-test-error.png');
|
||
throw error;
|
||
} finally {
|
||
await browser.close();
|
||
}
|
||
}
|
||
|
||
async function verifyDatabaseData(trainerId) {
|
||
console.log('🔍 Verifying certification data in database...');
|
||
|
||
try {
|
||
// Check if certification posts were created
|
||
const posts = execSync(`
|
||
UPSKILL_STAGING_URL="${BASE_URL}" wp-cli.phar --url=$UPSKILL_STAGING_URL --ssh=root@upskill-staging.measurequick.com post list --post_type=trainer_certification --meta_key=trainer_id --meta_value=${trainerId} --fields=ID,post_title,post_status --format=json
|
||
`, { encoding: 'utf8' });
|
||
|
||
const certPosts = JSON.parse(posts);
|
||
console.log(`📊 Found ${certPosts.length} certification posts for trainer ${trainerId}:`);
|
||
|
||
certPosts.forEach(post => {
|
||
console.log(` - ${post.post_title} (ID: ${post.ID}, Status: ${post.post_status})`);
|
||
});
|
||
|
||
// Get meta data for first post
|
||
if (certPosts.length > 0) {
|
||
const firstPostId = certPosts[0].ID;
|
||
const metaData = execSync(`
|
||
UPSKILL_STAGING_URL="${BASE_URL}" wp-cli.phar --url=$UPSKILL_STAGING_URL --ssh=root@upskill-staging.measurequick.com post meta list ${firstPostId} --format=json
|
||
`, { encoding: 'utf8' });
|
||
|
||
const meta = JSON.parse(metaData);
|
||
console.log(`🏷️ Meta data for post ${firstPostId}:`);
|
||
meta.forEach(item => {
|
||
if (item.meta_key.startsWith('certification_') || item.meta_key === 'trainer_id' || item.meta_key === 'status') {
|
||
console.log(` - ${item.meta_key}: ${item.meta_value}`);
|
||
}
|
||
});
|
||
}
|
||
|
||
return certPosts;
|
||
|
||
} catch (error) {
|
||
console.error('❌ Database verification failed:', error.message);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
async function cleanupTestData(trainerId) {
|
||
console.log('🧹 Cleaning up test certification data...');
|
||
|
||
try {
|
||
// Delete test certification posts
|
||
const result = execSync(`
|
||
UPSKILL_STAGING_URL="${BASE_URL}" wp-cli.phar --url=$UPSKILL_STAGING_URL --ssh=root@upskill-staging.measurequick.com post delete $(wp post list --post_type=trainer_certification --meta_key=trainer_id --meta_value=${trainerId} --field=ID) --force
|
||
`, { encoding: 'utf8' });
|
||
|
||
console.log('✅ Test certification data cleaned up');
|
||
console.log(`📋 Cleanup result: ${result.trim()}`);
|
||
|
||
} catch (error) {
|
||
console.log(`⚠️ Cleanup warning: ${error.message}`);
|
||
}
|
||
}
|
||
|
||
// Main test execution
|
||
async function main() {
|
||
console.log('🚀 Starting certification system test...\n');
|
||
|
||
let testTrainer = null;
|
||
|
||
try {
|
||
// Step 1: Create sample data
|
||
testTrainer = await createSampleCertifications();
|
||
console.log(`\n✅ Sample data created for trainer ${testTrainer.trainerLogin}\n`);
|
||
|
||
// Step 2: Verify database data
|
||
const dbResults = await verifyDatabaseData(testTrainer.trainerId);
|
||
console.log(`\n📊 Database verification: ${dbResults.length} posts found\n`);
|
||
|
||
// Step 3: Test display
|
||
const displayResults = await testCertificationDisplay(testTrainer);
|
||
console.log('\n🎭 Display test results:');
|
||
console.log(` - Certification cards: ${displayResults.certificationCards}`);
|
||
console.log(` - Certification grids: ${displayResults.certificationGrids}`);
|
||
console.log(` - Legacy sections: ${displayResults.legacyCerts}`);
|
||
console.log(` - Console errors: ${displayResults.consoleErrors}`);
|
||
|
||
// Test evaluation
|
||
if (displayResults.certificationCards > 0) {
|
||
console.log('\n✅ SUCCESS: New certification cards are being displayed!');
|
||
} else if (displayResults.legacyCerts > 0) {
|
||
console.log('\n⚠️ PARTIAL: Only legacy certification display found');
|
||
} else {
|
||
console.log('\n❌ ISSUE: No certification display found');
|
||
}
|
||
|
||
} catch (error) {
|
||
console.error('\n💥 Test failed:', error.message);
|
||
process.exit(1);
|
||
} finally {
|
||
// Step 4: Cleanup
|
||
if (testTrainer) {
|
||
await cleanupTestData(testTrainer.trainerId);
|
||
}
|
||
}
|
||
|
||
console.log('\n🎉 Certification system test completed!');
|
||
}
|
||
|
||
// Run the test
|
||
main().catch(console.error); |