Files
workinf_Blender_Wasm/web/tests/e2e/geometry-node-main-reader.spec.ts
mes123456 72503b2969
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
chore(web): continuous handoff WBV2-P1187-001
2026-09-04 07:54:43 +08:00

84 lines
3.7 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 fixturePath = process.env.WBV2_BATCH_FIXTURE ?? "tests/files/web/modifier_geometry_nodes_scene.blend";
const geometryNodesBlend = path.resolve(import.meta.dirname, "../../../", fixturePath);
const task = process.env.WBV2_BATCH_TASK ?? "WBV2-P1125-000";
const sourceUnits = JSON.parse(process.env.WBV2_BATCH_UNITS ?? "[]") as string[];
const expectedTypes = JSON.parse(process.env.WBV2_BATCH_TYPES ?? "[]") as string[];
const productionPath = process.env.WBV2_BATCH_PRODUCTION ?? `tests/golden/${task}/geometry-node-reader-production.json`;
test("M10-01 production Worker preserves Main Geometry Node topology across save and reopen", async ({ page }) => {
test.setTimeout(120_000);
await page.goto("/");
const blendBytes = fs.readFileSync(geometryNodesBlend);
const result = await page.evaluate(async ({ blendBytes }) => {
const { WebEngineClient } = await import("/src/engine-client/WebEngineClient.ts");
const source = blendBytes.buffer.slice(
blendBytes.byteOffset,
blendBytes.byteOffset + blendBytes.byteLength,
) as ArrayBuffer;
const first = new WebEngineClient({ timeoutMs: 60_000 });
await first.init();
const opened = await first.openBlend(source);
const initial = opened.snapshot.geometryNodeGraphs ?? [];
const saved = await first.saveBlend();
first.terminate();
const second = new WebEngineClient({ timeoutMs: 60_000 });
await second.init();
const reopened = await second.openBlend(saved);
const restored = reopened.snapshot.geometryNodeGraphs ?? [];
second.terminate();
return {
graphNames: initial.map((graph) => graph.name),
nodeTypes: initial.flatMap((graph) => graph.nodes.map((node) => node.type)),
nodeCount: initial.reduce((count, graph) => count + graph.nodes.length, 0),
linkCount: initial.reduce((count, graph) => count + graph.links.length, 0),
defaultCount: initial.reduce((count, graph) => count + graph.nodes.reduce(
(nodeCount, node) => nodeCount + node.sockets.filter((socket) => socket.defaultValue !== undefined).length,
0,
), 0),
unsupportedPreserved: initial.some((graph) => graph.nodes.some((node) => node.type === "GeometryNodeSimulationOutput")),
stable: JSON.stringify(initial) === JSON.stringify(restored),
hashes: initial.map((graph) => graph.graphHash),
};
}, { blendBytes: new Uint8Array(blendBytes) });
fs.mkdirSync(path.dirname(path.join(root, productionPath)), { recursive: true });
fs.writeFileSync(path.join(root, productionPath), `${JSON.stringify({
schemaVersion: 1,
task,
operation: "GEOMETRY_NODE_MAIN_READER_CHROMIUM",
browser: "chromium",
queueMutation: false,
fixture: fixturePath,
fixtureSha256: crypto.createHash("sha256").update(blendBytes).digest("hex"),
sourceUnits,
expectedTypes,
...result,
}, null, 2)}\n`);
if (sourceUnits.length > 0) {
expect(result.nodeTypes).toEqual(expect.arrayContaining(expectedTypes));
expect(result.stable).toBe(true);
expect(result.hashes.every((hash) => /^[0-9a-f]{64}$/.test(hash ?? ""))).toBe(true);
} else {
expect(result).toEqual({
graphNames: ["WebGeometryNodes", "WebGeometryNodesSetPosition", "WebGeometryNodesSimulation"],
nodeTypes: expect.any(Array),
nodeCount: 10,
linkCount: 7,
defaultCount: 9,
unsupportedPreserved: true,
stable: true,
hashes: result.hashes,
});
expect(result.hashes).toHaveLength(3);
expect(result.hashes.every((hash) => /^[0-9a-f]{64}$/.test(hash ?? ""))).toBe(true);
}
});