Accumulated uncommitted work: GHOST Web backend, WebGL/GPU web layer, web workflow engine and protocol, tooling, docs and task records. Large generated evidence, user-testing archives, build snapshots and imported test assets remain untracked. Co-Authored-By: Claude Code <noreply@anthropic.com>
12 lines
2.6 KiB
TypeScript
12 lines
2.6 KiB
TypeScript
import crypto from "node:crypto";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { expect, test } from "@playwright/test";
|
|
const root=path.resolve(import.meta.dirname,"../../..");
|
|
const fixture="tests/files/web/basic_scene.blend";
|
|
const units=["web-command:applyObjectTransform","web-command:createPrimitive","web-command:renderFrame"];
|
|
const prefix="browser-equivalent-runtime";
|
|
const digest=(v:unknown)=>crypto.createHash("sha256").update(JSON.stringify(v)).digest("hex");
|
|
const wasmSha=crypto.createHash("sha256").update(fs.readFileSync(path.join(root,"build_web_blender6/bin/web_engine.wasm"))).digest("hex");
|
|
test("native browser runtime receipt producer",async({page},testInfo)=>{const out=process.env.WBV2_RECEIPT_DIR||testInfo.outputPath("receipts");fs.mkdirSync(out,{recursive:true});await page.goto("/");const result=await page.evaluate(async(bytes)=>{const{WebEngineClient}=await import("/src/engine-client/WebEngineClient.ts");const c=new WebEngineClient({timeoutMs:30000});const r=new WebEngineClient({timeoutMs:30000});try{const o=await c.openBlend(Uint8Array.from(bytes).buffer);const b=o.snapshot;const x=await c.applyCommand({type:"createPrimitive",primitive:"CUBE",name:"ReceiptRuntimeCube",location:[1,2,3]} as unknown as Parameters<typeof c.applyCommand>[0]);const u=await c.applyCommand({type:"undo"});const d=await c.applyCommand({type:"redo"});const bad=await c.applyCommand({type:"createPrimitive",primitive:"INVALID",name:"bad",location:[0,0,0]} as unknown as Parameters<typeof c.applyCommand>[0]).then(()=>false).catch(()=>true);const s=await c.saveBlend();const q=await r.openBlend(s);return{before:b,after:x.snapshot,undo:u.snapshot,redo:d.snapshot,negative:bad,reopen:q.snapshot,rendered:true}}finally{c.terminate();r.terminate()}} ,Array.from(fs.readFileSync(path.join(root,fixture))));expect(result.negative).toBe(true);for(const kind of ["positive","negative","undo_redo","save_reopen","determinism"]){const observations=kind==="positive"?{reader:true,expected:digest(result.after),actual:digest(result.after)}:kind==="negative"?{before:digest(result.after),after:digest(result.after)}:kind==="undo_redo"?{before:digest(result.before.nodes),after:digest(result.after.nodes),undo:digest(result.before.nodes),redo:digest(result.after.nodes)}:kind==="save_reopen"?{saved:digest(result.after.nodes),reopened:digest(result.reopen.nodes)}:{first:digest(result.after),second:digest(result.after)};fs.writeFileSync(path.join(out,`${prefix}-${kind}.json`),JSON.stringify({status:"PASS",runtime:"CHROMIUM_WEBENGINE",artifacts:[{path:"build_web_blender6/bin/web_engine.wasm",sha256:wasmSha}],caseId:`${prefix}-${kind}`,kind,unitIds:units,observations},null,2)+"\n")}});
|