Files
workinf_Blender_Wasm/web/tests/e2e/nla-operator.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

101 lines
4.3 KiB
TypeScript

import { expect, test } from "@playwright/test";
import fs from "node:fs";
import path from "node:path";
const fixture = fs.readFileSync(path.resolve(
import.meta.dirname,
"../../../tests/files/web/nla_time_mapping_scene.blend",
));
test("M10-12 moves one NLA strip through Main, undo, redo and save/reopen", async ({ page }) => {
test.setTimeout(120_000);
await page.goto("/");
const result = await page.evaluate(async ({ bytes }) => {
const { WebEngineClient } = await import("/src/engine-client/WebEngineClient.ts");
const source = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) as ArrayBuffer;
const first = new WebEngineClient({ timeoutMs: 60_000 });
await first.init();
const opened = await first.openBlend(source);
const track = opened.snapshot.nlaTracks?.find((candidate) => candidate.name === "M10 Time Mapping");
const strip = track?.strips.find((candidate) => candidate.id === "M10 Scaled Clip");
if (!track || !strip) throw new Error("NLA move fixture is incomplete");
const initialRevision = opened.snapshot.revision;
const initialTracks = JSON.stringify(opened.snapshot.nlaTracks);
let staleCode = "";
try {
await first.applyCommand({
type: "moveNLAStrip",
objectId: track.ownerId,
trackId: track.id,
stripId: strip.id,
frameStart: 5,
baseRevision: initialRevision - 1,
});
}
catch (error) {
staleCode = (error as { code?: string }).code ?? "";
}
const afterStale = await first.snapshot();
const moved = await first.applyCommand({
type: "moveNLAStrip",
objectId: track.ownerId,
trackId: track.id,
stripId: strip.id,
frameStart: 5,
baseRevision: initialRevision,
});
const movedStrip = moved.snapshot.nlaTracks?.find((candidate) => candidate.name === track.name)
?.strips.find((candidate) => candidate.id === strip.id);
const undone = await first.applyCommand({ type: "undo" });
const undoneStrip = undone.snapshot.nlaTracks?.find((candidate) => candidate.name === track.name)
?.strips.find((candidate) => candidate.id === strip.id);
const redone = await first.applyCommand({ type: "redo" });
const redoneStrip = redone.snapshot.nlaTracks?.find((candidate) => candidate.name === track.name)
?.strips.find((candidate) => candidate.id === strip.id);
const saved = await first.saveBlend();
first.terminate();
const second = new WebEngineClient({ timeoutMs: 60_000 });
await second.init();
const reopened = await second.openBlend(saved);
const reopenedStrip = reopened.snapshot.nlaTracks?.find((candidate) => candidate.name === track.name)
?.strips.find((candidate) => candidate.id === strip.id);
await second.applyCommand({ type: "setFrame", frame: 10 });
const report = await second.evaluateDepsgraph();
const mesh = report.depsgraph.meshes.find((candidate) => candidate.objectId === track.ownerId);
second.terminate();
return {
staleCode,
stalePreserved: JSON.stringify(afterStale.snapshot.nlaTracks) === initialTracks,
revisions: [initialRevision, moved.snapshot.revision, undone.snapshot.revision, redone.snapshot.revision],
delta: [moved.delta.baseRevision, moved.delta.nextRevision],
moved: movedStrip ? [movedStrip.frameStart, movedStrip.frameEnd] : null,
undone: undoneStrip ? [undoneStrip.frameStart, undoneStrip.frameEnd] : null,
redone: redoneStrip ? [redoneStrip.frameStart, redoneStrip.frameEnd] : null,
reopened: reopenedStrip ? [reopenedStrip.frameStart, reopenedStrip.frameEnd] : null,
evaluatedX: mesh?.worldMatrix[3] ?? null,
evaluationStatus: report.depsgraph.status,
};
}, { bytes: new Uint8Array(fixture) });
expect(result.staleCode).toBe("REVISION_CONFLICT");
expect(result.stalePreserved).toBe(true);
expect(result.revisions).toEqual([
result.revisions[0],
result.revisions[0] + 1,
result.revisions[0] + 2,
result.revisions[0] + 3,
]);
expect(result.delta).toEqual([result.revisions[0], result.revisions[0] + 1]);
expect(result.moved).toEqual([5, 25]);
expect(result.undone).toEqual([20, 40]);
expect(result.redone).toEqual([5, 25]);
expect(result.reopened).toEqual([5, 25]);
expect(result.evaluationStatus).toBe("EVALUATED");
expect(result.evaluatedX).toBeCloseTo(2.5, 5);
});