#!/usr/bin/env node // E2E test: session_loader // - Creates a session via backend-api POST /api/session // - Opens broadcast panel at / // - Waits for sessionStorage key and verifies token/url present const puppeteer = require('puppeteer'); const fetch = require('node-fetch'); (async () => { const BACKEND = process.env.BACKEND || 'http://localhost:4000'; const BROADCAST = process.env.BROADCAST || 'http://localhost:5175'; const HEADLESS = process.env.HEADLESS !== '0'; // set HEADLESS=0 to see browser console.log('Using BACKEND=%s BROADCAST=%s HEADLESS=%s', BACKEND, BROADCAST, HEADLESS); // 1) create session via backend const room = 'e2e-test-room-' + Math.random().toString(36).slice(2,8); const username = 'e2e-user'; console.log('Creating session for room=%s username=%s', room, username); let resp; try { resp = await fetch(`${BACKEND.replace(/\/$/, '')}/api/session`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ room, username }) }); } catch (err) { console.error('Failed to reach backend to create session:', String(err)); process.exit(2); } if (!resp.ok) { console.error('Failed to create session on backend:', resp.status); const txt = await resp.text().catch(()=>null); console.error('Body:', txt); process.exit(2); } const js = await resp.json(); const sessionId = js.id || js.sessionId || js.id; if (!sessionId) { console.error('Session creation response missing id:', js); process.exit(2); } console.log('Created session id=', sessionId); // 2) open broadcast panel at / const url = `${BROADCAST.replace(/\/$/, '')}/${encodeURIComponent(sessionId)}`; console.log('Opening', url); const browser = await puppeteer.launch({ headless: HEADLESS, args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'] }); const page = await browser.newPage(); page.on('console', msg => console.log('PAGE LOG:', msg.text())); page.on('pageerror', err => console.error('PAGE ERROR:', err.message)); try { await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 }); } catch (e) { console.error('Failed to open broadcast panel url:', e.message); // capture screenshot for debugging if possible try { await page.screenshot({ path: '/tmp/e2e_page_error.png', fullPage: false }); console.log('Saved screenshot to /tmp/e2e_page_error.png'); } catch(e){} await browser.close(); process.exit(3); } // wait for sessionStorage key with retry const STORE_KEY = process.env.STORE_KEY || 'avanzacast_studio_session'; console.log('Waiting for sessionStorage key=', STORE_KEY); let found = null; try { found = await page.waitForFunction((k) => { try { return !!sessionStorage.getItem(k); } catch (e) { return false } }, { timeout: 15000 }, STORE_KEY).catch(()=>null); } catch (err) { found = null } if (!found) { console.error('sessionStorage key not found within timeout'); try { const html = await page.content(); console.error('Page content snapshot length:', html.length); } catch(e){} try { await page.screenshot({ path: '/tmp/e2e_no_sessionstorage.png' }); console.log('Saved screenshot to /tmp/e2e_no_sessionstorage.png'); } catch(e){} await browser.close(); process.exit(4); } const stored = await page.evaluate((k) => sessionStorage.getItem(k), STORE_KEY); console.log('Stored value (truncated):', stored && stored.slice(0, 400)); let parsed = null; try { parsed = JSON.parse(stored); } catch (e) { console.error('Failed to parse stored JSON', e); } if (!parsed) { console.error('No valid session stored'); await browser.close(); process.exit(5); } // Accept either token or participantToken const token = parsed.token || parsed.participantToken || parsed.access_token || parsed.token; const urlField = parsed.url || parsed.serverUrl || parsed.studioUrl || parsed.redirectUrl; console.log('Extracted token prefix:', token ? token.slice(0, 24) + '...' : '(none)'); console.log('Extracted url:', urlField || '(none)'); if (!token) { console.error('Token not found in stored session'); await browser.close(); process.exit(6); } // Optionally validate token via backend validate proxy try { const v = await fetch(`${BACKEND.replace(/\/$/, '')}/api/session/validate?token=${encodeURIComponent(token)}`); const vt = await v.text(); console.log('Validate response (first 400 chars):', vt && vt.slice(0,400)); } catch (e) { console.warn('Validate proxy call failed:', e.message); } console.log('E2E test succeeded'); await browser.close(); process.exit(0); })();