/* Verify computed styles for a given theme class after runtime swap. */ const { spawn } = require("node:child_process"); const fs = require("node:fs"); const http = require("node:http"); const EDGE = "C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe"; const PORT = 9337; function httpJson(path) { return new Promise((resolve, reject) => { const req = http.request({ host: "127.0.0.1", port: PORT, path }, (res) => { let d = ""; res.on("data", (c) => (d += c)); res.on("end", () => { try { resolve(JSON.parse(d)); } catch { resolve(d); } }); }); req.on("error", reject); req.end(); }); } (async () => { const profile = fs.mkdtempSync("/tmp/edge-prof-"); const proc = spawn(EDGE, ["--headless=new", `--remote-debugging-port=${PORT}`, `--user-data-dir=${profile}`, "--no-first-run", "--no-default-browser-check", "--disable-gpu", "about:blank"], { stdio: "ignore" }); let targets = null; for (let i = 0; i < 40; i++) { await new Promise((r) => setTimeout(r, 500)); try { targets = await httpJson("/json/list"); break; } catch {} } if (!targets) { console.error("no targets"); process.exit(1); } const page = targets.find((t) => t.type === "page"); const ws = new WebSocket(page.webSocketDebuggerUrl); await new Promise((r) => (ws.onopen = r)); let id = 0; const send = (method, params = {}) => new Promise((resolve) => { const myId = ++id; ws.send(JSON.stringify({ id: myId, method, params })); const t = setInterval(() => { const m = ws._buf.find((b) => b.id === myId); if (m) { clearInterval(t); resolve(m.result ?? m.error); } }, 10); }); ws._buf = []; ws.onmessage = (m) => { const msg = JSON.parse(m.data); if (msg.id) { ws._buf.push(msg); return; } if (msg.method === "Runtime.consoleAPICalled") console.log("[c]", msg.params.args.map((a) => a.value ?? a.description ?? a.type).join(" ").slice(0, 160)); }; await send("Runtime.enable"); await send("Network.enable"); const cookieFile = process.argv[2]; if (cookieFile) { const line = fs.readFileSync(cookieFile, "utf8").split("\n").map((l) => l.trim()).find((l) => l.includes("authjs.session-token")); if (line) await send("Network.setCookies", { cookies: [{ name: "authjs.session-token", value: line.split("\t").pop(), domain: "localhost", path: "/", httpOnly: true, sameSite: "Lax" }] }); } await send("Page.enable"); await send("Page.navigate", { url: "http://localhost:3210/" }); await new Promise((r) => setTimeout(r, 4000)); const theme = process.argv[3] || "dark"; await send("Runtime.evaluate", { expression: `document.documentElement.className = ${JSON.stringify(theme)}` }); await new Promise((r) => setTimeout(r, 1500)); const info = await send("Runtime.evaluate", { expression: `(() => { const card = document.querySelector('[aria-label^="Drag to move"]')?.closest('[class*="rounded-2xl"]'); const checkbox = card ? card.querySelector('button[class*="size-4"]') : null; return JSON.stringify({ htmlClass: document.documentElement.className.split(" ").slice(-1)[0], checkboxBorder: checkbox ? getComputedStyle(checkbox).borderColor : null, cardBg: card ? getComputedStyle(card).backgroundColor : null, }); })()`, returnByValue: true }); console.log(info?.result?.value); proc.kill(); process.exit(0); })().catch((e) => { console.error(e.message); process.exit(1); });