import { test, expect } from '@playwright/test'; test.describe('Bet Creation and Taking E2E', () => { test('Create bet as Alice via TradingPanel', async ({ page }) => { const errors: string[] = []; const networkErrors: string[] = []; page.on('pageerror', error => { console.log('Page error:', error.message); errors.push(error.message); }); page.on('response', response => { if (response.status() >= 400) { networkErrors.push(`${response.status()} ${response.url()}`); } }); // Login as Alice await page.goto('/login'); await page.fill('input[type="email"]', 'alice@example.com'); await page.fill('input[type="password"]', 'password123'); await page.click('button[type="submit"]'); // Wait for login to complete await page.waitForURL('/', { timeout: 10000 }); console.log('Alice logged in successfully'); // Navigate to event page await page.goto('/events/1', { waitUntil: 'networkidle' }); await page.waitForTimeout(2000); // Take screenshot before await page.screenshot({ path: 'test-results/bet-create-before.png', fullPage: true }); // Check if TradingPanel is visible const placeBetSection = await page.locator('text=Place Bet').first(); expect(await placeBetSection.isVisible()).toBe(true); console.log('Place Bet section is visible'); // Get initial bet count from stats const betsText = await page.locator('text=/Bets:.*\\d+/').first().textContent(); const initialBets = parseInt(betsText?.match(/\d+/)?.[0] || '0'); console.log('Initial bet count:', initialBets); // Select home team (should already be selected by default) const homeTeamBtn = page.locator('button').filter({ hasText: /Wake Forest|Home/i }).first(); if (await homeTeamBtn.isVisible()) { await homeTeamBtn.click(); } // Enter stake amount const stakeInput = page.locator('input[type="number"]'); await stakeInput.fill('50'); console.log('Entered stake amount: 50'); // Click create bet button const createBetBtn = page.locator('button').filter({ hasText: /Create.*Bet/i }).first(); expect(await createBetBtn.isVisible()).toBe(true); // Listen for API response const responsePromise = page.waitForResponse( response => response.url().includes('/api/v1/spread-bets') && response.request().method() === 'POST', { timeout: 10000 } ); await createBetBtn.click(); console.log('Clicked Create Bet button'); // Wait for API response try { const response = await responsePromise; console.log('API Response status:', response.status()); const body = await response.json(); console.log('API Response body:', JSON.stringify(body, null, 2)); expect(response.status()).toBe(200); console.log('Bet created successfully via API!'); } catch (e) { console.log('No API response received or error:', e); } // Wait for UI update await page.waitForTimeout(2000); // Take screenshot after await page.screenshot({ path: 'test-results/bet-create-after.png', fullPage: true }); // Check for success toast const toastVisible = await page.locator('text=successfully').isVisible({ timeout: 5000 }).catch(() => false); console.log('Success toast visible:', toastVisible); // Log any errors console.log('Page errors:', errors); console.log('Network errors:', networkErrors); expect(errors.length).toBe(0); }); test('Take bet as Bob', async ({ page }) => { const errors: string[] = []; const networkErrors: string[] = []; page.on('pageerror', error => { console.log('Page error:', error.message); errors.push(error.message); }); page.on('response', response => { if (response.status() >= 400) { networkErrors.push(`${response.status()} ${response.url()}`); } }); // Login as Bob await page.goto('/login'); await page.fill('input[type="email"]', 'bob@example.com'); await page.fill('input[type="password"]', 'password123'); await page.click('button[type="submit"]'); await page.waitForURL('/', { timeout: 10000 }); console.log('Bob logged in successfully'); // Navigate to event page await page.goto('/events/1', { waitUntil: 'networkidle' }); await page.waitForTimeout(2000); await page.screenshot({ path: 'test-results/bob-event-page.png', fullPage: true }); // Look for "Take" button in the TradingPanel const takeBtn = page.locator('button').filter({ hasText: 'Take' }).first(); if (await takeBtn.isVisible({ timeout: 5000 }).catch(() => false)) { console.log('Found Take button'); // Listen for API response const responsePromise = page.waitForResponse( response => response.url().includes('/api/v1/spread-bets') && response.url().includes('/take'), { timeout: 10000 } ); await takeBtn.click(); console.log('Clicked Take button'); try { const response = await responsePromise; console.log('Take bet API Response status:', response.status()); const body = await response.json(); console.log('Take bet API Response:', JSON.stringify(body, null, 2)); expect(response.status()).toBe(200); expect(body.status).toBe('matched'); console.log('Bet taken successfully!'); } catch (e) { console.log('Take bet API error:', e); } } else { console.log('No Take button found - checking available bets'); // List what buttons are available const buttons = await page.locator('button').allTextContents(); console.log('Available buttons:', buttons.filter(b => b.trim())); } await page.waitForTimeout(1000); await page.screenshot({ path: 'test-results/bob-after-take.png', fullPage: true }); console.log('Page errors:', errors); console.log('Network errors:', networkErrors); }); });