101 lines
4.3 KiB
TypeScript
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);
|
|
});
|