/** * Comprehensive E2E Test Suite for H2H Betting Platform * * Tests all critical user flows and captures console errors */ const { chromium } = require('playwright'); // Configuration const BASE_URL = 'http://localhost:5173'; const API_URL = 'http://localhost:8000'; // Test users const USERS = { alice: { email: 'alice@example.com', password: 'password123' }, bob: { email: 'bob@example.com', password: 'password123' }, charlie: { email: 'charlie@example.com', password: 'password123' } }; // Collect all console errors let consoleErrors = []; let consoleWarnings = []; async function setupBrowser() { const browser = await chromium.launch({ headless: false }); const context = await browser.newContext({ viewport: { width: 1280, height: 720 } }); const page = await context.newPage(); // Capture console errors and warnings page.on('console', msg => { const type = msg.type(); const text = msg.text(); if (type === 'error') { consoleErrors.push({ text, url: page.url() }); console.log(`❌ Console Error: ${text}`); } else if (type === 'warning') { consoleWarnings.push({ text, url: page.url() }); console.log(`⚠️ Console Warning: ${text}`); } }); // Capture page errors page.on('pageerror', error => { consoleErrors.push({ text: error.message, url: page.url(), stack: error.stack }); console.log(`❌ Page Error: ${error.message}`); }); // Capture failed requests page.on('requestfailed', request => { console.log(`❌ Request Failed: ${request.url()} - ${request.failure().errorText}`); }); return { browser, context, page }; } async function login(page, user) { console.log(`\n🔐 Logging in as ${user.email}...`); await page.goto(BASE_URL); await page.waitForLoadState('networkidle'); // Check if already logged in const isLoggedIn = await page.locator('text=/logout/i').count() > 0; if (isLoggedIn) { console.log('✅ Already logged in'); return; } // Click login/sign in button const loginButton = page.locator('button', { hasText: /sign in|login/i }).first(); if (await loginButton.count() > 0) { await loginButton.click(); await page.waitForTimeout(500); } // Fill in credentials await page.fill('input[type="email"], input[name="email"]', user.email); await page.fill('input[type="password"], input[name="password"]', user.password); // Submit await page.click('button[type="submit"]'); await page.waitForTimeout(2000); console.log('✅ Logged in successfully'); } async function logout(page) { console.log('\n🚪 Logging out...'); const logoutButton = page.locator('button, a', { hasText: /logout|sign out/i }).first(); if (await logoutButton.count() > 0) { await logoutButton.click(); await page.waitForTimeout(1000); console.log('✅ Logged out'); } } async function testMarketplace(page) { console.log('\n📊 Testing Marketplace...'); await page.goto(`${BASE_URL}/marketplace`); await page.waitForLoadState('networkidle'); await page.waitForTimeout(2000); // Check for bet cards const betCards = await page.locator('[class*="bet"], [data-testid*="bet"]').count(); console.log(` Found ${betCards} bet cards`); // Check filters const categoryFilters = await page.locator('button, select', { hasText: /sports|entertainment|politics|custom/i }).count(); console.log(` Found ${categoryFilters} category filters`); console.log('✅ Marketplace loaded'); } async function testWallet(page) { console.log('\n💰 Testing Wallet...'); await page.goto(`${BASE_URL}/wallet`); await page.waitForLoadState('networkidle'); await page.waitForTimeout(2000); // Check wallet balance display const balanceElements = await page.locator('text=/balance|\\$/i').count(); console.log(` Found ${balanceElements} balance elements`); // Check for deposit button const depositButton = await page.locator('button', { hasText: /deposit|add funds/i }).count(); console.log(` Deposit button present: ${depositButton > 0}`); console.log('✅ Wallet loaded'); } async function testCreateBet(page) { console.log('\n➕ Testing Create Bet...'); await page.goto(`${BASE_URL}/marketplace`); await page.waitForLoadState('networkidle'); // Find and click create bet button const createButton = page.locator('button', { hasText: /create|new bet/i }).first(); if (await createButton.count() === 0) { console.log('⚠️ Create bet button not found'); return; } await createButton.click(); await page.waitForTimeout(1000); // Check if modal opened const modalOpen = await page.locator('[role="dialog"], .modal').count() > 0; console.log(` Modal opened: ${modalOpen}`); if (modalOpen) { // Fill in bet details console.log(' Filling bet form...'); await page.fill('input[type="text"]').first().fill('Test Bet Title'); await page.locator('textarea').first().fill('This is a test bet description'); // Find stake amount input const stakeInput = page.locator('input[type="number"]').first(); await stakeInput.fill('10'); // Look for submit button const submitButton = page.locator('button[type="submit"], button', { hasText: /create|submit/i }).last(); console.log(` Submit button found: ${await submitButton.count() > 0}`); // Don't actually submit - just testing the form opens const cancelButton = page.locator('button', { hasText: /cancel/i }).first(); if (await cancelButton.count() > 0) { await cancelButton.click(); await page.waitForTimeout(500); } } console.log('✅ Create bet flow tested'); } async function testMyBets(page) { console.log('\n📋 Testing My Bets...'); await page.goto(`${BASE_URL}/my-bets`); await page.waitForLoadState('networkidle'); await page.waitForTimeout(2000); // Check for tabs const tabs = await page.locator('[role="tab"], button[class*="tab"]').count(); console.log(` Found ${tabs} tabs`); console.log('✅ My Bets loaded'); } async function testNavigation(page) { console.log('\n🧭 Testing Navigation...'); const routes = [ { path: '/marketplace', name: 'Marketplace' }, { path: '/my-bets', name: 'My Bets' }, { path: '/wallet', name: 'Wallet' } ]; for (const route of routes) { console.log(` Navigating to ${route.name}...`); await page.goto(`${BASE_URL}${route.path}`); await page.waitForLoadState('networkidle'); await page.waitForTimeout(1000); } console.log('✅ Navigation tested'); } async function runTests() { console.log('🧪 Starting Comprehensive E2E Tests\n'); console.log('=' .repeat(60)); const { browser, page } = await setupBrowser(); try { // Test 1: Login Flow console.log('\n📝 TEST 1: Login Flow'); await login(page, USERS.alice); // Test 2: Marketplace console.log('\n📝 TEST 2: Marketplace'); await testMarketplace(page); // Test 3: Wallet console.log('\n📝 TEST 3: Wallet'); await testWallet(page); // Test 4: Create Bet console.log('\n📝 TEST 4: Create Bet'); await testCreateBet(page); // Test 5: My Bets console.log('\n📝 TEST 5: My Bets'); await testMyBets(page); // Test 6: Navigation console.log('\n📝 TEST 6: Navigation'); await testNavigation(page); // Test 7: Logout console.log('\n📝 TEST 7: Logout'); await logout(page); // Summary console.log('\n' + '='.repeat(60)); console.log('📊 TEST SUMMARY\n'); console.log(`Console Errors: ${consoleErrors.length}`); if (consoleErrors.length > 0) { console.log('\n❌ CONSOLE ERRORS:'); consoleErrors.forEach((err, i) => { console.log(`\n${i + 1}. ${err.text}`); console.log(` Page: ${err.url}`); if (err.stack) { console.log(` Stack: ${err.stack.split('\n')[0]}`); } }); } console.log(`\nConsole Warnings: ${consoleWarnings.length}`); if (consoleWarnings.length > 0 && consoleWarnings.length < 20) { console.log('\n⚠️ CONSOLE WARNINGS:'); consoleWarnings.forEach((warn, i) => { console.log(`${i + 1}. ${warn.text}`); }); } console.log('\n' + '='.repeat(60)); if (consoleErrors.length === 0) { console.log('✅ All tests passed with no console errors!'); } else { console.log(`⚠️ Tests completed with ${consoleErrors.length} console errors`); } } catch (error) { console.error('\n❌ Test failed:', error); } finally { console.log('\n🔍 Keeping browser open for 10 seconds for inspection...'); await page.waitForTimeout(10000); await browser.close(); } } // Run tests runTests().catch(console.error);