import { STAGING_URL, PATHS, TIMEOUTS } from './config/staging-config'; import { test, expect } from '@playwright/test'; // STAGING_URL is now imported from config test.describe('Investigate Form Submission', () => { test('analyze form submission mechanism', async ({ page }) => { // Capture console messages and errors page.on('console', msg => { console.log(`Console ${msg.type()}: ${msg.text()}`); }); page.on('pageerror', err => { console.log('Page error:', err.message); }); // Login await page.goto(PATHS.login); await page.fill('#user_login', 'test_trainer'); await page.fill('#user_pass', 'Test123!'); await page.click('#wp-submit'); await page.waitForURL('**/hvac-dashboard/'); // Navigate to create event await page.click('a:has-text("CREATE EVENT")'); await page.waitForLoadState('networkidle'); await page.waitForTimeout(3000); // Analyze the form structure const formInfo = await page.evaluate(() => { const form = document.querySelector('form'); if (!form) return { hasForm: false }; return { hasForm: true, action: form.action, method: form.method, id: form.id, classes: form.className, onsubmit: form.onsubmit ? 'has onsubmit handler' : 'no onsubmit', fields: Array.from(form.elements).map(el => ({ name: (el as any).name, type: (el as any).type, required: (el as any).required, value: (el as any).value })).filter(f => f.name) }; }); console.log('Form info:', JSON.stringify(formInfo, null, 2)); // Check for jQuery form handlers const jqueryHandlers = await page.evaluate(() => { if (typeof jQuery === 'undefined') return { hasJquery: false }; const form = jQuery('form').first(); if (!form.length) return { hasJquery: true, hasForm: false }; // Get event handlers const events = jQuery._data(form[0], 'events') || {}; return { hasJquery: true, hasForm: true, submitHandlers: events.submit ? events.submit.length : 0, clickHandlers: jQuery('input[type="submit"], button[type="submit"]').length }; }); console.log('jQuery handlers:', jqueryHandlers); // Fill minimal required fields await page.fill('input[name="post_title"]', `Test Event ${Date.now()}`); // Try to set description directly in multiple ways await page.evaluate(() => { // Method 1: Direct TinyMCE if (typeof tinymce !== 'undefined' && tinymce.activeEditor) { tinymce.activeEditor.setContent('Test description content'); tinymce.activeEditor.save(); } // Method 2: Find actual textarea const textareas = document.querySelectorAll('textarea'); textareas.forEach(ta => { if (ta.name.includes('content') || ta.id.includes('content')) { (ta as HTMLTextAreaElement).value = 'Test description content'; } }); // Method 3: Hidden inputs const hiddenInputs = document.querySelectorAll('input[type="hidden"]'); hiddenInputs.forEach(input => { if (input.name.includes('content')) { (input as HTMLInputElement).value = 'Test description content'; } }); }); // Set dates const today = new Date(); const dateStr = `${(today.getMonth() + 1).toString().padStart(2, '0')}/${today.getDate().toString().padStart(2, '0')}/${today.getFullYear()}`; await page.fill('input#EventStartDate', dateStr); await page.fill('input#EventEndDate', dateStr); // Listen to network requests const requests: any[] = []; page.on('request', request => { if (request.method() === 'POST') { requests.push({ url: request.url(), method: request.method(), postData: request.postData() }); } }); // Take screenshot before submit await page.screenshot({ path: 'test-results/before-submit-investigate.png' }); // Find submit button and get its properties const submitInfo = await page.evaluate(() => { const submitBtn = document.querySelector('input[type="submit"][value="Submit Event"]'); if (!submitBtn) return null; return { id: submitBtn.id, name: (submitBtn as HTMLInputElement).name, value: (submitBtn as HTMLInputElement).value, onclick: submitBtn.onclick ? 'has onclick' : 'no onclick', form: (submitBtn as HTMLInputElement).form ? 'has form' : 'no form' }; }); console.log('Submit button info:', submitInfo); // Try to submit and catch any navigation let navigationHappened = false; let formStayed = false; try { const navigationPromise = page.waitForNavigation({ timeout: 5000 }); await page.click('input[type="submit"][value="Submit Event"]'); await navigationPromise; navigationHappened = true; } catch (e) { formStayed = true; console.log('No navigation occurred'); } await page.waitForTimeout(3000); // Check current state const currentUrl = page.url(); console.log('Current URL:', currentUrl); console.log('Navigation happened:', navigationHappened); console.log('Form stayed:', formStayed); console.log('POST requests:', requests); // Check for validation errors in DOM const validationErrors = await page.evaluate(() => { const errors: any[] = []; // Check for WordPress admin notices document.querySelectorAll('.notice, .error, .updated').forEach(el => { errors.push({ type: 'wordpress-notice', text: el.textContent?.trim(), classes: el.className }); }); // Check for inline errors document.querySelectorAll('.error-message, .field-error, .validation-error').forEach(el => { errors.push({ type: 'inline-error', text: el.textContent?.trim(), classes: el.className }); }); // Check for HTML5 validation const inputs = document.querySelectorAll('input, textarea, select'); inputs.forEach(input => { if ((input as any).validationMessage) { errors.push({ type: 'html5-validation', field: (input as any).name, message: (input as any).validationMessage }); } }); return errors; }); console.log('Validation errors:', validationErrors); // Get final form data const finalFormData = await page.evaluate(() => { const form = document.querySelector('form'); if (!form) return null; const formData = new FormData(form as HTMLFormElement); const data: Record = {}; formData.forEach((value, key) => { data[key] = value; }); return data; }); console.log('Final form data:', finalFormData); // Take final screenshot await page.screenshot({ path: 'test-results/after-submit-investigate.png', fullPage: true }); // Pass test to see output expect(true).toBe(true); }); });