Files
workinf_Blender_Wasm/web/tests/e2e/wbv2-convert-to-mesh-production.spec.ts
mes123456 d1e6b63d54
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: checkpoint web Blender feature-gap work, docs and tests
- update native web_engine sources and rebuilt wasm artifacts
- add task cards, status notes and tooling scripts
- add web e2e specs, tutorial UI sources and tutorial assets
- sync golden task manifests and audit records

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-11-11 10:46:55 +08:00

53 lines
3.8 KiB
TypeScript

import { test, expect } from "@playwright/test";
import fs from "node:fs";
import path from "node:path";
const root = path.resolve(import.meta.dirname, "../../..");
const fixture = fs.readFileSync(path.join(root, "tests/files/web/basic_scene.blend"));
const cases = [
{ operator: "curve.primitive_bezier_curve_add", properties: {}, expected: "CURVE" },
{ operator: "surface.primitive_nurbs_surface_surface_add", properties: {}, expected: "SURFACE" },
{ operator: "object.text_add", properties: {}, expected: "FONT" },
];
test("curve, surface and text objects convert to meshes", async ({ page }) => {
test.setTimeout(180_000);
await page.goto("/?engine=manual");
const results = await page.evaluate(async ({ bytes, cases }) => {
const { WebEngineClient } = await import("/src/engine-client/WebEngineClient.ts");
const out: Record<string, unknown>[] = [];
for (const item of cases) {
const client = new WebEngineClient({ timeoutMs: 30_000 });
try {
const open = await client.openBlend(Uint8Array.from(bytes).buffer);
const mesh = open.snapshot.nodes.find((n) => n.type === "MESH");
let revision = open.snapshot.revision;
const invoke = async (operator: string, properties: Record<string, unknown>, activeName: string, selected: string[]) => {
const payload = JSON.stringify({ operator, properties, baseRevision: revision, sceneName: open.snapshot.scenes?.[0]?.name ?? "Scene", areaType: "VIEW_3D", mode: "OBJECT", native: true, selectedObjects: selected, activeObject: activeName, meshSelection: null, nonMeshSelection: null });
const source = `import json, web_blender\nweb_blender.desktop_operator(json.loads(${JSON.stringify(payload)}))`;
const res = await client.executeEmbeddedPython(source, "Convert.py", false);
revision = res.snapshot.revision;
if (res.python.state !== "DONE") throw new Error(res.python.error ?? res.python.output ?? res.python.state);
return res.snapshot;
};
const created = await invoke(item.operator, item.properties, mesh?.name ?? "", mesh ? [mesh.name] : []);
const createdNode = created.nodes.find((n) => !open.snapshot.nodes.some((old) => old.id === n.id));
if (!createdNode) throw new Error("source object was not created");
const converted = await invoke("object.convert", { target: "MESH" }, createdNode.name, [createdNode.name]);
const convertedNode = converted.nodes.find((n) => n.id === createdNode.id || n.name === createdNode.name);
const convertedMesh = convertedNode?.dataId ? converted.meshes.find((m) => m.id === convertedNode.dataId) : undefined;
out.push({ ...item, status: "FINISHED", created: { name: createdNode.name, type: createdNode.type }, converted: { name: convertedNode?.name, type: convertedNode?.type, dataId: convertedNode?.dataId }, mesh: convertedMesh ? { name: convertedMesh.name, vertices: convertedMesh.vertexCount, faces: convertedMesh.faceCount } : null });
} catch (error) {
const e = error as { message?: string; code?: string };
out.push({ ...item, status: "ERROR", message: e?.message, code: e?.code });
} finally { client.terminate(); await new Promise((resolve) => setTimeout(resolve, 120)); }
}
return out;
}, { bytes: Array.from(fixture), cases });
fs.writeFileSync(path.join(root, "tests/golden/WBV2-P1425-001/verification/convert-to-mesh-production.json"), JSON.stringify({ schemaVersion: 1, browser: "chromium", scope: "CURVE/SURFACE/FONT -> OBJECT_OT_convert(target=MESH)", results }, null, 2));
expect(results.filter((item) => item.status !== "FINISHED")).toEqual([]);
for (const item of results) {
expect(item.created.type).toBe(item.expected);
expect(item.converted.type).toBe("MESH");
expect(item.mesh?.vertices).toBeGreaterThan(0);
}
});