81 lines
6.5 KiB
JavaScript
81 lines
6.5 KiB
JavaScript
/* Verify every theme switch updates group card colors in the UI (no reload). */
|
|
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 = 9357;
|
|
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,150));}
|
|
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[1],"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});
|
|
await send("Page.navigate",{url:"http://localhost:3210/"});
|
|
await new Promise(r=>setTimeout(r,5000));
|
|
// wait until group cards (divs with inline borderColor+backgroundColor) have rendered
|
|
const cardQ=`Array.from(document.querySelectorAll("div")).some(d=>{const st=d.getAttribute("style")||"";return /background-color/.test(st)&&/border-color/.test(st)})`;
|
|
for(let i=0;i<30;i++){ if(await send("Runtime.evaluate",{expression:cardQ,returnByValue:true}).then(r=>r.result?.value)){ break; } await new Promise(r=>setTimeout(r,1000)); }
|
|
await new Promise(r=>setTimeout(r,500));
|
|
|
|
const ev=(expr)=>send("Runtime.evaluate",{expression:expr,returnByValue:true,awaitPromise:true}).then(r=>r.result?.value ?? r.exceptionDetails?.exception?.description);
|
|
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});};
|
|
// Option button scoped to the open dropdown (avoids the "Default" *project* nav item)
|
|
const optionAt=async(name)=>{const v=await ev(`(()=>{
|
|
const menu=document.querySelector('[data-slot="dropdown-menu-content"]');
|
|
if(!menu) return null;
|
|
const b=Array.from(menu.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;};
|
|
const openMenu=async()=>{const v=await ev(`(()=>{const b=Array.from(document.querySelectorAll("button")).find(x=>(x.textContent||"").trim()==="Theme");if(!b)return null;const r=b.getBoundingClientRect();return JSON.stringify({x:Math.round(r.x+r.width/2),y:Math.round(r.y+r.height/2)})})()`);if(!v)return false;const p=JSON.parse(v);await click(p.x,p.y);await new Promise(r=>setTimeout(r,500));return true;};
|
|
const state=async(label)=>{const out=JSON.stringify(await ev(`(()=>{
|
|
const cards=Array.from(document.querySelectorAll("[class*=rounded-2xl]")).filter(c=>/background-color/.test(c.getAttribute("style")||"")&&/border-color/.test(c.getAttribute("style")||""));
|
|
const card=cards[0]||{getAttribute:()=>""};
|
|
const s=card.getAttribute("style")||"";
|
|
return {
|
|
html:document.documentElement.className.split(" ").filter(Boolean).slice(-1).join(","),
|
|
cards:cards.length,
|
|
cardBg:(s.match(/background-color:([^;]+)/)||[])[1],
|
|
cardBorder:(s.match(/border-color:([^;]+)/)||[])[1],
|
|
bodyBg:getComputedStyle(document.body).backgroundColor
|
|
};
|
|
})()`));console.log(label,out);return out;};
|
|
|
|
const pickCard=await ev(`Array.from(document.querySelectorAll("div")).filter(d=>{const st=d.getAttribute("style")||"";return /background-color/.test(st)&&/border-color/.test(st)}).length`);
|
|
console.log(" cards-with-style:", pickCard);
|
|
let s1 = await state("1) initial (dark) ");
|
|
await openMenu(); let o = await optionAt("Default"); console.log(" -> clicking Default at", JSON.stringify(o));
|
|
if(o){await click(o.x,o.y);} await new Promise(r=>setTimeout(r,900));
|
|
let s2 = await state("2) after Default ");
|
|
await openMenu(); o = await optionAt("Sunset"); console.log(" -> clicking Sunset at", JSON.stringify(o));
|
|
if(o){await click(o.x,o.y);} await new Promise(r=>setTimeout(r,900));
|
|
let s3 = await state("3) after Sunset ");
|
|
await openMenu(); o = await optionAt("Ocean"); console.log(" -> clicking Ocean at", JSON.stringify(o));
|
|
if(o){await click(o.x,o.y);} await new Promise(r=>setTimeout(r,900));
|
|
let s4 = await state("4) after Ocean ");
|
|
await openMenu(); o = await optionAt("Dark"); console.log(" -> clicking Dark at", JSON.stringify(o));
|
|
if(o){await click(o.x,o.y);} await new Promise(r=>setTimeout(r,900));
|
|
let s5 = await state("5) back to Dark ");
|
|
|
|
const parse=(s)=>JSON.parse(s.slice(s.indexOf("{")));
|
|
const ok1 = parse(s2).cardBorder !== parse(s1).cardBorder || parse(s2).html !== parse(s1).html;
|
|
const ok2 = parse(s3).cardBg !== parse(s2).cardBg;
|
|
const ok3 = parse(s4).cardBg !== parse(s3).cardBg;
|
|
const ok4 = parse(s5).cardBg !== parse(s4).cardBg;
|
|
console.log("TRANSITIONS OK:", ok1, ok2, ok3, ok4, "| ALL:", ok1&&ok2&&ok3&&ok4);
|
|
const real=errs.filter(e=>!/favicon|manifest|icon|404/i.test(e));
|
|
console.log("CONSOLE ERRORS:", real.length); real.slice(0,5).forEach(e=>console.log(" -",e));
|
|
proc.kill();process.exit(0);
|
|
})().catch(e=>{console.error("FAIL",e.message);process.exit(1)});
|