import { chromium } from "playwright"; const b = await chromium.launch({ headless: true }); const ctx = await b.newContext({ viewport: { width: 1440, height: 900 } }); const p = await ctx.newPage(); const calls = []; p.on("response", async (r) => { const u = r.url(); if (u.includes("/api/")) { calls.push({ status: r.status(), method: r.request().method(), url: u.replace("https://canvas.flow-master.ai", "") }); } }); p.on("console", (m) => { if (m.type() === "error") console.log("CONSOLE-ERR:", m.text().slice(0, 200)); }); p.on("pageerror", (e) => console.log("PAGE-ERR:", e.message.slice(0, 200))); await ctx.addInitScript(() => localStorage.setItem("fm.canvas.tour.seen", String(Date.now()))); await p.goto("https://canvas.flow-master.ai/", { waitUntil: "domcontentloaded" }); await p.waitForTimeout(2500); await p.locator(".persona-chip").filter({ hasText: /Mariana/ }).click(); // Live auth can take 6-10s; wait for shell to flip await p.waitForFunction(() => !document.querySelector("[class*='shell-login']"), null, { timeout: 30000 }).catch(() => {}); await p.waitForTimeout(3000); const state = await p.evaluate(() => { const shell = document.querySelector("[class*='shell-']")?.className; const topbar = document.querySelector("header.topbar"); const tabs = Array.from(document.querySelectorAll(".tab")).map(t => t.textContent?.trim()); const headerByTag = document.querySelector("header")?.outerHTML?.slice(0, 200); return { shell, hasTopbar: !!topbar, headerByTag, tabCount: tabs.length, tabs, sceneText: document.querySelector(".scene")?.innerText?.slice(0, 300) || null, }; }); console.log(JSON.stringify(state, null, 2)); await p.screenshot({ path: "/tmp/canvas-evidence/measure.png", fullPage: false }); console.log("screenshot /tmp/canvas-evidence/measure.png"); console.log("\n=== api calls ==="); for (const c of calls) console.log(` ${c.status} ${c.method} ${c.url.slice(0, 100)}`); await b.close();