// Headless-browser probe: logs in and captures the REAL client-side error on /dashboard. // Run via the official Playwright Docker image (no local Node needed): // docker run --rm --network host -v "$PWD/scripts/debug:/work" -w /work \ // mcr.microsoft.com/playwright:v1.49.0-jammy \ // sh -c "npm i playwright@1.49.0 -s && node dashboard-probe.mjs" // // Captures: console messages, page errors (un-minified via sourcemaps if present), // failed requests, and a screenshot. import { chromium } from "playwright" const BASE = process.env.BASE_URL || "http://192.168.188.119:3000" const EMAIL = process.env.LOGIN_EMAIL || "admin@test.de" const PASSWORD = process.env.LOGIN_PASSWORD || "test123" const browser = await chromium.launch() const ctx = await browser.newContext({ ignoreHTTPSErrors: true }) const page = await ctx.newPage() const log = [] page.on("console", (m) => log.push(`[console.${m.type()}] ${m.text()}`)) page.on("pageerror", (e) => log.push(`[pageerror] ${e.stack || e.message}`)) page.on("requestfailed", (r) => log.push(`[requestfailed] ${r.method()} ${r.url()} — ${r.failure()?.errorText}`) ) page.on("response", (r) => { if (r.status() >= 400) log.push(`[http ${r.status()}] ${r.url()}`) }) try { console.log(`==> GET ${BASE}/login`) await page.goto(`${BASE}/login`, { waitUntil: "networkidle", timeout: 20000 }) await page.fill('input[type="email"], input[name="email"], #email', EMAIL) await page.fill('input[type="password"], input[name="password"], #password', PASSWORD) await page.click('button[type="submit"]') // Wait for navigation to settle on the dashboard (or wherever it lands) await page.waitForTimeout(5000) console.log(`==> landed on: ${page.url()}`) // Force-navigate to dashboard to reproduce the crash deterministically await page.goto(`${BASE}/dashboard`, { waitUntil: "networkidle", timeout: 20000 }) await page.waitForTimeout(3000) await page.screenshot({ path: "dashboard-probe.png", fullPage: true }) console.log("==> screenshot saved: dashboard-probe.png") } catch (e) { console.log(`[probe-error] ${e.message}`) } finally { console.log("\n===== CAPTURED BROWSER EVENTS =====") console.log(log.join("\n") || "(none)") await browser.close() }