AvanzaCast/packages/studio-panel/scripts/playwright_postmessage_test.mjs

153 lines
7.0 KiB
JavaScript

import fs from 'fs';
let playwright;
try { playwright = await import('playwright'); } catch (e) { fs.appendFileSync('/tmp/playwright_debug.log', `Playwright import error: ${e}\n`); process.exit(2); }
const { chromium } = playwright;
const LOG = '/tmp/playwright_debug.log';
function log(msg){
const line = `[${new Date().toISOString()}] ${msg}\n`;
try{ fs.appendFileSync(LOG, line); } catch(e) {}
}
(async ()=>{
log('Starting playwright_postmessage_test');
let browser;
try{
browser = await chromium.launch({ headless: true, args: ['--no-sandbox','--disable-dev-shm-usage'] });
log('Chromium launched');
const context = await browser.newContext();
const page = await context.newPage();
page.on('console', m => log('PAGE LOG: ' + m.text()));
let studioConsoleLogs = [];
// Use environment variables if provided, otherwise default to production domains
const BROADCAST_URL = process.env.BROADCAST_URL || 'https://avanzacast-broadcastpanel.bfzqqk.easypanel.host/post_token_to_studio.html?auto=1';
const STUDIO_ORIGIN = process.env.STUDIO_ORIGIN || 'https://avanzacast-studio.bfzqqk.easypanel.host';
log('Navigating to broadcast URL: ' + BROADCAST_URL);
await page.goto(BROADCAST_URL, { waitUntil: 'networkidle', timeout: 30000 });
log('Broadcast page loaded');
// Wait briefly for auto-run, otherwise click the open button if present
try{
// if the page has a button with id 'run' or 'openSend', try to click it as fallback
const runBtn = await page.$('#run') || await page.$('#openSend');
if (runBtn) {
log('Found run/open button on page; clicking to trigger flow');
await runBtn.click();
}
} catch(e){ log('No run button click fallback: ' + e); }
// Wait up to 12s for the redirect to the studio (the broadcast page may open a popup or redirect)
log('Waiting for a new page whose origin matches ' + STUDIO_ORIGIN + ' (timeout 12s)');
let studioPage = null;
const start = Date.now();
const timeoutMs = 12000;
while (!studioPage && (Date.now() - start) < timeoutMs){
const pages = context.pages();
for (const p of pages){
try{
const u = p.url();
if (u && u.startsWith(STUDIO_ORIGIN)) { studioPage = p; break; }
}catch(e){}
}
if (studioPage) break;
await new Promise(r=>setTimeout(r, 300));
}
if (!studioPage){
log('Studio page not opened automatically; attempting to open studio receiver directly at ' + STUDIO_ORIGIN + '/studio_receiver.html');
// open the studio receiver in the same context
studioPage = await context.newPage();
await studioPage.goto(STUDIO_ORIGIN + '/studio_receiver.html', { waitUntil: 'networkidle', timeout: 30000 }).catch(e=>{ log('Goto studio_receiver failed: '+e); });
}
if (!studioPage) {
log('ERROR: Could not open studio page');
} else {
// capture console logs from studio page to detect connected/ACK messages
studioPage.on('console', m => {
try { const txt = m.text(); studioConsoleLogs.push(txt); log('STUDIO PAGE LOG: ' + txt); } catch(e) {}
});
log('Studio page ready at ' + studioPage.url());
try{
// wait for #status element that studio_receiver exposes
// try a slightly longer wait and fallback to scanning page text
try {
await studioPage.waitForSelector('#status', { timeout: 16000 });
} catch (e) {
log('waitForSelector #status timed out, will fallback to scanning page content');
}
const statusText = await studioPage.evaluate(() => {
const el = document.getElementById('status');
if (el) return el.textContent;
return document.body ? document.body.innerText || document.body.textContent : null;
}).catch(()=>null);
log('Studio #status text (initial): ' + statusText);
} catch(e){ log('No #status element or timeout: ' + (e && e.message)); }
// Now wait for the simulator page log (broadcast) to show ACK or for studio to update
try{
// Wait up to 10s for ACK to appear in any page logs (simulator) or studio status
const ackStart = Date.now();
let ackSeen = false;
const ackTimeout = 20000; // increase to 20s
while (!ackSeen && (Date.now() - ackStart) < ackTimeout){
// check studio console logs first
try{
for (const cmsg of studioConsoleLogs){
if (cmsg && (cmsg.toLowerCase().includes('conectado') || cmsg.toLowerCase().includes('connected') || cmsg.toLowerCase().includes('ack'))) {
ackSeen = true; log('ACK/connected found in studio console logs: ' + cmsg); break;
}
}
}catch(e){}
if (ackSeen) break;
// check simulator page (first page) for log element
try{
const simulatorPages = context.pages();
for (const sp of simulatorPages){
try{
const content = await sp.evaluate(()=>{
const el = document.getElementById('log');
if (el && el.textContent) return el.textContent;
return document.body ? (document.body.innerText || document.body.textContent) : null;
});
if (content && (content.includes('ACK') || /connected/i.test(content) || /conectado/i.test(content))) { ackSeen = true; log('ACK/connected found in simulator page content'); break; }
}catch(e){}
}
}catch(e){ }
// also check studio status
try{
const s = await studioPage.evaluate(()=>{
const st = document.getElementById('status');
if (st && st.textContent) return st.textContent;
return document.body ? (document.body.innerText || document.body.textContent) : null;
});
if (s && (s.toLowerCase().includes('ack') || s.toLowerCase().includes('connected') || s.toLowerCase().includes('conectado'))) { ackSeen = true; log('ACK/connected found in studio content: '+s); }
}catch(e){}
if (!ackSeen) await new Promise(r=>setTimeout(r, 300));
}
if (!ackSeen) log('Timeout waiting for ACK ('+ (ackTimeout/1000) +'s)');
} catch(e){ log('Error while waiting for ACK: '+e); }
// take screenshots
const simShot = '/tmp/sim_postmessage_simulator.png';
const studioShot = '/tmp/sim_postmessage_studio.png';
try{ await page.screenshot({ path: simShot, fullPage: true }); log('Saved simulator screenshot: ' + simShot); } catch(e){ log('Failed saving simulator screenshot: ' + e); }
try{ await studioPage.screenshot({ path: studioShot, fullPage: true }); log('Saved studio screenshot: ' + studioShot); } catch(e){ log('Failed saving studio screenshot: ' + e); }
}
} catch (err) {
log('Unhandled error: ' + (err && err.stack ? err.stack : String(err)));
process.exitCode = 2;
} finally {
try { if (browser) await browser.close(); log('Browser closed'); } catch(e) { log('Error closing browser: ' + e); }
}
log('Test finished');
})();