Organize/.cdp/debug-menu.cjs

54 lines
4.6 KiB
JavaScript

/* Debug: step through the theme menu with full state dumps between clicks. */
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 = 9356;
function httpJson(p){return new Promise((res,rej)=>{const r=http.request({host:"127.0.0.1",port:PORT,path:p},(x)=>{let d="";x.on("data",c=>d+=c);x.on("end",()=>{try{res(JSON.parse(d))}catch{res(d)}})});r.on("error",rej);r.end()})}
(async()=>{
const prof=fs.mkdtempSync(require("node:os").tmpdir()+"/edge-prof-");
const proc=spawn(EDGE,["--headless=new","--remote-debugging-port="+PORT,"--user-data-dir="+prof,"--no-first-run","--no-default-browser-check","--disable-gpu","about:blank"],{stdio:"ignore"});
let tg=null;for(let i=0;i<40;i++){await new Promise(r=>setTimeout(r,500));try{tg=await httpJson("/json/list");break}catch{}}
const page=tg.find(t=>t.type==="page");
const ws=new WebSocket(page.webSocketDebuggerUrl);
await new Promise(r=>ws.onopen=r);let id=0;
const send=(m,p={})=>new Promise(res=>{const i2=++id;ws.send(JSON.stringify({id:i2,method:m,params:p}));const t=setInterval(()=>{const f=ws._buf.find(b=>b.id===i2);if(f){clearInterval(t);res(f.result??f.error)}},10)});
ws._buf=[];const errs=[];
ws.onmessage=(m)=>{const j=JSON.parse(m.data);if(j.id){ws._buf.push(j);return;}
if(j.method==="Runtime.consoleAPICalled"&&j.params.type==="error"){errs.push(j.params.args.map(a=>(a.value??a.description??"")).join(" ").slice(0,160));}
if(j.method==="Runtime.exceptionThrown"){errs.push("EXC: "+(j.params.exceptionDetails?.exception?.description||"").slice(0,120));}};
await send("Runtime.enable");await send("Page.enable");await send("Network.enable");
const cv=fs.readFileSync(process.argv[2],"utf8").split("\n").map(l=>l.trim()).find(l=>l.includes("authjs.session-token")).split("\t").pop();
await send("Network.setCookies",{cookies:[{name:"authjs.session-token",value:cv,domain:"localhost",path:"/",httpOnly:true,sameSite:"Lax"}]});
await send("Emulation.setDeviceMetricsOverride",{width:1440,height:900,deviceScaleFactor:1});
const ev=(expr)=>send("Runtime.evaluate",{expression:expr,returnByValue:true,awaitPromise:true}).then(r=>r.result?.value ?? r.exceptionDetails?.exception?.description);
const dump=async(label)=>console.log(label, JSON.stringify(await ev(`(()=>{
const btns=Array.from(document.querySelectorAll("button")).map(b=>(b.textContent||"").trim()).filter(t=>["Theme","Default","Sunset","Dark","Ocean","Match system"].includes(t));
return {html:document.documentElement.className.split(" ").filter(Boolean).slice(-1).join(","), ls:localStorage.getItem("theme"), btns, menuOpen:!!document.querySelector('[data-slot="dropdown-menu-content"]')};
})()`)));
const click=async(x,y)=>{await send("Input.dispatchMouseEvent",{type:"mousePressed",x,y,button:"left",clickCount:1});await send("Input.dispatchMouseEvent",{type:"mouseReleased",x,y,button:"left",clickCount:1});};
const center=async(name)=>{const v=await ev(`(()=>{const b=Array.from(document.querySelectorAll("button")).find(x=>(x.textContent||"").trim()==="${name}");if(!b)return null;const r=b.getBoundingClientRect();return JSON.stringify({x:Math.round(r.x+12),y:Math.round(r.y+r.height/2)})})()`);return v?JSON.parse(v):null;};
await send("Page.navigate",{url:"http://localhost:3210/"});
await new Promise(r=>setTimeout(r,9000));
console.log("PAGE", JSON.stringify(await ev("JSON.stringify({title:document.title,bodyLen:document.body.innerText.length,btnCount:document.querySelectorAll('button').length})")));
await dump("S0 initial ");
let p=await center("Theme"); if(!p){console.log("no Theme btn");proc.kill();process.exit(1);}
await click(p.x,p.y); await new Promise(r=>setTimeout(r,600));
await dump("S1 after open ");
p=await center("Default"); console.log(" default btn at", JSON.stringify(p));
await click(p.x,p.y); await new Promise(r=>setTimeout(r,900));
await dump("S2 after Default");
p=await center("Theme"); if(!p){console.log("no Theme btn #2");proc.kill();process.exit(1);}
await click(p.x,p.y); await new Promise(r=>setTimeout(r,600));
await dump("S3 after open2 ");
p=await center("Ocean"); console.log(" ocean btn at", JSON.stringify(p));
await click(p.x,p.y); await new Promise(r=>setTimeout(r,900));
await dump("S4 after Ocean ");
const real=errs.filter(e=>!/favicon|manifest|icon|404/i.test(e));
console.log("ERRORS:", real.length); real.slice(0,6).forEach(e=>console.log(" -",e));
proc.kill();process.exit(0);
})().catch(e=>{console.error("FAIL",e.message);process.exit(1)});