/** * WebRTC test utilities for E2E tests. */ /** * Wait for video element to start playing. * @param {import('@playwright/test').Page} page * @param {string} selector - CSS selector for video element * @param {number} timeoutMs - Timeout in milliseconds * @returns {Promise} */ export async function waitForVideoPlaying(page, selector = 'video', timeoutMs = 30000) { await page.waitForSelector(selector, { timeout: timeoutMs }) // Wait for video to have metadata loaded and valid dimensions await page.waitForFunction( (sel) => { const video = document.querySelector(sel) if (!video) return false // readyState >= 2 means HAVE_CURRENT_DATA (has metadata) // videoWidth > 0 means video has actual dimensions (not black screen) return video.readyState >= 2 && video.videoWidth > 0 && video.videoHeight > 0 }, selector, { timeout: timeoutMs }, ) } /** * Wait for session to appear in the active sessions list with hasStream: true. * @param {import('@playwright/test').Page} page * @param {string} sessionId - Session ID to wait for * @param {number} timeoutMs - Timeout in milliseconds * @returns {Promise} */ export async function waitForSessionToAppear(page, sessionId, timeoutMs = 30000) { const startTime = Date.now() const pollInterval = 1000 // Poll every second while (Date.now() - startTime < timeoutMs) { try { // Call /api/live endpoint to check for session const response = await page.request.get('/api/live') if (response.ok()) { const sessions = await response.json() const session = sessions.find(s => s.id === sessionId && s.hasStream === true) if (session) { return // Session found with stream } } } catch { // API call failed, continue polling } await new Promise(resolve => setTimeout(resolve, pollInterval)) } throw new Error(`Session ${sessionId} did not appear with hasStream: true within ${timeoutMs}ms`) } /** * Get session ID from share-live page state. * @param {import('@playwright/test').Page} page * @returns {Promise} Session ID or null if not found */ export async function getSessionIdFromPage(page) { try { // Brief delay so producer is registered on server await new Promise(resolve => setTimeout(resolve, 1500)) // Use API to get active sessions (page has auth cookies) const response = await page.request.get('/api/live') if (response.ok()) { const sessions = await response.json() const withStream = sessions.filter(s => s.hasStream === true) // Most recently updated session with stream is ours const activeSession = withStream.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0))[0] return activeSession?.id || null } } catch (error) { console.error('[test] Failed to get session ID:', error) } return null } /** * Verify video is playing (not paused, has dimensions). * @param {import('@playwright/test').Page} page * @param {string} selector - CSS selector for video element * @returns {Promise<{ width: number, height: number, playing: boolean }>} Video dimensions and playing state. */ export async function getVideoState(page, selector = 'video') { return await page.evaluate((sel) => { const video = document.querySelector(sel) if (!video) { return { width: 0, height: 0, playing: false } } return { width: video.videoWidth, height: video.videoHeight, playing: !video.paused && video.readyState >= 2, } }, selector) }