Advance N-015 through N-018 bounded workflows

This commit is contained in:
mes123456
2026-08-12 17:14:27 -04:00
parent 86136139e2
commit d54d5dd913
30 changed files with 662 additions and 59 deletions

View File

@@ -482,6 +482,35 @@ for (const offscreen of [false, true]) {
});
}
test("validates the N-016 Grease Pencil editor context transaction boundary", async ({ page }) => {
await page.goto("/");
const result = await page.evaluate(() => new Promise<Record<string, unknown>>((resolve, reject) => {
const worker = new Worker("/src/workers/grease-pencil-editor-test.worker.ts", { type: "module" });
worker.onmessage = (event: MessageEvent<Record<string, unknown>>) => { worker.terminate(); resolve(event.data); };
worker.onerror = (event) => { worker.terminate(); reject(new Error(event.message)); };
worker.postMessage({});
}));
expect(result.edit).toEqual([2, 5, [0, 2], [{ strokeIndex: 2, pointIndex: 1 }]]);
expect(result.stale).toContain("REVISION_CONFLICT");
expect(result.duplicate).toContain("GREASE_PENCIL_EDITOR_INVALID");
expect(result.negative).toContain("GREASE_PENCIL_EDITOR_INVALID");
});
test("edits N-016 Grease Pencil layers and frames from the bounded editor panel", async ({ page }) => {
await page.goto("/");
await page.setInputFiles("[data-testid=blend-file-input]", greasePencilBlend);
await expect(page.getByText("GreasePencilObject", { exact: true })).toBeVisible({ timeout: 20_000 });
await page.getByText("GreasePencilObject", { exact: true }).click();
const editor = page.getByTestId("grease-pencil-editor");
await expect(editor).toContainText("1 layers / 1 frames / 1 strokes");
await editor.getByLabel("Grease Pencil new layer name").fill("Browser Draft");
await editor.getByRole("button", { name: "Add Layer" }).click();
await expect(editor).toContainText("2 layers / 1 frames / 1 strokes");
await editor.getByLabel("Grease Pencil layer").selectOption({ label: "Browser Draft" });
await editor.getByRole("button", { name: "Add Frame" }).click();
await expect(editor).toContainText("2 layers / 2 frames / 1 strokes");
});
test("enforces the N-017 paint stroke, PBVH/UV hit and brush budgets", async ({ page }) => {
await page.goto("/");
const result = await page.evaluate(() => new Promise<Record<string, string>>((resolve, reject) => {
@@ -523,6 +552,24 @@ test("derives an N-017 source-face, barycentric and UV paint hit from a real ray
expect(result?.normal).toEqual([0, 0, 1]);
});
test("commits N-017 vertex color and weight patches from the bounded paint panel", async ({ page }) => {
await page.goto("/");
await page.setInputFiles("[data-testid=blend-file-input]", attributeBlend);
await expect(page.getByText("AttributeMeshObject", { exact: true })).toBeVisible({ timeout: 20_000 });
await page.getByText("AttributeMeshObject", { exact: true }).click();
await page.getByRole("button", { name: /Object Mode/ }).click();
await page.getByRole("button", { name: "1 Vertex" }).click();
await page.getByRole("button", { name: "Select All" }).click();
const editor = page.getByTestId("paint-editor");
await expect(editor).toContainText("5 selected vertices");
await editor.getByLabel("Paint vertex color").fill("#336699");
await editor.getByRole("button", { name: "Apply Color" }).click();
await expect(page.getByTestId("engine-status")).toContainText("SceneIR r", { timeout: 20_000 });
await editor.getByLabel("Paint vertex group").fill("BrowserPaint");
await editor.getByRole("button", { name: "Apply Weight" }).click();
await expect(page.getByTestId("engine-status")).toContainText("SceneIR r", { timeout: 20_000 });
});
test("validates the N-018 physics capability and cache manifests without claiming solvers", async ({ page }) => {
await page.goto("/");
const result = await page.evaluate(() => new Promise<Record<string, unknown>>((resolve, reject) => {
@@ -714,6 +761,20 @@ test("keeps N-015 selection history bounded and rejects stale raycast hits", asy
expect(result.gates).toEqual(["READY", "READY", "BLOCKED"]);
});
test("validates the N-015 curve gizmo interaction transaction boundary", async ({ page }) => {
await page.goto("/");
const result = await page.evaluate(() => new Promise<Record<string, unknown>>((resolve, reject) => {
const worker = new Worker("/src/workers/nonmesh-interaction-test.worker.ts", { type: "module" });
worker.onmessage = (event: MessageEvent<Record<string, unknown>>) => { worker.terminate(); resolve(event.data); };
worker.onerror = (event) => { worker.terminate(); reject(new Error(event.message)); };
worker.postMessage({});
}));
expect(result.commit).toEqual([4, [1.25, 2, 3]]);
expect(result.stale).toContain("REVISION_CONFLICT");
expect(result.duplicate).toContain("CURVE_GIZMO_INVALID");
expect(result.axis).toContain("CURVE_GIZMO_INVALID");
});
test("validates bounded OpenVDB metadata, SHA and cancellation", async ({ page }) => {
await page.goto("/");
const result = await page.evaluate(() => new Promise<{ decodedByteLength: number; outsideProject: string; cancelled: boolean }>((resolve, reject) => {