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');
|
|
}
|
|
}
|
|
});
|
|
}); |