107 lines
3.5 KiB
JavaScript
107 lines
3.5 KiB
JavaScript
/**
|
|
* 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<void>}
|
|
*/
|
|
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<void>}
|
|
*/
|
|
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<string | null>} 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)
|
|
}
|