148 lines
5.9 KiB
JavaScript
148 lines
5.9 KiB
JavaScript
import { chromium } from 'playwright';
|
|
import { spawn } from 'child_process';
|
|
import path from 'path';
|
|
|
|
console.log('run_e2e: starting (pid=' + process.pid + ')');
|
|
console.log('ENV VITE_STUDIO_URL=' + (process.env.VITE_STUDIO_URL || ''));
|
|
console.log('ENV VITE_BROADCASTPANEL_URL=' + (process.env.VITE_BROADCASTPANEL_URL || ''));
|
|
console.log('ENV VITE_TOKEN_SERVER_URL=' + (process.env.VITE_TOKEN_SERVER_URL || ''));
|
|
|
|
const serverPath = path.resolve('./server.mjs');
|
|
const base = 'http://localhost:5174';
|
|
|
|
// Allow overriding the target origin via ENV (e.g., VITE_STUDIO_URL)
|
|
const targetOrigin = process.env.VITE_STUDIO_URL || process.env.TARGET_ORIGIN || '';
|
|
// If provided, open this as the sender page so origin matches allowed production origins
|
|
const broadcastSender = process.env.VITE_BROADCASTPANEL_URL || '';
|
|
// Token server URL for obtaining tokens automatically
|
|
const tokenServer = process.env.VITE_TOKEN_SERVER_URL || process.env.TOKEN_SERVER_URL || '';
|
|
|
|
async function startServer() {
|
|
console.log('run_e2e: starting static server at', serverPath);
|
|
const proc = spawn(process.execPath, [serverPath], { env: { ...process.env, PORT: '5174' }, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
proc.stdout.on('data', d => process.stdout.write('[server] ' + d.toString()));
|
|
proc.stderr.on('data', d => process.stderr.write('[server] ' + d.toString()));
|
|
await new Promise(r => setTimeout(r, 300));
|
|
console.log('run_e2e: static server started');
|
|
return proc;
|
|
}
|
|
|
|
// helper: request token from token server
|
|
async function requestTokenFromServer() {
|
|
if (!tokenServer) return null;
|
|
try {
|
|
// If SESSION_ID is provided, request that session; otherwise use a default /api/session/e2e endpoint
|
|
const sessionId = process.env.SESSION_ID || '';
|
|
const endpoint = sessionId ? `/api/session/${encodeURIComponent(sessionId)}` : '/api/session/e2e';
|
|
const url = `${tokenServer.replace(/\/$/, '')}${endpoint}`;
|
|
console.log('Requesting token from', url, sessionId ? `(sessionId=${sessionId})` : '(default)');
|
|
const res = await fetch(url, { method: 'GET' });
|
|
if (!res.ok) {
|
|
console.warn('Token server returned', res.status);
|
|
return null;
|
|
}
|
|
const data = await res.json();
|
|
if (data && data.token) return data;
|
|
return null;
|
|
} catch (err) {
|
|
console.warn('Token request failed:', String(err));
|
|
return null;
|
|
}
|
|
}
|
|
|
|
async function run() {
|
|
console.log('run_e2e: launching browser');
|
|
const server = await startServer();
|
|
const browser = await chromium.launch({ headless: true });
|
|
console.log('run_e2e: browser launched');
|
|
const context = await browser.newContext();
|
|
const page = await context.newPage();
|
|
|
|
let url;
|
|
if (broadcastSender) {
|
|
url = broadcastSender; // open prod broadcast panel as sender
|
|
console.log('Opening broadcast sender at', url);
|
|
} else {
|
|
url = base + '/sender.html';
|
|
if (targetOrigin) url += '?target=' + encodeURIComponent(targetOrigin);
|
|
console.log('Opening local sender at', url);
|
|
}
|
|
|
|
console.log('run_e2e: navigating to', url);
|
|
await page.goto(url);
|
|
console.log('run_e2e: page loaded');
|
|
|
|
// If we opened local sender, click UI; if we opened remote broadcast page we try to trigger postMessage via evaluate
|
|
if (!broadcastSender) {
|
|
await page.click('#open');
|
|
}
|
|
|
|
// Before sending a token, try to fetch a fresh token from the token server
|
|
let token = 'E2E_TEST_TOKEN'; // fallback
|
|
let tokenMeta = null;
|
|
try {
|
|
tokenMeta = await requestTokenFromServer();
|
|
if (tokenMeta && tokenMeta.token) {
|
|
token = tokenMeta.token;
|
|
console.log('Obtained token from server, using it for handshake');
|
|
} else {
|
|
console.log('No token from server, using fallback token');
|
|
}
|
|
} catch (e) {
|
|
console.warn('Token fetch error, using fallback token', e);
|
|
}
|
|
|
|
if (!broadcastSender) {
|
|
// send token from the local sender UI (click send)
|
|
await page.click('#send');
|
|
// but override the message in the page to use the token we fetched
|
|
try {
|
|
await page.evaluate((tok) => {
|
|
if (window.__studioPopup && !window.__studioPopup.closed) {
|
|
try {
|
|
window.__studioPopup.postMessage({ type: 'LIVEKIT_TOKEN', token: tok, room: 'e2e-room' }, window.__studioPopup.location?.origin || '*');
|
|
} catch (e) {
|
|
// fallback: send to global origin used by the page
|
|
try { window.postMessage({ type: 'LIVEKIT_TOKEN', token: tok, room: 'e2e-room' }, location.origin); } catch(e){}
|
|
}
|
|
}
|
|
}, token);
|
|
} catch (e) { console.warn('Override send failed', e); }
|
|
} else {
|
|
// For remote broadcast panel, open the studio popup and post message using the fetched token
|
|
await page.evaluate(async (studioUrl, tok) => {
|
|
// open popup
|
|
window.popupForE2E = window.open(studioUrl, 'studioPopup', 'width=800,height=600');
|
|
// wait for a moment and then post the token
|
|
await new Promise(r => setTimeout(r, 600));
|
|
try {
|
|
window.popupForE2E.postMessage({ type: 'LIVEKIT_TOKEN', token: tok, room: 'e2e-room' }, studioUrl);
|
|
} catch (e) {
|
|
console.error('postMessage failed inside page eval', e);
|
|
}
|
|
}, targetOrigin || '', token);
|
|
}
|
|
|
|
// wait for token ack
|
|
await page.waitForFunction(() => {
|
|
const p = document.querySelector('pre');
|
|
return p && p.textContent && p.textContent.includes('LIVEKIT_TOKEN_ACK');
|
|
}, { timeout: 7000 }).catch(()=>{});
|
|
|
|
// wait for connected ack
|
|
await page.waitForFunction(() => {
|
|
const p = document.querySelector('pre');
|
|
return p && p.textContent && p.textContent.includes('LIVEKIT_ACK') && p.textContent.includes('connected');
|
|
}, { timeout: 7000 }).catch(()=>{});
|
|
|
|
console.log('run_e2e: finished script, collecting logs');
|
|
const log = await page.$eval('pre', el => el.textContent).catch(()=>'');
|
|
console.log('E2E log:\n', log);
|
|
|
|
await browser.close();
|
|
console.log('run_e2e: browser closed, killing server');
|
|
server.kill();
|
|
}
|
|
|
|
run().catch(err => { console.error('run_e2e: fatal error', err); process.exit(1); });
|