/** * Simplified Enhanced TEC Template Visual Validation Script * * Focus on visual verification and manual field testing * Avoids problematic JavaScript field population system */ const { chromium } = require('playwright'); const fs = require('fs').promises; const path = require('path'); const config = { baseUrl: 'https://upskill-staging.measurequick.com', timeout: 45000, testCredentials: { username: 'test_trainer', password: 'TestTrainer123!' }, screenshotDir: 'test-results/visual-validation-simple' }; console.log('šŸŽÆ Simplified Enhanced TEC Template Visual Validation'); console.log('=================================================='); console.log(`🌐 Testing URL: ${config.baseUrl}`); console.log('šŸ“‹ Focus: Template verification and field accessibility'); console.log(''); async function runSimplifiedValidation() { await ensureDirectoryExists(config.screenshotDir); const browser = await chromium.launch({ headless: false, slowMo: 1000, args: ['--no-sandbox', '--disable-dev-shm-usage'] }); const context = await browser.newContext({ viewport: { width: 1920, height: 1080 }, ignoreHTTPSErrors: true }); const page = await context.newPage(); const pageErrors = []; page.on('pageerror', error => { pageErrors.push(error.message); console.error(`āŒ Page Error: ${error.message}`); }); const testResults = { screenshots: [], templateElements: {}, fieldAccess: {}, manualPopulation: {}, errors: pageErrors }; try { console.log('šŸ“‹ Step 1: Login and Navigate'); // Login await page.goto(`${config.baseUrl}/training-login/`); await page.waitForLoadState('networkidle'); await takeScreenshot('01-login-page', 'Login page loaded'); await page.fill('input[name="log"]', config.testCredentials.username); await page.fill('input[name="pwd"]', config.testCredentials.password); await page.click('input[type="submit"]'); await page.waitForLoadState('networkidle'); console.log('šŸ“‹ Step 2: Navigate to TEC Form'); await page.goto(`${config.baseUrl}/events/network/add`); await page.waitForLoadState('networkidle'); await page.waitForTimeout(3000); // Allow template to fully load await takeScreenshot('02-tec-form-loaded', 'Enhanced TEC form loaded'); console.log('šŸ“‹ Step 3: Template Element Detection'); testResults.templateElements = await detectTemplateElements(page); await takeScreenshot('03-template-elements', 'Template elements highlighted'); console.log('šŸ“‹ Step 4: Field Accessibility Testing'); testResults.fieldAccess = await testFieldAccessibility(page); await takeScreenshot('04-field-access', 'Field accessibility tested'); console.log('šŸ“‹ Step 5: Manual Population Testing'); testResults.manualPopulation = await testManualPopulation(page); await takeScreenshot('05-manual-population', 'Manual field population tested'); console.log('šŸ“‹ Step 6: Generate Results'); const finalReport = generateSimplifiedReport(testResults); await saveReport(finalReport); console.log('\nšŸŽ‰ SIMPLIFIED VALIDATION COMPLETE'); console.log('='.repeat(50)); console.log(finalReport.summary); return finalReport; } catch (error) { console.error('āŒ Simplified validation failed:', error.message); await takeScreenshot('error-final', `Error: ${error.message}`); throw error; } finally { await browser.close(); } async function takeScreenshot(name, description) { try { const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const filename = `${timestamp}_${name}.png`; const filepath = path.join(config.screenshotDir, filename); await page.screenshot({ path: filepath, fullPage: true }); testResults.screenshots.push({ name, description, filename, timestamp }); console.log(`šŸ“ø Screenshot: ${description} -> ${filename}`); } catch (error) { console.error(`āŒ Screenshot failed: ${error.message}`); } } } async function detectTemplateElements(page) { console.log('šŸ” Detecting template elements...'); const elements = { enhancedIndicator: '.hvac-success-indicator', basicForm: '#tribe-community-events', anyForm: 'form', titleField: 'input[name*="title"], #post-title-0', contentField: 'textarea[name*="content"], #post-content-0', venueField: 'input[name*="venue"]', organizerField: 'input[name*="organizer"]', dateField: 'input[name*="date"]', costField: 'input[name*="cost"]' }; const results = {}; let totalFound = 0; for (let [name, selector] of Object.entries(elements)) { try { const element = await page.locator(selector).first(); const count = await element.count(); results[name] = { found: count > 0, count: count, selector: selector }; if (count > 0) { totalFound++; console.log(`āœ… ${name}: Found (${count} elements)`); // Try to highlight if possible try { await element.highlight(); await page.waitForTimeout(200); } catch (e) { // Continue if highlight fails } } else { console.log(`āŒ ${name}: Not found`); } } catch (error) { results[name] = { found: false, error: error.message, selector: selector }; console.log(`āŒ ${name}: Error - ${error.message}`); } } const successRate = Math.round((totalFound / Object.keys(elements).length) * 100); console.log(`šŸ“Š Template elements: ${totalFound}/${Object.keys(elements).length} found (${successRate}%)`); results._summary = { totalFound, totalChecked: Object.keys(elements).length, successRate }; return results; } async function testFieldAccessibility(page) { console.log('šŸŽÆ Testing field accessibility...'); const criticalFields = [ { name: 'Title', selector: 'input[name*="title"], #post-title-0' }, { name: 'Content', selector: 'textarea[name*="content"], #post-content-0' }, { name: 'Venue', selector: 'input[name*="venue"]' }, { name: 'Organizer', selector: 'input[name*="organizer"]' }, { name: 'Start Date', selector: 'input[name*="start"], input[name*="date"]' }, { name: 'Cost', selector: 'input[name*="cost"]' } ]; const results = {}; let accessibleFields = 0; for (let field of criticalFields) { try { const element = await page.locator(field.selector).first(); const exists = await element.count() > 0; if (exists) { // Test if field is interactable const isVisible = await element.isVisible(); const isEnabled = await element.isEnabled(); results[field.name] = { exists: true, visible: isVisible, enabled: isEnabled, accessible: isVisible && isEnabled, selector: field.selector }; if (isVisible && isEnabled) { accessibleFields++; console.log(`āœ… ${field.name}: Accessible`); // Highlight accessible fields try { await element.highlight(); await page.waitForTimeout(200); } catch (e) { // Continue if highlight fails } } else { console.log(`āš ļø ${field.name}: Found but not accessible (visible: ${isVisible}, enabled: ${isEnabled})`); } } else { results[field.name] = { exists: false, accessible: false, selector: field.selector }; console.log(`āŒ ${field.name}: Not found`); } } catch (error) { results[field.name] = { exists: false, accessible: false, error: error.message, selector: field.selector }; console.log(`āŒ ${field.name}: Error - ${error.message}`); } } const accessibilityRate = Math.round((accessibleFields / criticalFields.length) * 100); console.log(`šŸ“Š Field accessibility: ${accessibleFields}/${criticalFields.length} accessible (${accessibilityRate}%)`); results._summary = { accessibleFields, totalFields: criticalFields.length, accessibilityRate }; return results; } async function testManualPopulation(page) { console.log('āœļø Testing manual field population...'); const testData = { title: 'Enhanced Template Validation Test Event', content: 'This is a test event to validate the enhanced TEC template functionality.', venue: 'Test Training Center', organizer: 'Enhanced Template Testing', cost: '199' }; const fieldMappings = [ { name: 'Title', selector: 'input[name*="title"], #post-title-0', value: testData.title }, { name: 'Content', selector: 'textarea[name*="content"], #post-content-0', value: testData.content }, { name: 'Venue', selector: 'input[name*="venue"]', value: testData.venue }, { name: 'Organizer', selector: 'input[name*="organizer"]', value: testData.organizer }, { name: 'Cost', selector: 'input[name*="cost"]', value: testData.cost } ]; const results = {}; let populatedFields = 0; for (let field of fieldMappings) { try { const element = await page.locator(field.selector).first(); if (await element.count() > 0) { await element.highlight(); await element.clear(); await element.fill(field.value); await page.waitForTimeout(300); // Verify population const currentValue = await element.inputValue(); const populated = currentValue === field.value; results[field.name] = { attempted: true, populated: populated, expectedValue: field.value, actualValue: currentValue, selector: field.selector }; if (populated) { populatedFields++; console.log(`āœ… ${field.name}: Successfully populated`); } else { console.log(`āš ļø ${field.name}: Population attempted but verification failed`); } } else { results[field.name] = { attempted: false, populated: false, reason: 'Field not found', selector: field.selector }; console.log(`āŒ ${field.name}: Field not found for population`); } } catch (error) { results[field.name] = { attempted: false, populated: false, error: error.message, selector: field.selector }; console.log(`āŒ ${field.name}: Population error - ${error.message}`); } } const populationRate = Math.round((populatedFields / fieldMappings.length) * 100); console.log(`šŸ“Š Manual population: ${populatedFields}/${fieldMappings.length} fields populated (${populationRate}%)`); results._summary = { populatedFields, totalFields: fieldMappings.length, populationRate }; return results; } function generateSimplifiedReport(results) { const report = { timestamp: new Date().toISOString(), summary: '', details: results, success: false, metrics: {} }; // Extract metrics report.metrics.templateElementsRate = results.templateElements._summary?.successRate || 0; report.metrics.fieldAccessibilityRate = results.fieldAccess._summary?.accessibilityRate || 0; report.metrics.manualPopulationRate = results.manualPopulation._summary?.populationRate || 0; report.metrics.screenshotsCaptured = results.screenshots.length; report.metrics.errorsDetected = results.errors.length; // Determine overall success const avgSuccess = (report.metrics.templateElementsRate + report.metrics.fieldAccessibilityRate + report.metrics.manualPopulationRate) / 3; report.success = avgSuccess >= 75 && report.metrics.manualPopulationRate >= 50; // Generate summary let summary = '\nšŸ“Š SIMPLIFIED VISUAL VALIDATION REPORT\n'; summary += '='.repeat(50) + '\n\n'; summary += `šŸ” TEMPLATE ELEMENTS: ${report.metrics.templateElementsRate}%\n`; summary += `šŸŽÆ FIELD ACCESSIBILITY: ${report.metrics.fieldAccessibilityRate}%\n`; summary += `āœļø MANUAL POPULATION: ${report.metrics.manualPopulationRate}%\n`; summary += `šŸ“ø SCREENSHOTS CAPTURED: ${report.metrics.screenshotsCaptured}\n`; summary += `āŒ ERRORS DETECTED: ${report.metrics.errorsDetected}\n`; summary += `šŸ“Š AVERAGE SUCCESS RATE: ${Math.round(avgSuccess)}%\n`; summary += '\nšŸ† OVERALL RESULT: '; if (report.success) { summary += 'āœ… SUCCESS\n'; summary += 'āœ… Enhanced TEC template is functional\n'; summary += 'āœ… Critical fields are accessible and working\n'; summary += 'āœ… Ready for production validation\n'; } else { summary += 'āš ļø NEEDS IMPROVEMENT\n'; summary += 'āŒ Some template elements missing or inaccessible\n'; summary += 'āŒ Field population needs enhancement\n'; } if (report.metrics.errorsDetected > 0) { summary += '\nāŒ PAGE ERRORS:\n'; results.errors.forEach((error, index) => { summary += ` ${index + 1}. ${error}\n`; }); } // Enhanced template specific assessment summary += '\nšŸŽÆ ENHANCED TEMPLATE ASSESSMENT:\n'; if (results.templateElements.enhancedIndicator?.found) { summary += 'āœ… Enhanced template indicator detected\n'; } else { summary += 'āŒ Enhanced template indicator missing\n'; } if (report.metrics.fieldAccessibilityRate >= 80) { summary += 'āœ… Critical fields accessible for event creation\n'; } else { summary += 'āš ļø Some critical fields may not be accessible\n'; } report.summary = summary; return report; } async function saveReport(report) { try { const reportPath = path.join(config.screenshotDir, 'simplified-validation-report.json'); await fs.writeFile(reportPath, JSON.stringify(report, null, 2)); const summaryPath = path.join(config.screenshotDir, 'simplified-validation-summary.txt'); await fs.writeFile(summaryPath, report.summary); console.log(`šŸ“„ Report saved: ${reportPath}`); console.log(`šŸ“„ Summary saved: ${summaryPath}`); } catch (error) { console.error(`āŒ Failed to save report: ${error.message}`); } } async function ensureDirectoryExists(dirPath) { try { await fs.access(dirPath); } catch { await fs.mkdir(dirPath, { recursive: true }); console.log(`šŸ“ Created directory: ${dirPath}`); } } // Main execution if (require.main === module) { runSimplifiedValidation() .then(report => { console.log('\nāœ… Simplified validation completed'); console.log(`šŸ“Š Average Success Rate: ${Math.round((report.metrics.templateElementsRate + report.metrics.fieldAccessibilityRate + report.metrics.manualPopulationRate) / 3)}%`); console.log(`šŸŽÆ Production Ready: ${report.success ? 'YES' : 'NO'}`); process.exit(0); }) .catch(error => { console.error('\nāŒ Simplified validation failed:', error.message); process.exit(1); }); } module.exports = { runSimplifiedValidation };