AvanzaCast/e2e/run_e2e_with_mock.js
Cesar Mendivil 8b458a3ddf feat: add initial LiveKit Meet integration with utility scripts, configs, and core components
- Add Next.js app structure with base configs, linting, and formatting
- Implement LiveKit Meet page, types, and utility functions
- Add Docker, Compose, and deployment scripts for backend and token server
- Provide E2E and smoke test scaffolding with Puppeteer and Playwright helpers
- Include CSS modules and global styles for UI
- Add postMessage and studio integration utilities
- Update package.json with dependencies and scripts for development and testing
2025-11-20 12:50:38 -07:00

122 lines
4.4 KiB
JavaScript

// e2e/run_e2e_with_mock.js
// Starts an express mock server in-process, runs the local validator against it, then shuts down.
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const { spawn } = require('child_process');
async function startMock(port = 4001) {
const app = express();
app.use(bodyParser.json());
const sessions = new Map();
function generateId() { return 's' + Math.random().toString(36).slice(2,9); }
app.post('/api/session', (req, res) => {
const body = req.body || {};
const id = generateId();
const token = 'mocktoken-' + Math.random().toString(36).slice(2,12);
sessions.set(id, { token, room: body.room || 'room', username: body.username || 'user' });
const studioUrl = `http://localhost:${port}/studio/${id}`;
res.json({ id, studioUrl, redirectUrl: studioUrl, ttlSeconds: 300 });
});
app.get('/api/session/:id/token', (req, res) => {
const id = req.params.id;
const s = sessions.get(id);
if (!s) return res.status(404).json({ error: 'not_found' });
res.json({ token: s.token, ttlSeconds: 300, room: s.room, username: s.username, url: `ws://localhost:7880` });
});
app.get('/broadcast', (req, res) => {
res.setHeader('Content-Type', 'text/html');
res.send(`<!doctype html>
<html>
<head><meta charset="utf-8"><title>Mock Broadcast</title></head>
<body>
<h1>Broadcast Panel - Mock</h1>
<a id="enter" href="#">Entrar al estudio</a>
<script>
document.getElementById('enter').addEventListener('click', async () => {
try {
const r = await fetch('/api/session', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({ room: 'mock', username: 'tester' }) });
const j = await r.json();
const win = window.open(j.redirectUrl, '_blank');
setTimeout(() => {
try { win.postMessage({ type: 'LIVEKIT_PING' }, '*'); } catch(e){}
}, 500);
} catch (e) { console.error('create session error', e); }
});
window.addEventListener('message', (e) => { console.log('Broadcast received message', e.data); });
</script>
</body>
</html>`);
});
app.get('/studio/:id', (req, res) => {
const id = req.params.id;
res.setHeader('Content-Type', 'text/html');
res.send(`<!doctype html>
<html>
<head><meta charset="utf-8"><title>Mock Studio ${id}</title></head>
<body>
<h1>Studio Portal - Mock</h1>
<div id="status">loading...</div>
<script>
async function init() {
const parts = location.pathname.split('/');
const id = parts[parts.length - 1];
const qs = new URLSearchParams(location.search);
let token = qs.get('token');
if (!token) {
try {
const resp = await fetch('/api/session/' + id + '/token');
if (resp.ok) { const j = await resp.json(); token = j.token; }
} catch(e) { console.error('token fetch error', e); }
}
document.getElementById('status').innerText = token ? ('token=' + token) : 'no token';
try { if (window.opener) { window.opener.postMessage({ type: 'LIVEKIT_ACK', status: token ? 'connected' : 'error', token }, '*'); } } catch(e){}
}
window.addEventListener('message', (e)=>{ if (e.data && e.data.type === 'LIVEKIT_PING') { try { window.opener && window.opener.postMessage({ type: 'LIVEKIT_READY' }, '*'); } catch(e){} } });
init();
</script>
</body>
</html>`);
});
return new Promise((resolve, reject) => {
const server = app.listen(port, () => {
console.log('Mock server listening on', port);
resolve(server);
});
server.on('error', reject);
});
}
(async () => {
const port = 4001;
let server;
try {
server = await startMock(port);
} catch (err) {
console.error('Failed to start mock', err);
process.exit(1);
}
console.log('Running local validator against mock...');
const env = Object.assign({}, process.env, {
BROADCAST_URL: `http://localhost:${port}/broadcast`,
TOKEN: 'mock-runner-token-1',
STUDIO_URL: `http://localhost:${port}/studio`,
});
const child = spawn(process.execPath, [path.join(__dirname, 'validate-flow-domains-local.js')], { env, stdio: 'inherit' });
child.on('exit', (code) => {
console.log('Validator exited with', code);
server.close(() => {
console.log('Mock server stopped');
process.exit(code || 0);
});
});
})();