97 lines
3.7 KiB
TypeScript
97 lines
3.7 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { paintPBVHBrushInventory } from "../../protocol/paint-pbvh-capability";
|
|
|
|
const attributeBlend = path.resolve(import.meta.dirname, "../../../tests/files/web/attribute_scene.blend");
|
|
|
|
test("M9-13 production Worker blocks the full PBVH brush inventory without changing Main", async ({ page }) => {
|
|
test.setTimeout(120_000);
|
|
await page.goto("/");
|
|
const blendBytes = fs.readFileSync(attributeBlend);
|
|
const result = await page.evaluate(async ({ blendBytes, inventory }) => {
|
|
const { WebEngineClient } = await import("/src/engine-client/WebEngineClient.ts");
|
|
const engine = new WebEngineClient({ timeoutMs: 60_000 });
|
|
await engine.init();
|
|
const opened = await engine.openBlend(blendBytes.buffer.slice(blendBytes.byteOffset, blendBytes.byteOffset + blendBytes.byteLength));
|
|
const object = opened.snapshot.nodes.find((candidate) => candidate.id === opened.snapshot.activeObjectId && candidate.type === "MESH");
|
|
if (!object?.dataId) throw new Error("PBVH fixture has no active Mesh object");
|
|
const before = await engine.snapshot();
|
|
const gates = [];
|
|
for (const entry of inventory) {
|
|
gates.push(await engine.queryPaintPBVHCapability({
|
|
schemaVersion: 1,
|
|
operation: "PBVH_BRUSH",
|
|
domain: entry.domain,
|
|
brush: entry.brush,
|
|
objectId: object.id,
|
|
meshId: object.dataId,
|
|
baseRevision: before.snapshot.revision,
|
|
}));
|
|
}
|
|
const stale = await engine.queryPaintPBVHCapability({
|
|
schemaVersion: 1,
|
|
operation: "PBVH_BRUSH",
|
|
domain: "WEIGHT",
|
|
brush: "DRAW",
|
|
objectId: object.id,
|
|
meshId: object.dataId,
|
|
baseRevision: before.snapshot.revision + 1,
|
|
});
|
|
let malformed: { code?: string; severity?: string; recoverable?: boolean } = {};
|
|
try {
|
|
await engine.queryPaintPBVHCapability({
|
|
schemaVersion: 1,
|
|
operation: "PBVH_BRUSH",
|
|
domain: "WEIGHT",
|
|
brush: "DRAW",
|
|
objectId: object.id,
|
|
meshId: object.dataId,
|
|
baseRevision: before.snapshot.revision,
|
|
proxySuccess: true,
|
|
} as never);
|
|
}
|
|
catch (error) {
|
|
malformed = error as typeof malformed;
|
|
}
|
|
const after = await engine.snapshot();
|
|
engine.terminate();
|
|
return {
|
|
count: gates.length,
|
|
statuses: [...new Set(gates.map((gate) => gate.status))],
|
|
taskIds: [...new Set(gates.map((gate) => gate.taskId))],
|
|
issueCodes: [...new Set(gates.flatMap((gate) => gate.issues.map((issue) => issue.code)))],
|
|
capabilities: new Set(gates.map((gate) => gate.capability)).size,
|
|
staleCode: stale.issues[0]?.code,
|
|
malformed,
|
|
beforeRevision: before.snapshot.revision,
|
|
afterRevision: after.snapshot.revision,
|
|
beforeHandles: before.status.liveHandles,
|
|
afterHandles: after.status.liveHandles,
|
|
beforeBytes: before.status.allocatedBytes,
|
|
afterBytes: after.status.allocatedBytes,
|
|
};
|
|
}, { blendBytes: new Uint8Array(blendBytes), inventory: paintPBVHBrushInventory() });
|
|
|
|
expect(result).toEqual({
|
|
count: 46,
|
|
statuses: ["BLOCKED"],
|
|
taskIds: ["N-017"],
|
|
issueCodes: ["PAINT_PBVH_UNAVAILABLE"],
|
|
capabilities: 46,
|
|
staleCode: "REVISION_CONFLICT",
|
|
malformed: {
|
|
code: "PAINT_SCHEMA_INVALID",
|
|
severity: "error",
|
|
recoverable: true,
|
|
message: "PBVH capability request contains unsupported field proxySuccess",
|
|
},
|
|
beforeRevision: result.beforeRevision,
|
|
afterRevision: result.beforeRevision,
|
|
beforeHandles: result.beforeHandles,
|
|
afterHandles: result.beforeHandles,
|
|
beforeBytes: result.beforeBytes,
|
|
afterBytes: result.beforeBytes,
|
|
});
|
|
});
|