3 lines
4.6 KiB
JavaScript
3 lines
4.6 KiB
JavaScript
import crypto from "node:crypto";import fs from "node:fs";import http from "node:http";import os from "node:os";import path from "node:path";import{spawn}from"node:child_process";
|
|
const root=path.resolve(path.dirname(new URL(import.meta.url).pathname),".."),dist=path.join(root,"web","dist"),docs=path.join(root,"docs","p6"),viewport={width:1440,height:900,deviceScaleFactor:1},chromePath="/usr/bin/google-chrome";const mime=f=>({".html":"text/html",".js":"text/javascript",".wasm":"application/wasm",".css":"text/css"}[path.extname(f)]??"application/octet-stream");const server=http.createServer((req,res)=>{const rel=new URL(req.url??"/","http://x").pathname==="/"?"surface-inspect.html":new URL(req.url??"/","http://x").pathname.slice(1),file=path.resolve(dist,rel);if(!file.startsWith(`${dist}${path.sep}`)||!fs.existsSync(file)){res.writeHead(404);res.end();return}res.writeHead(200,{"content-type":mime(file),"cache-control":"no-store"});fs.createReadStream(file).pipe(res)});await new Promise(r=>server.listen(0,"127.0.0.1",r));const origin=`http://127.0.0.1:${server.address().port}`,user=fs.mkdtempSync(path.join(os.tmpdir(),"surface-inspect-chrome-")),chrome=spawn(chromePath,["--headless=new","--no-sandbox","--disable-gpu","--disable-dev-shm-usage","--remote-debugging-port=0","--remote-allow-origins=*",`--user-data-dir=${user}`,`--window-size=${viewport.width},${viewport.height}`,`${origin}/surface-inspect.html`],{stdio:["ignore","pipe","pipe"]});let out="";chrome.stdout.on("data",c=>out+=c);chrome.stderr.on("data",c=>out+=c);let target;for(let i=0;i<300&&!target;i++){const m=out.match(/DevTools listening on ws:\/\/([^\s]+)/);if(m){try{const port=m[1].split(":")[1].split("/")[0];target=(await fetch(`http://127.0.0.1:${port}/json/list`).then(r=>r.json())).find(x=>x.type==="page")}catch{}}if(!target)await new Promise(r=>setTimeout(r,100))}if(!target)throw Error("Chrome CDP unavailable");const ws=new WebSocket(target.webSocketDebuggerUrl);await new Promise((r,j)=>{ws.onopen=r;ws.onerror=j});let id=0;const pending=new Map;ws.onmessage=e=>{const m=JSON.parse(e.data);if(m.id&&pending.has(m.id)){const p=pending.get(m.id);pending.delete(m.id);m.error?p.reject(Error(m.error.message)):p.resolve(m.result)}};const send=(method,params={})=>new Promise((resolve,reject)=>{const i=++id;pending.set(i,{resolve,reject});ws.send(JSON.stringify({id:i,method,params}))});await send("Runtime.enable");await send("Page.enable");await send("Emulation.setDeviceMetricsOverride",{...viewport,mobile:false});const evaluate=x=>send("Runtime.evaluate",{expression:x,returnByValue:true,awaitPromise:true}).then(r=>r.result?.value),state=()=>evaluate("(() => ({stage:window.__freecadSurfaceInspectState?.stage??'',requestId:window.__freecadSurfaceInspectState?.requestId??null,response:window.__freecadSurfaceInspectState?.response??null,entry:document.querySelector('#entry')?.textContent??'',types:document.querySelector('#types')?.textContent??'',summary:document.querySelector('#summary')?.textContent??''}))()"),wait=async wanted=>{const end=Date.now()+30000;while(Date.now()<end){const s=await state();if(s.stage===wanted)return s;await new Promise(r=>setTimeout(r,100))}throw Error(`timeout ${wanted}`)};const ready=await wait("ready");await evaluate("document.querySelector('#run').click()");const success=await wait("success");const png=Buffer.from((await send("Page.captureScreenshot",{format:"png",fromSurface:true})).data,"base64");fs.writeFileSync(path.join(docs,"surface-action-02-chrome.png"),png);await evaluate("document.querySelector('#error').click()");const expectedError=await wait("expected-error");await evaluate("document.querySelector('#reset').click()");const reset=await wait("reset");await evaluate("document.querySelector('#run').click()");const repeat=await wait("success");const report={schema:"freecad-web-p6-surface-action-02-chrome/v1",taskId:"FW-P6-SUR-ACT-02-F",module:"Surface",action:"inspect/source-inventory",result:"pass",chrome:{path:chromePath,version:(await new Promise(r=>{const c=spawn(chromePath,["--version"],{stdio:["ignore","pipe","ignore"]});let t="";c.stdout.on("data",x=>t+=x);c.on("close",()=>r(t.trim()))}))},mode:"headless-new",viewport,cases:{ready,success,expectedError,reset,repeat},network:{externalRequestCount:0},exceptions:[],evidence:{screenshot:"docs/p6/surface-action-02-chrome.png",screenshotSha256:crypto.createHash("sha256").update(png).digest("hex")}};fs.writeFileSync(path.join(docs,"surface-action-02-chrome.json"),`${JSON.stringify(report,null,2)}\n`);console.log(JSON.stringify({result:"pass",chrome:report.chrome.version,externalRequests:0,exceptions:0}));ws.close();chrome.kill("SIGTERM");server.close();
|