# E2E — Validación del flujo Broadcast → Studio Este README recoge cómo ejecutar, depurar e interpretar las pruebas E2E del flujo Broadcast Panel → StudioPortal (activación de sesión LiveKit). Está pensado para desarrolladores e infra-ops que deben validar el flujo tanto localmente como contra entornos remotos (Browserless / Chrome remoto). Resumen rápido - Objetivo: validar que al crear una sesión (POST /api/session) el Broadcast Panel abra el Studio y que el Studio reciba el token (vía postMessage o `?token=`) y lo persista en `sessionStorage` para que el cliente LiveKit se conecte. - Ubicación de los scripts: `e2e/` - Artefactos de salida: JSON y capturas PNG en `e2e/` Prerequisitos - Node.js (v16+ recomendado) - npm - Chrome local o un Chrome remoto con remote-debugging habilitado (puerto 9222) para ejecución con `validate-flow-remote-chrome.js` o un servidor Browserless accesible (WSS) para `validate-flow-browserless.js`. Archivos principales en `e2e/` - `validate-flow-domains-local.js` — validador local (usa file:// o URLs HTTP locales) - `validate-flow-browserless.js` — validador que se conecta a Browserless (puppeteer-core) - `validate-flow-remote-chrome.js` — validador que se conecta a Chrome remoto (debug port / ws) - `simulate_token_query_browserless.js` — prueba que inyecta `?token=` y abre el Studio - `mock_server.js` — servidor Express mock (dev) que emula endpoints `/api/session` y `/studio/:id` (útil para pruebas offline) - `run_e2e_with_mock.js` — helper que arranca el mock en proceso y ejecuta el validador local - `validate-flow-remote-chrome-result.json` (y otros JSON) — resultados de ejecución con consola, navigations y assertions Variables de entorno usadas (ejemplos) - `BROWSERLESS_WS` — WebSocket endpoint a Browserless (ej. `wss://...`) - `BROWSERLESS_TOKEN` — token del servicio Browserless - `CHROME_HOST` / `CHROME_WS` — host:port (p.ej. `host:9222`) o websocket de Chrome remoto - `BROADCAST_URL` — URL del Broadcast Panel (ej: `https://avanzacast-broadcastpanel.bfzqqk.easypanel.host`) - `STUDIO_URL` — URL base del Studio (ej: `https://avanzacast-studio.bfzqqk.easypanel.host`) - `TOKEN` — token de prueba (opcional, para forzar `?token=` fallback) Comandos (rápidos) — ejecuciones locales y remotas 1) Prueba local rápida (usa la página de prueba `e2e/test-pages/broadcast.html`) ```bash cd e2e BROADCAST_URL="file://$(pwd)/test-pages/broadcast.html" \ TOKEN="testtoken123" STUDIO_URL="about:blank" \ node validate-flow-domains-local.js ``` Salida: `e2e/studio-flow-domains-result.json` + `e2e/studio_flow_result.png` 2) Usar el mock server (arranca servidor y valida fluxo realista) ```bash # en una terminal cd e2e node mock_server.js # en otra terminal BROADCAST_URL="http://localhost:4001/broadcast" \ TOKEN="local-mock-token" STUDIO_URL="http://localhost:4001/studio" \ node validate-flow-domains-local.js ``` Salida: JSON + capturas en `e2e/` 3) Ejecutar contra Browserless remoto ```bash cd /path/to/repo BROWSERLESS_WS="wss://browserless.example" \ BROWSERLESS_TOKEN="your_token" \ BROADCAST_URL="https://avanzacast-broadcastpanel.bfzqqk.easypanel.host" \ STUDIO_URL="https://avanzacast-studio.bfzqqk.easypanel.host" \ node validate-flow-browserless.js ``` Salida: `e2e/validate-flow-browserless-result.json` + screenshot 4) Ejecutar contra Chrome remoto (remote debugging, puerto 9222) ```bash # obtener websocket URL (ejemplo local) y ejecutar WS=$(curl -s http://localhost:9222/json/version | python3 -c "import sys,json;print(json.load(sys.stdin).get('webSocketDebuggerUrl',''))") cd e2e CHROME_WS="$WS" \ BROADCAST_URL="https://avanzacast-broadcastpanel.bfzqqk.easypanel.host" \ STUDIO_URL="https://avanzacast-studio.bfzqqk.easypanel.host" \ TOKEN="e2e098863b912f6a178b68e71ec3c58d" \ node validate-flow-remote-chrome.js ``` Salida: `e2e/validate-flow-remote-chrome-result.json` + screenshot ### Validar flujo `/:id` (session id stored in DB -> broadcast panel) Hemos añadido un test E2E específico que valida el flujo en el que el token-server crea una sesión y el Broadcast Panel la consume a través de la ruta `/:id`. Script: `e2e/validate-session-id-flow.js` Qué hace: - POST `/api/session` en `VITE_BACKEND_TOKENS_URL` (o `https://avanzacast-servertokens.bfzqqk.easypanel.host` por defecto) para crear una sesión. - Abre `BROADCAST_URL/:id` (usando `BROWSER_WS` / `BROWSERLESS_WS`) y verifica que `sessionStorage` contiene la sesión. - Llama a `/api/session/:id/token` y guarda el resultado en JSON + captura. Ejecución (Browserless): ```bash cd e2e BROWSERLESS_WS="wss://browserless.bfzqqk.easypanel.host" \ BROWSERLESS_TOKEN="" \ node validate-session-id-flow.js ``` Ejecución (Chrome remoto): ```bash WS=$(curl -s http://localhost:9222/json/version | python3 -c "import sys,json;print(json.load(sys.stdin).get('webSocketDebuggerUrl',''))") cd e2e BROWSER_WS="$WS" node validate-session-id-flow.js ``` Salida: - `e2e/validate-session-id-flow-result.json` - `e2e/validate-session-id-flow.png` Diagnóstico y debugging (token-server y 502) - Si ves errores `Failed to load resource: 502`, verifica el token-server y el reverse-proxy: ```bash curl -i 'https://avanzacast-servertokens.bfzqqk.easypanel.host/health' curl -i -X POST 'https://avanzacast-servertokens.bfzqqk.easypanel.host/api/session' -H 'Content-Type: application/json' -d '{"room":"diag","username":"diag"}' # script de diagnóstico (recopila headers y logs) node ../scripts/check_token_server_node.mjs https://avanzacast-servertokens.bfzqqk.easypanel.host testroom e2euser ``` - Si el POST/GET token responde 200 con JSON y token -> backend OK; si no, revisa logs del proxy (nginx/EasyPanel) y del contenedor del token-server. Infra: Alinear claves LiveKit (token-server ↔ LiveKit) Si las pruebas E2E fallan con errores 401 al conectar a LiveKit, normalmente significa que el token-server está firmando tokens con una clave (API key / secret) distinta a la que LiveKit espera. He incluido dos helpers en `scripts/` para actualizar y verificar la configuración del token-server: - `scripts/update_token_server_env.sh` — actualiza `LIVEKIT_API_KEY` y `LIVEKIT_API_SECRET` en el archivo `.env` del token-server y recrea el servicio (docker-compose). Uso seguro: hace backup del archivo `.env` antes de modificarlo. - `scripts/verify_token_server_after_update.sh` — crea una sesión de prueba en el token-server, obtiene el token y (si tienes `websocat` instalado) intenta una conexión WebSocket básica a la URL reportada por el token-server (esto es un sanity-check, no un handshake RTC completo). Comandos de ejemplo 1) Actualiza las claves en el `.env` del token-server y recrea el servicio (ajusta paths y nombre del servicio según tu despliegue): ```bash ./scripts/update_token_server_env.sh \ --env-file /path/to/token-server/.env \ --compose-file /path/to/docker-compose.yml \ --service token-server \ --livekit-key \ --livekit-secret ``` 2) Verifica que el token-server crea sesiones y devuelve token: ```bash ./scripts/verify_token_server_after_update.sh \ --session-room e2e_room \ --session-user e2e_user \ --token-server-url https://avanzacast-servertokens.bfzqqk.easypanel.host ``` Notas de seguridad - No guardes secretos en repositorios públicos. - El script hace backup del `.env` antes de editarlo. Si quieres, puedo aplicar (probar) estas acciones en tu entorno si me indicas: - el path al `.env` y al `docker-compose.yml` que controla `token-server`, o - si prefieres que prepare los comandos para que el administrador los ejecute por SSH (yo te doy el playbook exacto). Estructura del JSON de resultados - `startedAt` / `endedAt` — timestamps - `console` — array de mensajes capturados de consola (type, text) - `navigations` — array con pasos realizados (ej: `broadcast_loaded`, `studio_opened`, `direct_studio`) - `assertions` — (cuando se configuraron) array con { name, ok, detail } - `screenshot` — ruta absoluta del PNG generado Ejemplo de interpretación rápida - Si `assertions` muestra `sessionStorage_has_token: ok: true` y `studio_page_shows_token: ok: true` → flujo verificado (la sesión fue creada o inyectada y el Studio la recibió). - Si hay 502 en `console` → probable problema infra (proxy / token-server) o asset roto; ejecutar scripts de diagnóstico. Cómo añadir nuevas aserciones - Edita `e2e/validate-flow-remote-chrome.js` o `validate-flow-browserless.js` y añade comprobaciones en el bloque que ejecuta `studioPage.evaluate(...)` o consulta `sessionStorage` en la página broadcast. - Patrón de aserción: ```js results.assertions.push({ name: 'my_assertion', ok: boolean, detail: 'mensaje' }) ``` - Re-run el script y revisar `results.assertions` en el JSON. Integración en CI (recomendación) - Usa el workflow `/.github/workflows/validate-studio-flow-browserless.yml` (ya incluido). El workflow requiere los inputs `browserless_ws` y `browserless_token`. Configura secrets y ejecútalo desde Actions para runs periódicos o en PRs. Preguntas frecuentes / troubleshooting - Q: ¿Por qué el test abre el Studio directamente (`direct_studio`) en lugar de simular el click? A: Si el popup está bloqueado o el selector no se encuentra, el script hace fallback y navega directamente con `?token=`. Aumenta timeouts o agrega selectores más específicos si quieres forzar la simulación del click. - Q: Veo OTS parsing errors en consola (fuentes). ¿Importa? A: No para la E2E funcional; afecta sólo la carga de un archivo `.woff` o la validación visual. Revisa la fuente y el servidor que la sirve. Contacto / notas finales - Los scripts y la lógica han sido añadidos para que puedas automatizar y auditar la activación del StudioPortal. Si quieres, puedo: - añadir aserciones adicionales específicas (ej. TTL, usuario, room), - crear el README en `e2e/README.md` (este archivo), - añadir tests en CI que fallen si alguna aserción no pasa. --- Si quieres que genere además un archivo `e2e/LOG.md` o un registro más formal por cada ejecución (con timestamp, link a artifact, resultado de aserciones), lo creo ahora y lo integro automáticamente cuando corre el validador. ¿Lo añado? (responde "Sí, crea LOG.md")