- 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
123 lines
5.0 KiB
JavaScript
123 lines
5.0 KiB
JavaScript
#!/usr/bin/env node
|
|
// packages/broadcast-panel/e2e/dify-plugin-playwright.mjs
|
|
// Minimal Playwright "plugin" runner inspired by dify-plugin-playwright
|
|
// Usage (CLI):
|
|
// node dify-plugin-playwright.mjs --ws ws://localhost:3003 --url http://localhost:5176 --out /tmp/dify-shot.png
|
|
// Or import and call runPlaywright(options)
|
|
|
|
import { chromium } from 'playwright';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
async function runPlaywright({ wsEndpoint, url, out = '/tmp/dify-playwright-shot.png', steps = [] }){
|
|
const result = { success: false, wsEndpoint, url, out, steps: [], error: null, used: null };
|
|
let browser;
|
|
try{
|
|
// Try to connect to remote Playwright server if wsEndpoint provided
|
|
if(wsEndpoint){
|
|
result.steps.push(`attempt_connect:${wsEndpoint}`);
|
|
try{
|
|
browser = await chromium.connect({ wsEndpoint, timeout: 30000 });
|
|
result.used = 'remote';
|
|
result.steps.push({ action: 'connect', ok: true, meta: { wsEndpoint } });
|
|
}catch(connectErr){
|
|
// Log the error and fallback to launching local browser
|
|
const em = String(connectErr && (connectErr.stack || connectErr.message || connectErr));
|
|
result.steps.push({ action: 'connect', ok: false, meta: { error: em } });
|
|
result.steps.push({ action: 'fallback', ok: true, meta: { reason: 'connect-failed, launching local chromium' } });
|
|
try{
|
|
browser = await chromium.launch({ headless: true });
|
|
result.used = 'local-launch';
|
|
result.steps.push({ action: 'launch', ok: true, meta: { launched: true } });
|
|
}catch(launchErr){
|
|
result.error = 'Failed to connect remote and failed to launch local chromium: ' + String(launchErr && (launchErr.stack || launchErr.message));
|
|
return result;
|
|
}
|
|
}
|
|
} else {
|
|
// No wsEndpoint provided -> launch local
|
|
result.steps.push('no-wsendpoint-launch-local');
|
|
browser = await chromium.launch({ headless: true });
|
|
result.used = 'local-launch';
|
|
result.steps.push({ action: 'launch', ok: true });
|
|
}
|
|
|
|
const context = await browser.newContext();
|
|
const page = await context.newPage();
|
|
|
|
// default flow if no custom steps
|
|
if(!steps || steps.length === 0){
|
|
steps = [
|
|
{ action: 'goto', url },
|
|
{ action: 'wait', ms: 1000 },
|
|
{ action: 'clickText', text: 'Entrar al Estudio' },
|
|
{ action: 'wait', ms: 1000 },
|
|
{ action: 'screenshot', path: out }
|
|
];
|
|
}
|
|
|
|
for(const s of steps){
|
|
const step = { action: s.action || 'unknown', ok: false, meta: null };
|
|
try{
|
|
if(s.action === 'goto'){
|
|
await page.goto(s.url, { waitUntil: 'networkidle', timeout: s.timeout || 30000 });
|
|
step.ok = true; step.meta = { url: page.url() };
|
|
} else if(s.action === 'wait'){
|
|
await page.waitForTimeout(s.ms || 500);
|
|
step.ok = true;
|
|
} else if(s.action === 'clickText'){
|
|
const locator = page.locator(`text=${s.text}`);
|
|
const c = await locator.count();
|
|
if(c > 0){ await locator.first().click({ timeout: 5000 }); step.ok = true; } else { step.ok = false; step.meta = { found: 0 }; }
|
|
} else if(s.action === 'type'){
|
|
await page.locator(s.selector).fill(s.text); step.ok = true;
|
|
} else if(s.action === 'screenshot'){
|
|
const p = s.path || out;
|
|
await page.screenshot({ path: p, fullPage: true }); step.ok = true; step.meta = { path: p };
|
|
} else if(s.action === 'eval'){
|
|
const r = await page.evaluate(s.fn);
|
|
step.ok = true; step.meta = { result: r };
|
|
} else {
|
|
// unknown
|
|
step.ok = false; step.meta = { reason: 'unknown action' };
|
|
}
|
|
}catch(err){
|
|
step.ok = false; step.meta = { error: String(err && (err.stack || err.message || err)) };
|
|
}
|
|
result.steps.push(step);
|
|
}
|
|
|
|
result.success = result.steps.every(st => typeof st === 'object' ? st.ok || st.action==='connect' : true);
|
|
|
|
await context.close();
|
|
try{ await browser.close(); }catch(e){}
|
|
return result;
|
|
}catch(err){
|
|
if(browser){ try{ await browser.close(); }catch(e){} }
|
|
result.error = String(err && (err.stack || err.message || err));
|
|
return result;
|
|
}
|
|
}
|
|
|
|
// CLI runner
|
|
if(process.argv[1] && process.argv[1].endsWith('dify-plugin-playwright.mjs')){
|
|
// parse args simply
|
|
const args = process.argv.slice(2);
|
|
const opts = {};
|
|
for(let i=0;i<args.length;i++){
|
|
if(args[i] === '--ws') opts.wsEndpoint = args[++i];
|
|
if(args[i] === '--url') opts.url = args[++i];
|
|
if(args[i] === '--out') opts.out = args[++i];
|
|
}
|
|
if(!opts.url) opts.url = process.env.BROADCAST_URL || 'http://localhost:5176';
|
|
if(!opts.wsEndpoint) opts.wsEndpoint = process.env.PW_WS || 'ws://localhost:3003';
|
|
(async ()=>{
|
|
const res = await runPlaywright({ wsEndpoint: opts.wsEndpoint, url: opts.url, out: opts.out });
|
|
console.log(JSON.stringify(res, null, 2));
|
|
if(!res.success) process.exit(2);
|
|
process.exit(0);
|
|
})();
|
|
}
|
|
|
|
export { runPlaywright };
|