Advance M8-M11 parity workflows
This commit is contained in:
92
web/tests/unit/paint-pbvh-capability.test.mjs
Normal file
92
web/tests/unit/paint-pbvh-capability.test.mjs
Normal file
@@ -0,0 +1,92 @@
|
||||
import assert from "node:assert/strict";
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import test from "node:test";
|
||||
import ts from "typescript";
|
||||
|
||||
const repoRoot = path.resolve(import.meta.dirname, "../../..");
|
||||
const temporary = fs.mkdtempSync(path.join(os.tmpdir(), "paint-pbvh-capability-unit-"));
|
||||
|
||||
function transpile(sourceName, outputName, replacements = []) {
|
||||
const sourcePath = path.join(repoRoot, "web/protocol", sourceName);
|
||||
const transpiled = ts.transpileModule(fs.readFileSync(sourcePath, "utf8"), {
|
||||
compilerOptions: { module: ts.ModuleKind.ES2022, target: ts.ScriptTarget.ES2022 },
|
||||
fileName: sourcePath,
|
||||
reportDiagnostics: true,
|
||||
});
|
||||
assert.deepEqual(transpiled.diagnostics, []);
|
||||
const output = replacements.reduce((source, [from, to]) => source.replaceAll(from, to), transpiled.outputText);
|
||||
fs.writeFileSync(path.join(temporary, outputName), output);
|
||||
}
|
||||
|
||||
transpile("capability-gates.ts", "capability-gates.mjs");
|
||||
transpile("paint-pbvh-capability.ts", "paint-pbvh-capability.mjs", [
|
||||
['from "./capability-gates"', 'from "./capability-gates.mjs"'],
|
||||
]);
|
||||
const pbvh = await import(pathToFileURL(path.join(temporary, "paint-pbvh-capability.mjs")));
|
||||
|
||||
const base = {
|
||||
schemaVersion: 1,
|
||||
operation: "PBVH_BRUSH",
|
||||
domain: "VERTEX_COLOR",
|
||||
brush: "DRAW",
|
||||
objectId: "object:Paint",
|
||||
meshId: "mesh:Paint",
|
||||
baseRevision: 7,
|
||||
};
|
||||
|
||||
test("M9-13 freezes the active Blender 5.2 PBVH-related brush inventory", () => {
|
||||
const inventory = pbvh.paintPBVHBrushInventory();
|
||||
const counts = Object.fromEntries(["SCULPT", "VERTEX_COLOR", "WEIGHT", "TEXTURE"].map((domain) => [
|
||||
domain,
|
||||
inventory.filter((entry) => entry.domain === domain).length,
|
||||
]));
|
||||
assert.deepEqual(counts, { SCULPT: 32, VERTEX_COLOR: 4, WEIGHT: 4, TEXTURE: 6 });
|
||||
assert.equal(new Set(inventory.map((entry) => `${entry.domain}:${entry.brush}`)).size, 46);
|
||||
assert.ok(inventory.every((entry) => entry.source.endsWith("DNA_brush_enums.h")));
|
||||
});
|
||||
|
||||
test("M9-13 blocks every PBVH brush when the WASM entrypoint is absent", () => {
|
||||
for (const entry of pbvh.paintPBVHBrushInventory()) {
|
||||
const gate = pbvh.gatePaintPBVHCapability({ ...base, domain: entry.domain, brush: entry.brush }, {
|
||||
nativeEntrypointPresent: false,
|
||||
sessionContextReady: false,
|
||||
verifiedBrushes: new Set(),
|
||||
currentRevision: 7,
|
||||
currentObjectId: base.objectId,
|
||||
currentMeshId: base.meshId,
|
||||
});
|
||||
assert.equal(gate.taskId, "N-017");
|
||||
assert.equal(gate.status, "BLOCKED");
|
||||
assert.deepEqual(gate.issues.map((issue) => issue.code), ["PAINT_PBVH_UNAVAILABLE"]);
|
||||
assert.equal(gate.issues[0].recoverable, false);
|
||||
}
|
||||
});
|
||||
|
||||
test("M9-13 remains fail-closed after symbol discovery until context and a brush golden exist", () => {
|
||||
const common = { nativeEntrypointPresent: true, verifiedBrushes: new Set(), currentRevision: 7 };
|
||||
assert.equal(pbvh.gatePaintPBVHCapability(base, { ...common, sessionContextReady: false }).issues[0].code, "PAINT_PBVH_CONTEXT_UNAVAILABLE");
|
||||
assert.equal(pbvh.gatePaintPBVHCapability(base, { ...common, sessionContextReady: true }).issues[0].code, "PAINT_PBVH_BRUSH_UNVERIFIED");
|
||||
assert.equal(pbvh.gatePaintPBVHCapability(base, {
|
||||
...common,
|
||||
sessionContextReady: true,
|
||||
verifiedBrushes: new Set(["VERTEX_COLOR:DRAW"]),
|
||||
}).status, "READY");
|
||||
});
|
||||
|
||||
test("M9-13 validates identity and revision before reporting runtime availability", () => {
|
||||
const context = {
|
||||
nativeEntrypointPresent: false,
|
||||
sessionContextReady: false,
|
||||
verifiedBrushes: new Set(),
|
||||
currentRevision: 7,
|
||||
currentObjectId: base.objectId,
|
||||
currentMeshId: base.meshId,
|
||||
};
|
||||
assert.equal(pbvh.gatePaintPBVHCapability({ ...base, baseRevision: 6 }, context).issues[0].code, "REVISION_CONFLICT");
|
||||
assert.equal(pbvh.gatePaintPBVHCapability({ ...base, objectId: "object:Other" }, context).issues[0].code, "PAINT_SCHEMA_INVALID");
|
||||
assert.throws(() => pbvh.parsePaintPBVHCapabilityRequest({ ...base, brush: "FAKE" }), { code: "PAINT_PBVH_BRUSH_UNVERIFIED" });
|
||||
assert.throws(() => pbvh.parsePaintPBVHCapabilityRequest({ ...base, proxySuccess: true }), { code: "PAINT_SCHEMA_INVALID" });
|
||||
});
|
||||
Reference in New Issue
Block a user