const { chromium } = require('playwright'); const fs = require('fs'); const path = require('path'); async function runComprehensiveQAAudit() { console.log('šŸ” Starting Comprehensive QA Audit...'); const browser = await chromium.launch({ headless: false, slowMo: 1000 // Slow down for visibility }); const context = await browser.newContext({ viewport: { width: 1280, height: 720 }, userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' }); const page = await context.newPage(); // Track console errors const consoleErrors = []; page.on('console', msg => { if (msg.type() === 'error') { consoleErrors.push(`${new Date().toISOString()}: ${msg.text()}`); } }); // Track network failures const networkErrors = []; page.on('response', response => { if (response.status() >= 400) { networkErrors.push(`${response.status()}: ${response.url()}`); } }); try { // Step 1: Login console.log('šŸ“ Step 1: Logging in...'); await page.goto('http://localhost:3001/login'); await page.waitForSelector('input[type="email"]', { timeout: 10000 }); await page.fill('input[type="email"]', 'tmartinez@gmail.com'); await page.fill('input[type="password"]', 'Skittles@420'); // Take login form screenshot await page.screenshot({ path: 'login-form-qa.png', fullPage: true }); console.log('šŸ“ø Screenshot: login-form-qa.png'); await page.click('button[type="submit"]'); await page.waitForNavigation({ timeout: 15000 }); console.log(`āœ… Login successful - Current URL: ${page.url()}`); // Step 2: Test Dashboard console.log('\nšŸ“Š Step 2: Testing Dashboard...'); await page.goto('http://localhost:3001/dashboard'); await page.waitForSelector('body', { timeout: 10000 }); await page.waitForTimeout(2000); // Let content load await page.screenshot({ path: 'dashboard-qa.png', fullPage: true }); console.log('šŸ“ø Screenshot: dashboard-qa.png'); // Test dashboard interactions try { // Look for "Create Event" or "New Event" button const createEventBtn = await page.locator('a[href*="events/new"], button:has-text("Create Event"), a:has-text("New Event")').first(); if (await createEventBtn.count() > 0) { console.log('āœ… Create Event button found'); } // Check for event cards or tables const eventElements = await page.locator('[data-testid*="event"], .event-card, table tr').count(); console.log(`šŸ“‹ Found ${eventElements} event-related elements`); } catch (error) { console.log('āš ļø Dashboard interaction test failed:', error.message); } // Step 3: Test Events New Page console.log('\nšŸŽ« Step 3: Testing Event Creation...'); await page.goto('http://localhost:3001/events/new'); await page.waitForSelector('body', { timeout: 10000 }); await page.waitForTimeout(2000); await page.screenshot({ path: 'events-new-qa.png', fullPage: true }); console.log('šŸ“ø Screenshot: events-new-qa.png'); // Test form interactions try { const eventNameInput = await page.locator('input[name="name"], input[name="title"], input[placeholder*="event"], input[placeholder*="name"]').first(); if (await eventNameInput.count() > 0) { await eventNameInput.fill('QA Test Event'); console.log('āœ… Event name field working'); } // Look for form submit button const submitBtn = await page.locator('button[type="submit"], button:has-text("Create"), button:has-text("Save")').first(); if (await submitBtn.count() > 0) { console.log('āœ… Form submit button found'); } } catch (error) { console.log('āš ļø Event creation form test failed:', error.message); } // Step 4: Test QR Scan Page console.log('\nšŸ“± Step 4: Testing QR Scanner...'); await page.goto('http://localhost:3001/scan'); await page.waitForSelector('body', { timeout: 10000 }); await page.waitForTimeout(2000); await page.screenshot({ path: 'scan-qa.png', fullPage: true }); console.log('šŸ“ø Screenshot: scan-qa.png'); // Test scanner interactions try { // Look for camera permission or scanner elements const scannerElements = await page.locator('[data-testid*="scanner"], video, canvas, .scanner').count(); console.log(`šŸ“· Found ${scannerElements} scanner-related elements`); } catch (error) { console.log('āš ļø Scanner test failed:', error.message); } // Step 5: Test Templates Page console.log('\nšŸ“‹ Step 5: Testing Templates...'); await page.goto('http://localhost:3001/templates'); await page.waitForSelector('body', { timeout: 10000 }); await page.waitForTimeout(2000); await page.screenshot({ path: 'templates-qa.png', fullPage: true }); console.log('šŸ“ø Screenshot: templates-qa.png'); // Step 6: Test Admin Dashboard console.log('\nšŸ”§ Step 6: Testing Admin Dashboard...'); await page.goto('http://localhost:3001/admin/dashboard'); await page.waitForSelector('body', { timeout: 10000 }); await page.waitForTimeout(2000); await page.screenshot({ path: 'admin-dashboard-qa.png', fullPage: true }); console.log('šŸ“ø Screenshot: admin-dashboard-qa.png'); // Step 7: Test Calendar Page console.log('\nšŸ“… Step 7: Testing Calendar...'); await page.goto('http://localhost:3001/calendar'); await page.waitForSelector('body', { timeout: 10000 }); await page.waitForTimeout(2000); await page.screenshot({ path: 'calendar-qa.png', fullPage: true }); console.log('šŸ“ø Screenshot: calendar-qa.png'); // Test calendar interactions try { // Look for calendar navigation const calendarNav = await page.locator('button:has-text("Today"), button:has-text("Next"), button:has-text("Previous"), .calendar-nav').count(); console.log(`šŸ“… Found ${calendarNav} calendar navigation elements`); } catch (error) { console.log('āš ļø Calendar interaction test failed:', error.message); } // Step 8: Test Event Management (need an event ID) console.log('\nāš™ļø Step 8: Testing Event Management...'); // First, try to get an event ID from the dashboard await page.goto('http://localhost:3001/dashboard'); await page.waitForTimeout(2000); let eventId = null; try { // Look for event links that might contain IDs const eventLinks = await page.locator('a[href*="/events/"][href*="/manage"], a[href*="/events/"][href$="/manage"]').all(); if (eventLinks.length > 0) { const href = await eventLinks[0].getAttribute('href'); const match = href.match(/\/events\/([^\/]+)\/manage/); if (match) { eventId = match[1]; console.log(`āœ… Found event ID: ${eventId}`); } } // If no existing event, check if we can create one quickly if (!eventId) { console.log('šŸ“ No existing events found, will use test ID'); eventId = 'test-event-id'; // Use a test ID to see the error page } // Test the event management page await page.goto(`http://localhost:3001/events/${eventId}/manage`); await page.waitForSelector('body', { timeout: 10000 }); await page.waitForTimeout(2000); await page.screenshot({ path: 'event-manage-qa.png', fullPage: true }); console.log('šŸ“ø Screenshot: event-manage-qa.png'); // Test management tabs if present const tabs = await page.locator('[role="tab"], .tab, button:has-text("Tickets"), button:has-text("Venue"), button:has-text("Analytics")').count(); console.log(`šŸ“‘ Found ${tabs} management tab elements`); } catch (error) { console.log('āš ļø Event management test failed:', error.message); } // Step 9: Test Mobile Responsiveness console.log('\nšŸ“± Step 9: Testing Mobile Responsiveness...'); await page.setViewportSize({ width: 375, height: 667 }); // iPhone size await page.goto('http://localhost:3001/dashboard'); await page.waitForTimeout(2000); await page.screenshot({ path: 'dashboard-mobile-qa.png', fullPage: true }); console.log('šŸ“ø Screenshot: dashboard-mobile-qa.png'); await page.goto('http://localhost:3001/scan'); await page.waitForTimeout(2000); await page.screenshot({ path: 'scan-mobile-qa.png', fullPage: true }); console.log('šŸ“ø Screenshot: scan-mobile-qa.png'); // Step 10: Test Navigation console.log('\n🧭 Step 10: Testing Navigation...'); await page.setViewportSize({ width: 1280, height: 720 }); // Back to desktop await page.goto('http://localhost:3001/dashboard'); await page.waitForTimeout(2000); // Test navigation menu try { const navItems = await page.locator('nav a, .nav-item, [role="navigation"] a').count(); console.log(`🧭 Found ${navItems} navigation items`); // Test menu toggle if present const menuToggle = await page.locator('button[aria-label*="menu"], .menu-toggle, .hamburger').first(); if (await menuToggle.count() > 0) { await menuToggle.click(); await page.waitForTimeout(1000); await page.screenshot({ path: 'navigation-open-qa.png', fullPage: true }); console.log('šŸ“ø Screenshot: navigation-open-qa.png'); } } catch (error) { console.log('āš ļø Navigation test failed:', error.message); } // Final Report console.log('\nšŸ“Š QA AUDIT RESULTS:'); console.log('====================='); console.log(`āœ… Total screenshots taken: 10+`); console.log(`āŒ Console errors: ${consoleErrors.length}`); console.log(`🌐 Network errors: ${networkErrors.length}`); if (consoleErrors.length > 0) { console.log('\n🚨 CONSOLE ERRORS:'); consoleErrors.forEach(error => console.log(` - ${error}`)); } if (networkErrors.length > 0) { console.log('\n🌐 NETWORK ERRORS:'); networkErrors.forEach(error => console.log(` - ${error}`)); } // Create summary report const report = { timestamp: new Date().toISOString(), routes_tested: [ '/login', '/dashboard', '/events/new', '/scan', '/templates', '/admin/dashboard', '/calendar', `/events/${eventId}/manage` ], screenshots_taken: [ 'login-form-qa.png', 'dashboard-qa.png', 'events-new-qa.png', 'scan-qa.png', 'templates-qa.png', 'admin-dashboard-qa.png', 'calendar-qa.png', 'event-manage-qa.png', 'dashboard-mobile-qa.png', 'scan-mobile-qa.png', 'navigation-open-qa.png' ], console_errors: consoleErrors, network_errors: networkErrors, status: consoleErrors.length === 0 && networkErrors.length === 0 ? 'PASSED' : 'ISSUES_FOUND' }; fs.writeFileSync('qa-audit-report.json', JSON.stringify(report, null, 2)); console.log('\nšŸ’¾ Report saved to: qa-audit-report.json'); } catch (error) { console.error('āŒ QA Audit failed:', error); } finally { await browser.close(); console.log('\nšŸ QA Audit completed'); } } runComprehensiveQAAudit();