Files
workinf_Blender_Wasm/web/tests/e2e/compositor-unsupported-gate.spec.ts
mes123456 0fe8d2bb56
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
Advance M8-M11 parity workflows
2026-08-17 04:37:07 -04:00

64 lines
3.3 KiB
TypeScript

import { expect, test } from "@playwright/test";
import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
const root = path.resolve(import.meta.dirname, "../../..");
const golden = JSON.parse(fs.readFileSync(path.join(root, "tests/golden/M11-08/compositor-unsupported-gate.json"), "utf8")) as {
fixture: { path: string; sha256: string };
scene: string;
unsupportedNode: { name: string; type: string; blenderType: string };
expectedErrorCode: string;
expectedRevisionDelta: number;
};
const fixture = fs.readFileSync(path.join(root, golden.fixture.path));
test("M11-08 keeps the Blender graph intact while blocking unsupported compositor execution", async ({ page }) => {
expect(crypto.createHash("sha256").update(fixture).digest("hex")).toBe(golden.fixture.sha256);
await page.goto("/");
const result = await page.evaluate(async (input) => {
const [{ WebEngineClient }, compositor] = await Promise.all([
import("/src/engine-client/WebEngineClient.ts"),
import("/src/compositor/CompositorExecutor.ts"),
]);
const client = new WebEngineClient({ timeoutMs: 30_000 });
await client.init();
const opened = await client.openBlend(input.bytes.buffer);
const scene = opened.snapshot.scenes.find((candidate) => candidate.name === input.scene);
if (!scene?.compositorGraph) throw new Error(`Missing compositor graph ${input.scene}`);
const beforeGraph = JSON.stringify(scene.compositorGraph);
const beforeRevision = opened.snapshot.revision;
const unsupported = scene.compositorGraph.nodes.find((node) => node.type === input.unsupportedNode.type);
let gateCode = "";
let executeCode = "";
let cachedCode = "";
try { gateCode = compositor.gateCompositorGraph(scene.compositorGraph, new Set()).issues[0]?.code ?? ""; } catch (error) { gateCode = String(error); }
try { compositor.executeCompositorGraph(scene.compositorGraph, new Map(), { width: 2, height: 2 }); }
catch (error) { executeCode = error instanceof compositor.CompositorValidationError ? error.code : String(error); }
try {
await compositor.executeCompositorGraphCached(scene.compositorGraph, new Map(), new compositor.CompositorFrameCache(512), { frame: 1, width: 2, height: 2 });
}
catch (error) { cachedCode = error instanceof compositor.CompositorValidationError ? error.code : String(error); }
const after = await client.snapshot();
client.terminate();
const afterScene = after.snapshot.scenes.find((candidate) => candidate.name === input.scene);
return {
beforeGraph,
afterGraph: JSON.stringify(afterScene?.compositorGraph),
beforeRevision,
afterRevision: after.snapshot.revision,
gateCode,
executeCode,
cachedCode,
unsupported: unsupported && { name: unsupported.name, type: unsupported.type, blenderType: unsupported.blenderType },
};
}, { bytes: new Uint8Array(fixture), scene: golden.scene, unsupportedNode: golden.unsupportedNode });
expect(result.gateCode).toBe(golden.expectedErrorCode);
expect(result.executeCode).toBe(golden.expectedErrorCode);
expect(result.cachedCode).toBe(golden.expectedErrorCode);
expect(result.unsupported).toEqual(golden.unsupportedNode);
expect(result.afterGraph).toBe(result.beforeGraph);
expect(result.afterRevision - result.beforeRevision).toBe(golden.expectedRevisionDelta);
});