180 lines
		
	
	
		
			No EOL
		
	
	
		
			7.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			180 lines
		
	
	
		
			No EOL
		
	
	
		
			7.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { STAGING_URL, PATHS, TIMEOUTS } from './config/staging-config';
 | |
| import { test, expect, Page } from '@playwright/test';
 | |
| import * as dotenv from 'dotenv';
 | |
| import { resolve } from 'path';
 | |
| 
 | |
| dotenv.config({ path: resolve(__dirname, '../../../../.env') });
 | |
| 
 | |
| test.use({
 | |
|   screenshot: 'only-on-failure',
 | |
|   video: 'retain-on-failure',
 | |
|   trace: 'retain-on-failure',
 | |
|   actionTimeout: 30000,
 | |
|   timeout: 120000, // 2 minutes per test
 | |
| });
 | |
| 
 | |
| test.describe('Event Creation with Cache Disabled', () => {
 | |
|   const stagingUrl = process.env.UPSKILL_STAGING_URL || 'https://upskill-staging.measurequick.com';
 | |
|   
 | |
|   test('creates event with cache disabled', async ({ page }) => {
 | |
|     const username = 'test_trainer';
 | |
|     const password = 'Test123!';
 | |
| 
 | |
|     // Step 1: Login with cache disabled (using no_cache_test query param)
 | |
|     await page.goto(stagingUrl + '/community-login/?no_cache_test=1', { waitUntil: 'domcontentloaded' });
 | |
|     await page.fill('input#user_login', username);
 | |
|     await page.fill('input#user_pass', password);
 | |
|     await page.getByRole('button', { name: /log in/i }).click();
 | |
|     
 | |
|     // Wait for login to complete
 | |
|     await page.waitForURL(/hvac-dashboard|manage-event/, { timeout: 30000 });
 | |
| 
 | |
|     // Step 2: Navigate directly to event creation (cache disabled for /manage-event/)
 | |
|     await page.goto(stagingUrl + '/manage-event/?no_cache_test=1', { waitUntil: 'domcontentloaded' });
 | |
|     await page.waitForSelector('input[name="post_title"]', { state: 'visible' });
 | |
| 
 | |
|     // Step 3: Fill form fields
 | |
|     const now = new Date();
 | |
|     const uniqueTitle = `HVAC Training ${now.toISOString().split('.')[0].replace(/[-T:]/g, '')}`;
 | |
|     await page.fill('input[name="post_title"]', uniqueTitle);
 | |
| 
 | |
|     // Set dates
 | |
|     const eventDate = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);
 | |
|     const dateStr = eventDate.toISOString().split('T')[0];
 | |
|     await page.fill('input[name="EventStartDate"]', dateStr);
 | |
|     await page.fill('input[name="EventEndDate"]', dateStr);
 | |
|     await page.fill('input[name="EventStartTime"]', '09:00');
 | |
|     await page.fill('input[name="EventEndTime"]', '17:00');
 | |
| 
 | |
|     // Set venue if fields exist
 | |
|     const venueFieldExists = await page.locator('input[name="venue[Venue]"]').isVisible().catch(() => false);
 | |
|     if (venueFieldExists) {
 | |
|       await page.fill('input[name="venue[Venue]"]', 'New Test Venue');
 | |
|       await page.fill('input[name="venue[Address]"]', '789 Test St');
 | |
|       await page.fill('input[name="venue[City]"]', 'Test City');
 | |
|       await page.fill('input[name="venue[Province]"]', 'BC');
 | |
|       await page.fill('input[name="venue[Country]"]', 'Canada');
 | |
|       await page.fill('input[name="venue[Zip]"]', 'V1X 1X1');
 | |
|     }
 | |
| 
 | |
|     // Step 4: Handle description field with proper naming
 | |
|     const descriptionText = `This is a test event created on ${now.toISOString()}. This event covers HVAC training basics.`;
 | |
|     
 | |
|     // Try multiple approaches to ensure the description is set
 | |
|     // 1. Fill the textarea directly
 | |
|     try {
 | |
|       await page.fill('textarea[name="tcepostcontent"]', descriptionText);
 | |
|     } catch (e) {
 | |
|       console.log('Direct textarea fill failed:', e.message);
 | |
|     }
 | |
| 
 | |
|     // 2. Handle TinyMCE editor if present
 | |
|     try {
 | |
|       const iframe = page.frameLocator('iframe#tcepostcontent_ifr');
 | |
|       const iframeBody = iframe.locator('body');
 | |
|       await iframeBody.click();
 | |
|       await iframeBody.fill(descriptionText);
 | |
|     } catch (e) {
 | |
|       console.log('TinyMCE iframe approach failed:', e.message);
 | |
|     }
 | |
| 
 | |
|     // 3. Use JavaScript to set both tcepostcontent and post_content
 | |
|     await page.evaluate((content) => {
 | |
|       // Set the visible textarea
 | |
|       const textarea = document.querySelector('textarea[name="tcepostcontent"]') as HTMLTextAreaElement;
 | |
|       if (textarea) {
 | |
|         textarea.value = content;
 | |
|         textarea.dispatchEvent(new Event('change', { bubbles: true }));
 | |
|       }
 | |
| 
 | |
|       // Create a hidden field for post_content if it doesn't exist
 | |
|       let postContentField = document.querySelector('input[name="post_content"], textarea[name="post_content"]') as HTMLInputElement;
 | |
|       if (!postContentField) {
 | |
|         postContentField = document.createElement('input');
 | |
|         postContentField.type = 'hidden';
 | |
|         postContentField.name = 'post_content';
 | |
|         const form = document.querySelector('form');
 | |
|         if (form) {
 | |
|           form.appendChild(postContentField);
 | |
|         }
 | |
|       }
 | |
|       postContentField.value = content;
 | |
| 
 | |
|       // Also try TinyMCE API if available
 | |
|       if ((window as any).tinymce) {
 | |
|         const editor = (window as any).tinymce.get('tcepostcontent');
 | |
|         if (editor) {
 | |
|           editor.setContent(content);
 | |
|         }
 | |
|       }
 | |
|     }, descriptionText);
 | |
| 
 | |
|     // Set additional fields if they exist
 | |
|     const organizerFieldExists = await page.locator('select[name="EventOrganizerID"]').isVisible().catch(() => false);
 | |
|     if (organizerFieldExists) {
 | |
|       await page.selectOption('select[name="EventOrganizerID"]', { index: 1 });
 | |
|     }
 | |
|     
 | |
|     const ticketFieldExists = await page.locator('input[name="ticket_price"]').isVisible().catch(() => false);
 | |
|     if (ticketFieldExists) {
 | |
|       await page.fill('input[name="ticket_price"]', '100');
 | |
|       await page.fill('input[name="ticket_quantity"]', '20');
 | |
|     }
 | |
| 
 | |
|     // Take screenshot before submission
 | |
|     await page.screenshot({ path: 'before-submission-no-cache.png', fullPage: true });
 | |
| 
 | |
|     // Step 5: Submit form with both field names
 | |
|     await page.evaluate(() => {
 | |
|       // Ensure both field names have the content
 | |
|       const tceContent = (document.querySelector('textarea[name="tcepostcontent"]') as HTMLTextAreaElement)?.value;
 | |
|       const postContentField = document.querySelector('input[name="post_content"], textarea[name="post_content"]') as HTMLInputElement;
 | |
|       
 | |
|       if (tceContent && postContentField) {
 | |
|         postContentField.value = tceContent;
 | |
|       }
 | |
|     });
 | |
| 
 | |
|     // Submit the form
 | |
|     await page.click('input[type="submit"][value="Submit Event"]');
 | |
|     await page.waitForLoadState('networkidle');
 | |
| 
 | |
|     // Check for success or error
 | |
|     const pageContent = await page.content();
 | |
|     const errorExists = await page.locator('.tribe-notice-error, .error-message').isVisible().catch(() => false);
 | |
|     
 | |
|     if (errorExists) {
 | |
|       await page.screenshot({ path: 'submission-error-no-cache.png', fullPage: true });
 | |
|       const errorText = await page.locator('.tribe-notice-error, .error-message').textContent();
 | |
|       console.error('Submission error:', errorText);
 | |
|       
 | |
|       // Additional debugging
 | |
|       const formData = await page.evaluate(() => {
 | |
|         const form = document.querySelector('form');
 | |
|         if (!form) return {};
 | |
|         const data: Record<string, string> = {};
 | |
|         const formData = new FormData(form);
 | |
|         formData.forEach((value, key) => {
 | |
|           data[key] = value.toString();
 | |
|         });
 | |
|         return data;
 | |
|       });
 | |
|       console.log('Form data:', formData);
 | |
|     }
 | |
| 
 | |
|     // Verify success
 | |
|     if (pageContent.includes(uniqueTitle) || pageContent.includes('Event submitted') || pageContent.includes('successfully created')) {
 | |
|       console.log('Event created successfully!');
 | |
|     } else {
 | |
|       console.log('Event creation may have failed - checking for any indication of success...');
 | |
|       
 | |
|       // Check if we were redirected to the event page
 | |
|       const currentUrl = page.url();
 | |
|       if (currentUrl.includes('/events/') || currentUrl.includes('event=')) {
 | |
|         console.log('Redirected to event page - likely successful');
 | |
|       } else {
 | |
|         throw new Error('Event creation failed');
 | |
|       }
 | |
|     }
 | |
|   });
 | |
| }); |