/** * Playwright test to diagnose ticket creation button issues * on the event management page */ const { test, expect } = require('@playwright/test'); test('Diagnose ticket creation button issues', async ({ page }) => { // Enable console logging to catch React errors const consoleMessages = []; const consoleErrors = []; page.on('console', msg => { const text = msg.text(); consoleMessages.push({ type: msg.type(), text }); if (msg.type() === 'error') { consoleErrors.push(text); console.log(`āŒ Console Error: ${text}`); } else if (msg.type() === 'warn') { console.log(`āš ļø Console Warning: ${text}`); } else if (text.includes('TicketsTab') || text.includes('ticket') || text.includes('React')) { console.log(`šŸ” Relevant Console: [${msg.type()}] ${text}`); } }); // Catch page errors page.on('pageerror', error => { console.log(`āŒ Page Error: ${error.message}`); consoleErrors.push(`Page Error: ${error.message}`); }); console.log('šŸš€ Starting diagnosis...'); // Step 1: Navigate to login page console.log('šŸ“ Step 1: Navigating to login page...'); await page.goto('http://localhost:3000/login'); await page.waitForLoadState('networkidle'); // Step 2: Login with provided credentials console.log('šŸ” Step 2: Logging in...'); await page.fill('input[type="email"]', 'tyler@zest.is'); await page.fill('input[type="password"]', 'Test123!'); await page.click('button[type="submit"]'); // Wait for redirect to dashboard await page.waitForURL('**/dashboard', { timeout: 10000 }); console.log('āœ… Successfully logged in and redirected to dashboard'); // Step 3: Find and navigate to an event management page console.log('šŸŽŖ Step 3: Looking for events to manage...'); // Wait for events to load await page.waitForTimeout(2000); // Look for event links - try multiple selectors const eventSelectors = [ 'a[href*="/events/"][href*="/manage"]', 'a[href*="/events/"]', '[data-testid="event-card"] a', '.event-card a', '.bg-white\\/10 a' ]; let eventLinks = []; for (const selector of eventSelectors) { eventLinks = await page.locator(selector).all(); if (eventLinks.length > 0) { console.log(`Found ${eventLinks.length} event links using selector: ${selector}`); break; } } if (eventLinks.length === 0) { console.log('āš ļø No event links found. Checking page content...'); // Get page title and URL for debugging const title = await page.title(); const url = page.url(); console.log(`Current page: ${title} at ${url}`); // Try to find any clickable elements related to events const eventText = await page.locator('text=/event/i').all(); console.log(`Found ${eventText.length} elements containing "event"`); // Take a screenshot to see what's on the dashboard await page.screenshot({ path: '/home/tyler/apps/bct-whitelabel/dashboard-state.png', fullPage: true }); console.log('Dashboard screenshot saved as dashboard-state.png'); return; } // Navigate to first available event management page let eventManageUrl; const firstLink = eventLinks[0]; eventManageUrl = await firstLink.getAttribute('href'); // Make sure it's a manage URL if (!eventManageUrl.includes('/manage')) { eventManageUrl = eventManageUrl + '/manage'; } console.log(`šŸŽÆ Step 4: Navigating to event management: ${eventManageUrl}`); await page.goto(`http://localhost:3000${eventManageUrl}`); await page.waitForLoadState('networkidle'); // Wait a bit for React components to mount await page.waitForTimeout(3000); // Step 5: Check current tab and navigate to Ticketing & Access if needed console.log('šŸ“‹ Step 5: Checking current tab...'); // Look for active tab first const activeTab = page.locator('.tab-active, [aria-selected="true"], .active').first(); if (await activeTab.isVisible()) { const activeTabText = await activeTab.textContent(); console.log(`Current active tab: "${activeTabText}"`); } // Look for Ticketing & Access tab specifically const ticketingTabSelectors = [ 'text="Ticketing & Access"', 'text="Tickets"', '[data-tab="tickets"]', 'button:has-text("Ticket")', 'a:has-text("Ticket")' ]; let ticketingTab = null; for (const selector of ticketingTabSelectors) { ticketingTab = page.locator(selector).first(); if (await ticketingTab.isVisible()) { console.log(`šŸŽ« Found Ticketing tab using selector: ${selector}`); break; } ticketingTab = null; } if (ticketingTab) { console.log('šŸŽ« Clicking Ticketing & Access tab...'); await ticketingTab.click(); await page.waitForTimeout(2000); // Check console for any new messages after tab click console.log('Checking for console messages after tab click...'); } else { console.log('āš ļø Ticketing & Access tab not found. Available tabs:'); // List all tabs/buttons that might be tabs const potentialTabs = await page.locator('button, a[role="tab"], [class*="tab"]').all(); for (let i = 0; i < Math.min(potentialTabs.length, 10); i++) { const tabText = await potentialTabs[i].textContent(); const isVisible = await potentialTabs[i].isVisible(); console.log(` Tab ${i + 1}: "${tabText}" (visible: ${isVisible})`); } } // Step 6: Inspect DOM for TicketsTab component and React mounting console.log('šŸ” Step 6: Inspecting DOM for React components...'); // Check for React component indicators const reactInspection = await page.evaluate(() => { // Check for React DevTools const hasReactDevTools = window.__REACT_DEVTOOLS_GLOBAL_HOOK__ !== undefined; // Check for React roots const reactRoots = document.querySelectorAll('[data-reactroot]'); // Check for any elements with React-like attributes or classes const reactElements = document.querySelectorAll('[data-react*], [class*="react"], [class*="React"]'); // Look for TicketsTab specifically const ticketsTabElements = document.querySelectorAll('[class*="TicketsTab"], [data-component*="TicketsTab"], [data-testid*="tickets"]'); // Check for Astro islands (which contain React components) const astroIslands = document.querySelectorAll('astro-island'); // Check for script tags that might contain React components const reactScripts = Array.from(document.scripts) .map(s => s.src) .filter(src => src && (src.includes('react') || src.includes('React') || src.includes('tickets') || src.includes('TicketsTab'))); // Look for any divs that might be React mount points const mountPoints = document.querySelectorAll('div[id*="react"], div[id*="tickets"], div[data-*]'); return { hasReactDevTools, reactRootsCount: reactRoots.length, reactElementsCount: reactElements.length, ticketsTabElementsCount: ticketsTabElements.length, astroIslandsCount: astroIslands.length, reactScripts, mountPointsCount: mountPoints.length, bodyClasses: document.body.className, documentTitle: document.title }; }); console.log('React Environment Check:', JSON.stringify(reactInspection, null, 2)); // Step 7: Look for ticket creation buttons with detailed search console.log('šŸ”˜ Step 7: Looking for ticket creation buttons...'); const buttonSelectors = [ 'text="Create Your First Ticket Type"', 'text="Add Ticket Type"', 'text="Create Ticket"', 'button:has-text("ticket")', 'button:has-text("Ticket")', 'button[class*="ticket"]', '[data-testid*="ticket"] button', '.ticket button', 'button:has-text("Add")', 'button:has-text("Create")' ]; const allButtons = []; for (const selector of buttonSelectors) { const buttons = await page.locator(selector).all(); if (buttons.length > 0) { console.log(`Found ${buttons.length} buttons with selector: ${selector}`); for (let i = 0; i < buttons.length; i++) { const button = buttons[i]; const text = await button.textContent(); const isVisible = await button.isVisible(); const isEnabled = await button.isEnabled(); allButtons.push({ button, text, isVisible, isEnabled, selector }); } } } console.log(`Total potential ticket creation buttons found: ${allButtons.length}`); // Step 8: Try to find the actual TicketsTab component mount point console.log('āš›ļø Step 8: Looking for TicketsTab component mount points...'); // Check for Astro islands that might contain the TicketsTab const astroIslands = await page.locator('astro-island').all(); console.log(`Found ${astroIslands.length} Astro islands`); for (let i = 0; i < astroIslands.length; i++) { const island = astroIslands[i]; const componentName = await island.getAttribute('component-export'); const componentUrl = await island.getAttribute('component-url'); const props = await island.getAttribute('props'); console.log(`Island ${i + 1}:`); console.log(` Component: ${componentName}`); console.log(` URL: ${componentUrl}`); console.log(` Props: ${props}`); if (componentName && componentName.includes('TicketsTab')) { console.log(`šŸŽÆ Found TicketsTab component island!`); // Check if the island has rendered content const islandContent = await island.innerHTML(); console.log(` Island content length: ${islandContent.length}`); console.log(` Island content preview: ${islandContent.substring(0, 200)}...`); } } // Step 9: Check for specific TicketsTab content console.log('šŸŽ« Step 9: Searching for TicketsTab-specific content...'); // Look for text that should be in TicketsTab const ticketTabContent = [ 'No ticket types created yet', 'Create Your First Ticket Type', 'Ticket Types', 'Add Ticket Type', 'General Admission', 'VIP', 'Early Bird' ]; for (const content of ticketTabContent) { const element = page.locator(`text="${content}"`).first(); const isVisible = await element.isVisible(); if (isVisible) { console.log(`āœ… Found TicketsTab content: "${content}"`); } } // Step 10: Try clicking ticket creation buttons if found console.log('šŸ–±ļø Step 10: Attempting to interact with ticket creation buttons...'); const workingButtons = allButtons.filter(b => b.isVisible && b.isEnabled); console.log(`Found ${workingButtons.length} clickable buttons`); if (workingButtons.length > 0) { const button = workingButtons[0]; console.log(`Attempting to click: "${button.text}" (${button.selector})`); // Monitor console messages during click const beforeClickMessages = consoleMessages.length; try { await button.button.click(); await page.waitForTimeout(2000); // Check for new console messages const newMessages = consoleMessages.slice(beforeClickMessages); if (newMessages.length > 0) { console.log('New console messages after click:'); newMessages.forEach(msg => console.log(` [${msg.type}] ${msg.text}`)); } // Check if a modal or form appeared const modalSelectors = [ '[role="dialog"]', '.modal', '[class*="modal"]', '[class*="popup"]', '[data-testid*="modal"]' ]; for (const selector of modalSelectors) { const modals = await page.locator(selector).all(); if (modals.length > 0) { console.log(`āœ… Found ${modals.length} modals after click using selector: ${selector}`); } } } catch (error) { console.log(`āŒ Error clicking button: ${error.message}`); } } else { console.log('āŒ No clickable ticket creation buttons found'); } // Step 11: Final diagnosis and screenshot console.log('\nšŸ“Š FINAL DIAGNOSIS:'); console.log('='.repeat(60)); console.log(`Console Errors: ${consoleErrors.length}`); if (consoleErrors.length > 0) { console.log('Console Errors:'); consoleErrors.forEach((error, i) => console.log(` ${i + 1}. ${error}`)); } console.log(`\nTotal Console Messages: ${consoleMessages.length}`); console.log(`React DevTools Available: ${reactInspection.hasReactDevTools ? 'āœ…' : 'āŒ'}`); console.log(`Astro Islands Found: ${reactInspection.astroIslandsCount}`); console.log(`React Elements Found: ${reactInspection.reactElementsCount}`); console.log(`TicketsTab Elements Found: ${reactInspection.ticketsTabElementsCount}`); console.log(`Potential Ticket Buttons: ${allButtons.length}`); console.log(`Clickable Ticket Buttons: ${allButtons.filter(b => b.isVisible && b.isEnabled).length}`); // Check for specific console messages that indicate the problem const ticketTabMessages = consoleMessages.filter(msg => msg.text.includes('TicketsTab') || msg.text.includes('tickets') || msg.text.includes('React') || msg.text.includes('component') ); if (ticketTabMessages.length === 0) { console.log('\n🚨 CRITICAL FINDING: No TicketsTab console messages detected!'); console.log('This suggests the TicketsTab React component is not mounting at all.'); } else { console.log('\nTicketsTab related console messages:'); ticketTabMessages.forEach(msg => console.log(` [${msg.type}] ${msg.text}`)); } // Take final screenshot console.log('\nšŸ“ø Taking final screenshot...'); await page.screenshot({ path: '/home/tyler/apps/bct-whitelabel/ticket-creation-final-diagnosis.png', fullPage: true }); console.log('Screenshot saved as: ticket-creation-final-diagnosis.png'); // Keep browser open briefly for manual inspection console.log('\nšŸ” Diagnosis complete. Check the screenshots and console output above.'); await page.waitForTimeout(5000); });