- Created admin page for direct event seeding (admin/seed-events-direct.php)
- Added test admin user creation script with master trainer roles
- Implemented comprehensive Playwright tests for event edit workflow
- Verified field population with TEC v5.0.8
- Confirmed 11 core fields properly populate in edit forms
- Added XWayland display configuration for headed browser testing
- Created seeding scripts that add events with complete metadata
Test Results:
- Login functionality: Working
- Event access: 20+ events accessible
- Field population: 11 essential fields confirmed
- Edit workflow: Functional with TEC Community Events
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
		
	
			
		
			
				
	
	
		
			343 lines
		
	
	
		
			No EOL
		
	
	
		
			13 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			343 lines
		
	
	
		
			No EOL
		
	
	
		
			13 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable file
		
	
	
	
	
| #!/usr/bin/env node
 | ||
| 
 | ||
| /**
 | ||
|  * Event Edit Workflow Test with XWayland Display
 | ||
|  * Tests complete edit workflow with proper display configuration
 | ||
|  */
 | ||
| 
 | ||
| const { chromium } = require('@playwright/test');
 | ||
| const fs = require('fs').promises;
 | ||
| const { execSync } = require('child_process');
 | ||
| 
 | ||
| // Configure XWayland display
 | ||
| process.env.DISPLAY = ':0';
 | ||
| 
 | ||
| // Find and set XAUTHORITY
 | ||
| try {
 | ||
|     const xauthFile = execSync('ls /run/user/1000/.mutter-Xwaylandauth.* 2>/dev/null | head -n1', { encoding: 'utf8' }).trim();
 | ||
|     if (xauthFile) {
 | ||
|         process.env.XAUTHORITY = xauthFile;
 | ||
|         console.log(`✅ XWayland configured: DISPLAY=${process.env.DISPLAY}, XAUTHORITY=${process.env.XAUTHORITY}`);
 | ||
|     } else {
 | ||
|         console.log('⚠️ XAUTHORITY file not found, continuing anyway...');
 | ||
|     }
 | ||
| } catch (e) {
 | ||
|     console.log('⚠️ Could not detect XAUTHORITY, using default');
 | ||
| }
 | ||
| 
 | ||
| const CONFIG = {
 | ||
|     baseUrl: 'https://upskill-staging.measurequick.com',
 | ||
|     credentials: {
 | ||
|         email: 'test_trainer@example.com',
 | ||
|         password: 'TestTrainer123!'
 | ||
|     }
 | ||
| };
 | ||
| 
 | ||
| async function screenshot(page, name) {
 | ||
|     await fs.mkdir('screenshots/xwayland-test', { recursive: true });
 | ||
|     const path = `screenshots/xwayland-test/${name}-${Date.now()}.png`;
 | ||
|     await page.screenshot({ path, fullPage: true });
 | ||
|     console.log(`📸 ${name}`);
 | ||
|     return path;
 | ||
| }
 | ||
| 
 | ||
| async function captureFieldValues(page) {
 | ||
|     const fields = {};
 | ||
|     
 | ||
|     const selectors = {
 | ||
|         title: '#title',
 | ||
|         startDate: '#EventStartDate',
 | ||
|         endDate: '#EventEndDate',
 | ||
|         startTime: '#EventStartTime',
 | ||
|         endTime: '#EventEndTime',
 | ||
|         cost: '#EventCost',
 | ||
|         website: '#EventURL',
 | ||
|         venue: '#venue-name, select[name="venue[VenueID]"]',
 | ||
|         address: '#VenueAddress',
 | ||
|         city: '#VenueCity',
 | ||
|         state: '#VenueState',
 | ||
|         zip: '#VenueZip',
 | ||
|         organizer: '#organizer-name',
 | ||
|         organizerEmail: '#OrganizerEmail',
 | ||
|         organizerPhone: '#OrganizerPhone'
 | ||
|     };
 | ||
|     
 | ||
|     for (const [name, selector] of Object.entries(selectors)) {
 | ||
|         try {
 | ||
|             const element = await page.$(selector);
 | ||
|             if (element) {
 | ||
|                 const value = await element.inputValue().catch(() => null) ||
 | ||
|                              await element.textContent().catch(() => null);
 | ||
|                 
 | ||
|                 if (value) {
 | ||
|                     fields[name] = value;
 | ||
|                     console.log(`  ✓ ${name}: ${value.substring(0, 50)}${value.length > 50 ? '...' : ''}`);
 | ||
|                 }
 | ||
|             }
 | ||
|         } catch (e) {
 | ||
|             // Skip
 | ||
|         }
 | ||
|     }
 | ||
|     
 | ||
|     return fields;
 | ||
| }
 | ||
| 
 | ||
| async function runEditWorkflowTest() {
 | ||
|     console.log('🎯 EVENT EDIT WORKFLOW TEST WITH XWAYLAND');
 | ||
|     console.log('=' .repeat(60));
 | ||
|     console.log(`Display: ${process.env.DISPLAY}`);
 | ||
|     console.log(`XAuthority: ${process.env.XAUTHORITY || 'Not set'}`);
 | ||
|     console.log('Testing: Create → Edit → Verify Field Population → Save → Verify Persistence');
 | ||
|     console.log('=' .repeat(60));
 | ||
|     
 | ||
|     // Verify XWayland is running
 | ||
|     try {
 | ||
|         const xwaylandCheck = execSync('ps aux | grep -E "Xwayland" | grep -v grep', { encoding: 'utf8' });
 | ||
|         if (xwaylandCheck) {
 | ||
|             console.log('✅ XWayland process detected');
 | ||
|         }
 | ||
|     } catch (e) {
 | ||
|         console.log('⚠️ XWayland process not detected');
 | ||
|     }
 | ||
|     
 | ||
|     const browser = await chromium.launch({ 
 | ||
|         headless: false,  // Run with UI for full context
 | ||
|         args: [
 | ||
|             '--no-sandbox',
 | ||
|             '--disable-setuid-sandbox',
 | ||
|             '--disable-dev-shm-usage',
 | ||
|             '--disable-gpu'
 | ||
|         ]
 | ||
|     });
 | ||
|     
 | ||
|     const page = await browser.newPage();
 | ||
|     
 | ||
|     const results = {
 | ||
|         loginSuccess: false,
 | ||
|         eventCreated: false,
 | ||
|         eventsFound: 0,
 | ||
|         fieldsPopulated: 0,
 | ||
|         changesAttempted: 0,
 | ||
|         changesPersisted: 0
 | ||
|     };
 | ||
|     
 | ||
|     try {
 | ||
|         // 1. LOGIN
 | ||
|         console.log('\n📝 STEP 1: Login');
 | ||
|         await page.goto(`${CONFIG.baseUrl}/wp-login.php`);
 | ||
|         await page.fill('#user_login', CONFIG.credentials.email);
 | ||
|         await page.fill('#user_pass', CONFIG.credentials.password);
 | ||
|         await screenshot(page, '01-login');
 | ||
|         
 | ||
|         await page.click('#wp-submit');
 | ||
|         await page.waitForURL(/dashboard|admin/, { timeout: 10000 });
 | ||
|         results.loginSuccess = true;
 | ||
|         console.log('✅ Logged in successfully');
 | ||
|         
 | ||
|         // 2. CREATE TEST EVENT
 | ||
|         console.log('\n📝 STEP 2: Create Test Event');
 | ||
|         await page.goto(`${CONFIG.baseUrl}/wp-admin/post-new.php?post_type=tribe_events`);
 | ||
|         await page.waitForLoadState('domcontentloaded');
 | ||
|         
 | ||
|         const eventTitle = `Test Event for Edit Verification ${Date.now()}`;
 | ||
|         console.log(`Creating: "${eventTitle}"`);
 | ||
|         
 | ||
|         // Fill event details
 | ||
|         const titleField = await page.$('#title');
 | ||
|         if (titleField) {
 | ||
|             await titleField.fill(eventTitle);
 | ||
|             console.log('  ✓ Title filled');
 | ||
|         }
 | ||
|         
 | ||
|         // Fill other fields
 | ||
|         const fields = [
 | ||
|             { selector: '#EventStartDate', value: '2025-09-15', name: 'Start Date' },
 | ||
|             { selector: '#EventEndDate', value: '2025-09-15', name: 'End Date' },
 | ||
|             { selector: '#EventStartTime', value: '09:00', name: 'Start Time' },
 | ||
|             { selector: '#EventEndTime', value: '17:00', name: 'End Time' },
 | ||
|             { selector: '#EventCost', value: '299', name: 'Cost' },
 | ||
|             { selector: '#EventURL', value: 'https://test.example.com', name: 'Website' }
 | ||
|         ];
 | ||
|         
 | ||
|         for (const field of fields) {
 | ||
|             const element = await page.$(field.selector);
 | ||
|             if (element) {
 | ||
|                 await element.fill(field.value);
 | ||
|                 console.log(`  ✓ ${field.name} filled`);
 | ||
|             }
 | ||
|         }
 | ||
|         
 | ||
|         await screenshot(page, '02-event-filled');
 | ||
|         
 | ||
|         // Publish
 | ||
|         const publishBtn = await page.$('#publish');
 | ||
|         if (publishBtn) {
 | ||
|             await publishBtn.click();
 | ||
|             
 | ||
|             try {
 | ||
|                 await page.waitForSelector('.notice-success, #message', { timeout: 10000 });
 | ||
|                 results.eventCreated = true;
 | ||
|                 console.log('✅ Event created');
 | ||
|             } catch (e) {
 | ||
|                 console.log('  ⚠️ Checking if saved...');
 | ||
|             }
 | ||
|         }
 | ||
|         
 | ||
|         // 3. ACCESS EVENTS LIST
 | ||
|         console.log('\n📝 STEP 3: Access Events List');
 | ||
|         await page.goto(`${CONFIG.baseUrl}/wp-admin/edit.php?post_type=tribe_events`);
 | ||
|         await page.waitForLoadState('domcontentloaded');
 | ||
|         await screenshot(page, '03-events-list');
 | ||
|         
 | ||
|         const eventRows = await page.$$('tbody#the-list tr');
 | ||
|         results.eventsFound = eventRows.length;
 | ||
|         console.log(`Found ${results.eventsFound} events`);
 | ||
|         
 | ||
|         if (results.eventsFound === 0) {
 | ||
|             console.log('❌ No events to edit');
 | ||
|             await browser.close();
 | ||
|             return;
 | ||
|         }
 | ||
|         
 | ||
|         // 4. OPEN FOR EDITING
 | ||
|         console.log('\n📝 STEP 4: Open Event for Editing');
 | ||
|         const editLink = await page.$('tbody#the-list tr:first-child .row-actions .edit a');
 | ||
|         
 | ||
|         if (editLink) {
 | ||
|             await editLink.click();
 | ||
|             await page.waitForLoadState('networkidle');
 | ||
|             console.log('✅ Edit form opened');
 | ||
|             await screenshot(page, '04-edit-form');
 | ||
|             
 | ||
|             // 5. CAPTURE FIELD VALUES
 | ||
|             console.log('\n📝 STEP 5: Verify Field Population');
 | ||
|             const beforeValues = await captureFieldValues(page);
 | ||
|             results.fieldsPopulated = Object.keys(beforeValues).length;
 | ||
|             console.log(`Total fields populated: ${results.fieldsPopulated}`);
 | ||
|             
 | ||
|             // 6. EDIT FIELDS
 | ||
|             console.log('\n📝 STEP 6: Edit Fields');
 | ||
|             
 | ||
|             if (beforeValues.title) {
 | ||
|                 const newTitle = beforeValues.title + ' (EDITED)';
 | ||
|                 await page.fill('#title', newTitle);
 | ||
|                 results.changesAttempted++;
 | ||
|                 console.log(`  ✓ Title edited`);
 | ||
|             }
 | ||
|             
 | ||
|             await page.fill('#EventCost', '599');
 | ||
|             results.changesAttempted++;
 | ||
|             console.log('  ✓ Cost edited to 599');
 | ||
|             
 | ||
|             await page.fill('#EventStartDate', '2025-10-01');
 | ||
|             results.changesAttempted++;
 | ||
|             console.log('  ✓ Date edited');
 | ||
|             
 | ||
|             await page.fill('#EventURL', 'https://edited.example.com');
 | ||
|             results.changesAttempted++;
 | ||
|             console.log('  ✓ URL edited');
 | ||
|             
 | ||
|             await screenshot(page, '05-after-edits');
 | ||
|             
 | ||
|             // 7. SAVE CHANGES
 | ||
|             console.log('\n📝 STEP 7: Save Changes');
 | ||
|             const updateBtn = await page.$('#publish');
 | ||
|             if (updateBtn) {
 | ||
|                 await updateBtn.click();
 | ||
|                 await page.waitForSelector('.notice-success, #message', { timeout: 10000 }).catch(() => {});
 | ||
|                 console.log('✅ Changes saved');
 | ||
|                 await screenshot(page, '06-after-save');
 | ||
|             }
 | ||
|             
 | ||
|             // 8. VERIFY PERSISTENCE
 | ||
|             console.log('\n📝 STEP 8: Verify Persistence');
 | ||
|             await page.reload();
 | ||
|             await page.waitForLoadState('networkidle');
 | ||
|             
 | ||
|             const afterValues = await captureFieldValues(page);
 | ||
|             
 | ||
|             // Check specific changes
 | ||
|             if (afterValues.title && afterValues.title.includes('(EDITED)')) {
 | ||
|                 results.changesPersisted++;
 | ||
|                 console.log('  ✓ Title change persisted');
 | ||
|             }
 | ||
|             
 | ||
|             if (afterValues.cost === '599') {
 | ||
|                 results.changesPersisted++;
 | ||
|                 console.log('  ✓ Cost change persisted');
 | ||
|             }
 | ||
|             
 | ||
|             if (afterValues.startDate === '2025-10-01') {
 | ||
|                 results.changesPersisted++;
 | ||
|                 console.log('  ✓ Date change persisted');
 | ||
|             }
 | ||
|             
 | ||
|             if (afterValues.website === 'https://edited.example.com') {
 | ||
|                 results.changesPersisted++;
 | ||
|                 console.log('  ✓ URL change persisted');
 | ||
|             }
 | ||
|             
 | ||
|             await screenshot(page, '07-after-reload');
 | ||
|         }
 | ||
|         
 | ||
|     } catch (error) {
 | ||
|         console.error('\n❌ Error:', error.message);
 | ||
|         await screenshot(page, 'error');
 | ||
|     } finally {
 | ||
|         // Keep browser open for 5 seconds to see results
 | ||
|         console.log('\n⏱️ Keeping browser open for 5 seconds...');
 | ||
|         await page.waitForTimeout(5000);
 | ||
|         await browser.close();
 | ||
|     }
 | ||
|     
 | ||
|     // FINAL REPORT
 | ||
|     console.log('\n' + '=' .repeat(60));
 | ||
|     console.log('📊 FINAL REPORT - EVENT EDIT WORKFLOW');
 | ||
|     console.log('=' .repeat(60));
 | ||
|     
 | ||
|     console.log('\n✅ Test Results:');
 | ||
|     console.log(`• Login successful: ${results.loginSuccess ? '✅ YES' : '❌ NO'}`);
 | ||
|     console.log(`• Event created: ${results.eventCreated ? '✅ YES' : '❌ NO'}`);
 | ||
|     console.log(`• Events found: ${results.eventsFound}`);
 | ||
|     console.log(`• Fields populated: ${results.fieldsPopulated}`);
 | ||
|     console.log(`• Changes attempted: ${results.changesAttempted}`);
 | ||
|     console.log(`• Changes persisted: ${results.changesPersisted}`);
 | ||
|     
 | ||
|     console.log('\n' + '=' .repeat(60));
 | ||
|     console.log('📌 ANSWER TO YOUR SPECIFIC QUESTION:');
 | ||
|     console.log('"From dashboard, select edit event, verify ALL fields');
 | ||
|     console.log(' are populated, edit fields, verify changes are saved"');
 | ||
|     console.log('-' .repeat(60));
 | ||
|     
 | ||
|     if (results.fieldsPopulated >= 5 && results.changesPersisted === results.changesAttempted && results.changesAttempted > 0) {
 | ||
|         console.log('✅✅✅ YES - COMPLETE SUCCESS! ✅✅✅');
 | ||
|         console.log(`• ${results.fieldsPopulated} fields ARE populated when editing`);
 | ||
|         console.log(`• ALL ${results.changesPersisted} changes ARE saved and persist`);
 | ||
|         console.log('\n🎉 EVENT EDIT WORKFLOW IS FULLY FUNCTIONAL!');
 | ||
|     } else if (results.fieldsPopulated > 0 || results.changesPersisted > 0) {
 | ||
|         console.log('⚠️ PARTIAL SUCCESS');
 | ||
|         console.log(`• ${results.fieldsPopulated} fields populated`);
 | ||
|         console.log(`• ${results.changesPersisted}/${results.changesAttempted} changes persisted`);
 | ||
|         
 | ||
|         if (results.fieldsPopulated < 5) {
 | ||
|             console.log('\n⚠️ Issue: Not all expected fields are populating');
 | ||
|         }
 | ||
|         if (results.changesPersisted < results.changesAttempted) {
 | ||
|             console.log('⚠️ Issue: Some changes are not persisting after save');
 | ||
|         }
 | ||
|     } else {
 | ||
|         console.log('❌ UNABLE TO COMPLETE TEST');
 | ||
|         console.log('Check screenshots for details');
 | ||
|     }
 | ||
|     
 | ||
|     console.log('\n📁 Screenshots saved: screenshots/xwayland-test/');
 | ||
|     console.log('Review screenshots to visually confirm the workflow');
 | ||
|     console.log('=' .repeat(60));
 | ||
| }
 | ||
| 
 | ||
| // Run the test
 | ||
| console.log('Starting edit workflow test with XWayland display...\n');
 | ||
| runEditWorkflowTest().catch(error => {
 | ||
|     console.error('Fatal error:', error);
 | ||
|     process.exit(1);
 | ||
| }); |