#!/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{ 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 };