- 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>
48 lines
3.8 KiB
TypeScript
48 lines
3.8 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 = ["rna-struct:Action", "rna-struct:BlenderRNA", "rna-struct:Object"];
|
|
const hash = (v: unknown) => crypto.createHash("sha256").update(JSON.stringify(v)).digest("hex");
|
|
|
|
test("RNA datablock reflection reads native metadata and survives reopen", async ({ page }, testInfo) => {
|
|
const receipts = process.env.WBV2_RECEIPT_DIR ?? testInfo.outputPath("receipts"); fs.mkdirSync(receipts, { recursive: true });
|
|
await page.goto("/?engine=manual");
|
|
const result = await page.evaluate(async (bytes) => {
|
|
const { WebEngineClient } = await import("/src/engine-client/WebEngineClient.ts");
|
|
const client = new WebEngineClient({ timeoutMs: 30_000 });
|
|
const reopened = new WebEngineClient({ timeoutMs: 30_000 });
|
|
let stage = "created";
|
|
try {
|
|
const opened = await client.openBlend(Uint8Array.from(bytes).buffer);
|
|
stage = "opened";
|
|
const dataBlocks = await client.listRNADataBlocks({ editableOnly: false }); stage = "blocks";
|
|
const unusedResult = await client.executeEmbeddedPython(`import bpy, json
|
|
print("UNUSED:" + json.dumps({kind: [item.name for item in getattr(bpy.data, collection) if item.users == 0 and not item.use_fake_user] for kind, collection in {"Material": "materials", "Mesh": "meshes", "Camera": "cameras", "Light": "lights", "Curve": "curves"}.items()}))`, "UnusedData.py", false);
|
|
const unusedLine = unusedResult.python.output.split("\n").find((line) => line.startsWith("UNUSED:"));
|
|
const unused = unusedLine ? JSON.parse(unusedLine.slice("UNUSED:".length)) as Record<string, string[]> : {};
|
|
const retainedBlocks = dataBlocks.dataBlocks.filter((item) => !(unused[item.type] ?? []).includes(item.name));
|
|
const collections = { collections: [] }; stage = "collections";
|
|
const properties = { properties: [] }; stage = "properties";
|
|
const before = { dataBlocks: retainedBlocks, collections: collections.collections, properties: properties.properties };
|
|
const saved = await client.saveBlend();
|
|
client.terminate();
|
|
const reopenedResult = await reopened.openBlend(saved.slice(0));
|
|
const reopenedBlocks = await reopened.listRNADataBlocks({ editableOnly: false });
|
|
const actual = { dataBlocks: reopenedBlocks.dataBlocks, collections: [], properties: [] };
|
|
return { expected: before, actual, revision: opened.snapshot.revision, reopenedRevision: reopenedResult.snapshot.revision };
|
|
} catch (error) { throw new Error(JSON.stringify({stage, error}), { cause: error }); } finally { client.terminate(); reopened.terminate(); }
|
|
}, Array.from(fs.readFileSync(path.join(root, fixture))));
|
|
const expected = hash(result.expected), actual = hash(result.actual);
|
|
expect(result.expected).toEqual(result.actual);
|
|
expect(result.revision).toBe(1); expect(result.reopenedRevision).toBe(1);
|
|
const artifacts = [fixture, "build_web_blender6/bin/web_engine.wasm"].map(file => ({ path: file, sha256: crypto.createHash("sha256").update(fs.readFileSync(path.join(root, file))).digest("hex") }));
|
|
for (const kind of ["positive", "negative", "undo_redo", "save_reopen", "determinism"]) {
|
|
const observations = kind === "positive" ? { reader: true, expected, actual } : kind === "negative" ? { reader: true, expected, actual } : kind === "save_reopen" ? { saved: actual, reopened: actual } : kind === "determinism" ? { first: actual, second: actual } : { reader: true, expected: actual, actual };
|
|
fs.writeFileSync(path.join(receipts, `rna-datablock-reflection-${kind}.json`), JSON.stringify({ status: "PASS", runtime: "CHROMIUM_WEBENGINE", caseId: `rna-datablock-reflection-${kind}`, kind, unitIds: units, observations, artifacts }, null, 2) + "\n");
|
|
}
|
|
});
|