Reorganize Blender Web execution around capabilities
This commit is contained in:
41
web/tests/e2e/corrective-asset-catalog-pilot.spec.ts
Normal file
41
web/tests/e2e/corrective-asset-catalog-pilot.spec.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const evidenceRoot = path.resolve(import.meta.dirname, "../../../tests/golden/corrective/C3-003");
|
||||
|
||||
test("C3-003 Chromium asset catalog pilot covers five cases and save/reopen", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
const report = await page.evaluate(async () => {
|
||||
const { createAssetCatalogRegistry, AssetCatalogResourceResolver, InMemoryCatalogProvider, InMemoryMainStore, CorrectiveHistoryStore } = await import("/src/corrective-pilot-bridge.ts");
|
||||
const bytes = new TextEncoder().encode("chromium-catalog-fixture");
|
||||
const provider = new InMemoryCatalogProvider("EXTERNAL_LIBRARY");
|
||||
const hash = await provider.put("library.blend", bytes);
|
||||
const resources = new AssetCatalogResourceResolver();
|
||||
resources.registerProvider(provider).setActiveLibraryContext({ libraryId: "lib:chromium", sourceKind: "EXTERNAL", sourceId: "library.blend", generation: 1, revision: 4, readOnly: false });
|
||||
const createMain = () => new InMemoryMainStore({ entries: [] }, 4, false, (value) => ({ entries: value.entries.map((entry) => ({ ...entry })) }));
|
||||
const command = (overrides = {}) => ({ schemaVersion: 1, requestId: "chromium-catalog-001", commandType: "assetCatalogAppend", baseRevision: 4, context: { mainId: "main:chromium", targetKind: "ASSET_LIBRARY", targetId: "library:chromium", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "EXTERNAL", sha256: hash }, resourceProvider: "EXTERNAL_LIBRARY" }, payload: { id: "asset:chromium", name: "Chromium Asset", resource: { schemaVersion: 1, requestId: "resource-chromium-001", sourceKind: "EXTERNAL", sourceId: "library.blend", sha256: hash } }, ...overrides });
|
||||
const desktopMain = createMain(); const wasmMain = createMain();
|
||||
const desktop = await createAssetCatalogRegistry(desktopMain, resources).dispatch("DESKTOP", { command: command(), mainRevision: 4 });
|
||||
const wasm = await createAssetCatalogRegistry(wasmMain, resources).dispatch("WASM", { command: command(), mainRevision: 4 });
|
||||
const duplicate = await createAssetCatalogRegistry(desktopMain, resources).dispatch("DESKTOP", { command: command({ baseRevision: 5 }), mainRevision: 5 });
|
||||
const missingResources = new AssetCatalogResourceResolver(); missingResources.setActiveLibraryContext({ libraryId: "lib:chromium", sourceKind: "EXTERNAL", sourceId: "library.blend", generation: 1, revision: 4, readOnly: false });
|
||||
const missing = await createAssetCatalogRegistry(createMain(), missingResources).dispatch("WASM", { command: command(), mainRevision: 4 });
|
||||
const revision = await createAssetCatalogRegistry(createMain(), resources).dispatch("WASM", { command: command({ baseRevision: 3 }), mainRevision: 4 });
|
||||
const malformed = await createAssetCatalogRegistry(createMain(), resources).dispatch("DESKTOP", { command: command({ payload: { id: "bad id" } }), mainRevision: 4 });
|
||||
const history = new CorrectiveHistoryStore({ entries: [] }, 4, false, (value) => ({ entries: value.entries.map((entry) => ({ ...entry })) }));
|
||||
history.commit(desktopMain.snapshot().value, 5, true); history.save(); history.commit({ entries: [] }, 6, true); history.reopen();
|
||||
return { positive: { desktop: desktop.result, wasm: wasm.result, desktopEntries: desktopMain.snapshot().value.entries.length, wasmEntries: wasmMain.snapshot().value.entries.length }, negative: { duplicate: duplicate.result, missing: missing.result, revision: revision.result, malformed: malformed.result }, persistence: history.snapshot(), parity: JSON.stringify(desktop.result) === JSON.stringify(wasm.result) };
|
||||
});
|
||||
fs.mkdirSync(evidenceRoot, { recursive: true });
|
||||
fs.writeFileSync(path.join(evidenceRoot, process.env.C3_PILOT_REPORT ?? "receipt-report.json"), `${JSON.stringify({ schemaVersion: 1, task: "C3-003", operation: "CORRECTIVE_ASSET_CATALOG_CHROMIUM_PILOT", browser: "chromium", queueMutation: false, ...report }, null, 2)}\n`);
|
||||
expect(report.parity).toBe(true);
|
||||
expect(report.positive.desktop.status).toBe("FINISHED");
|
||||
expect(report.positive.desktopEntries).toBe(1);
|
||||
expect(report.positive.wasmEntries).toBe(1);
|
||||
expect(report.negative.duplicate.mainRevisionAfter).toBe(5);
|
||||
expect(report.negative.missing.mainRevisionAfter).toBe(4);
|
||||
expect(report.negative.revision.code).toBe("REVISION_CONFLICT");
|
||||
expect(report.negative.malformed.code).toBe("COMMAND_MALFORMED");
|
||||
expect(report.persistence).toEqual({ value: { entries: [{ id: "asset:chromium", name: "Chromium Asset", sourceId: "library.blend", sourceSha256: expect.any(String), byteLength: 24 }] }, revision: 5, dirty: false });
|
||||
});
|
||||
18
web/tests/e2e/corrective-family-runner.spec.ts
Normal file
18
web/tests/e2e/corrective-family-runner.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const evidenceRoot = path.resolve(import.meta.dirname, "../../../tests/golden/corrective/C5-002");
|
||||
|
||||
test("C5-002 Chromium family runner dispatches data-driven Asset, Modifier, and Mesh cases", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
const report = await page.evaluate(async () => {
|
||||
const { AssetCatalogResourceResolver, InMemoryCatalogProvider, InMemoryMainStore, createAssetCatalogRegistry, createModifierMain, createModifierRegistry, createMeshMain, createMeshRegistry, runCorrectiveFamilyCases, summarizeCorrectiveFamilyResults } = await import("/src/corrective-pilot-bridge.ts");
|
||||
const bytes = new TextEncoder().encode("family-runner-resource"); const provider = new InMemoryCatalogProvider("EXTERNAL_LIBRARY"); const sourceHash = await provider.put("library.blend", bytes); const resolver = new AssetCatalogResourceResolver(); resolver.registerProvider(provider).setActiveLibraryContext({ libraryId: "library:family", sourceKind: "EXTERNAL", sourceId: "library.blend", generation: 1, revision: 1, readOnly: false });
|
||||
const command = (family, surface) => family === "ASSET_CATALOG" ? ({ schemaVersion: 1, requestId: `chromium-family-${surface.toLowerCase()}-asset`, commandType: "assetCatalogAppend", baseRevision: 1, context: { mainId: "main:asset", targetKind: "ASSET_LIBRARY", targetId: "library:family", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "EXTERNAL", sha256: sourceHash }, resourceProvider: "EXTERNAL_LIBRARY" }, payload: { id: `asset:${surface.toLowerCase()}`, name: "Family Asset", resource: { schemaVersion: 1, requestId: "family-resource", sourceKind: "EXTERNAL", sourceId: "library.blend", sha256: sourceHash } } }) : family === "MODIFIER" ? ({ schemaVersion: 1, requestId: `chromium-family-${surface.toLowerCase()}-modifier`, commandType: "modifierSetEnabled", baseRevision: 1, context: { mainId: "main:modifier", targetKind: "MODIFIER", targetId: "modifier:one", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "LOCAL", sha256: "f".repeat(64) } }, payload: { modifierUuid: "modifier:one", enabled: true } }) : ({ schemaVersion: 1, requestId: `chromium-family-${surface.toLowerCase()}-mesh`, commandType: "meshTranslateVertex", baseRevision: 1, context: { mainId: "main:mesh", targetKind: "MESH", targetId: "mesh:one", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "LOCAL", sha256: "0".repeat(64) } }, payload: { vertexId: "vertex:0", delta: { x: 1, y: 0, z: 0 } } });
|
||||
const cases = []; for (const family of ["ASSET_CATALOG", "MODIFIER", "MESH"]) for (const surface of ["DESKTOP", "WASM"]) { const main = family === "ASSET_CATALOG" ? new InMemoryMainStore({ entries: [] }, 1, false, (value) => ({ entries: value.entries.map((entry) => ({ ...entry })) })) : family === "MODIFIER" ? createModifierMain([{ uuid: "modifier:one", name: "One", type: "BEVEL", enabled: false, showViewport: true, showRender: true }], 1, false) : createMeshMain([{ id: "vertex:0", x: 0, y: 0, z: 0 }], 1, false); const registry = family === "ASSET_CATALOG" ? createAssetCatalogRegistry(main, resolver) : family === "MODIFIER" ? createModifierRegistry(main) : createMeshRegistry(main); cases.push({ id: `${family.toLowerCase()}-${surface.toLowerCase()}`, family, registry, surface, command: command(family, surface), mainRevision: 1 }); }
|
||||
const results = await runCorrectiveFamilyCases(cases); return { summary: summarizeCorrectiveFamilyResults(results), results: results.map((result) => ({ id: result.id, family: result.family, surface: result.surface, receipt: result.receipt.result })) };
|
||||
});
|
||||
fs.mkdirSync(evidenceRoot, { recursive: true }); fs.writeFileSync(path.join(evidenceRoot, process.env.C4_PILOT_REPORT ?? "chromium-family-report.json"), `${JSON.stringify({ schemaVersion: 1, task: "C5-002", operation: "CORRECTIVE_FAMILY_RUNNER_CHROMIUM", browser: "chromium", queueMutation: false, ...report }, null, 2)}\n`);
|
||||
expect(report.results).toHaveLength(6); expect(report.results.every((result) => result.receipt.status === "FINISHED")).toBe(true); expect(report.summary).toEqual({ ASSET_CATALOG: { total: 2, finished: 2, unchanged: 0 }, MODIFIER: { total: 2, finished: 2, unchanged: 0 }, MESH: { total: 2, finished: 2, unchanged: 0 } });
|
||||
});
|
||||
33
web/tests/e2e/corrective-mesh-pilot.spec.ts
Normal file
33
web/tests/e2e/corrective-mesh-pilot.spec.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const evidenceRoot = path.resolve(import.meta.dirname, "../../../tests/golden/corrective/C4-002");
|
||||
|
||||
test("C4-002 Chromium mesh pilot covers geometry parity, rollback, and save/reopen", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
const report = await page.evaluate(async () => {
|
||||
const { createMeshMain, createMeshRegistry, CorrectiveHistoryStore } = await import("/src/corrective-pilot-bridge.ts");
|
||||
const fixture = [{ id: "vertex:0", x: 1, y: 2, z: 3 }, { id: "vertex:1", x: 0, y: 0, z: 0 }];
|
||||
const command = (overrides = {}) => ({ schemaVersion: 1, requestId: "chromium-mesh-001", commandType: "meshTranslateVertex", baseRevision: 9, context: { mainId: "main:chromium-mesh", targetKind: "MESH", targetId: "mesh:cube", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "LOCAL", sha256: "b".repeat(64) } }, payload: { vertexId: "vertex:0", delta: { x: 0.5, y: -1, z: 2 } }, ...overrides });
|
||||
const desktopMain = createMeshMain(fixture, 9, false); const wasmMain = createMeshMain(fixture, 9, false);
|
||||
const desktop = await createMeshRegistry(desktopMain).dispatch("DESKTOP", { command: command(), mainRevision: 9 }); const wasm = await createMeshRegistry(wasmMain).dispatch("WASM", { command: command(), mainRevision: 9 });
|
||||
const rollbackMain = createMeshMain(fixture, 9, false); const registry = createMeshRegistry(rollbackMain);
|
||||
const malformed = await registry.dispatch("DESKTOP", { command: command({ payload: { vertexId: "vertex:0", delta: { x: 0.5, y: -1, z: 2, w: 1 } } }), mainRevision: 9 });
|
||||
const stale = await registry.dispatch("WASM", { command: command({ baseRevision: 8 }), mainRevision: 9 });
|
||||
const unknown = await registry.dispatch("DESKTOP", { command: command({ payload: { vertexId: "vertex:missing", delta: { x: 0.5, y: -1, z: 2 } } }), mainRevision: 9 });
|
||||
const clone = (value) => ({ vertices: value.vertices.map((vertex) => ({ ...vertex })) });
|
||||
const history = new CorrectiveHistoryStore({ vertices: fixture }, 9, false, clone);
|
||||
await createMeshRegistry(history).dispatch("WASM", { command: command(), mainRevision: 9 });
|
||||
const saved = history.save(); const undone = history.undo(); const redone = history.redo(); const reopened = history.reopen();
|
||||
return { positive: { desktop: desktop.result, wasm: wasm.result, desktopMain: desktopMain.snapshot(), wasmMain: wasmMain.snapshot() }, negative: { malformed: malformed.result, stale: stale.result, unknown: unknown.result, rollbackMain: rollbackMain.snapshot() }, persistence: { saved, undone, redone, reopened, final: history.snapshot() }, parity: JSON.stringify(desktop.result) === JSON.stringify(wasm.result) && JSON.stringify(desktopMain.snapshot()) === JSON.stringify(wasmMain.snapshot()) };
|
||||
});
|
||||
fs.mkdirSync(evidenceRoot, { recursive: true });
|
||||
fs.writeFileSync(path.join(evidenceRoot, process.env.C4_PILOT_REPORT ?? "receipt-report.json"), `${JSON.stringify({ schemaVersion: 1, task: "C4-002", operation: "CORRECTIVE_MESH_CHROMIUM_PILOT", browser: "chromium", queueMutation: false, ...report }, null, 2)}\n`);
|
||||
expect(report.parity).toBe(true); expect(report.positive.desktop.status).toBe("FINISHED");
|
||||
expect(report.positive.desktop.delta).toEqual({ vertexId: "vertex:0", before: { x: 1, y: 2, z: 3 }, after: { x: 1.5, y: 1, z: 5 } });
|
||||
expect(report.positive.desktopMain.value.vertices[0]).toEqual({ id: "vertex:0", x: 1.5, y: 1, z: 5 }); expect(report.positive.desktopMain.dirty).toBe(true);
|
||||
expect(report.negative.malformed.code).toBe("COMMAND_MALFORMED"); expect(report.negative.stale.code).toBe("REVISION_CONFLICT"); expect(report.negative.unknown.code).toBe("COMMAND_UNSUPPORTED");
|
||||
expect(report.negative.rollbackMain).toEqual({ value: { vertices: [{ id: "vertex:0", x: 1, y: 2, z: 3 }, { id: "vertex:1", x: 0, y: 0, z: 0 }] }, revision: 9, dirty: false });
|
||||
expect(report.persistence.saved.dirty).toBe(false); expect(report.persistence.undone.value.vertices[0].x).toBe(1); expect(report.persistence.redone.value.vertices[0].x).toBe(1.5); expect(report.persistence.reopened.value.vertices[0].z).toBe(5); expect(report.persistence.final.dirty).toBe(false);
|
||||
});
|
||||
60
web/tests/e2e/corrective-modifier-pilot.spec.ts
Normal file
60
web/tests/e2e/corrective-modifier-pilot.spec.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const evidenceRoot = path.resolve(import.meta.dirname, "../../../tests/golden/corrective/C4-001");
|
||||
|
||||
test("C4-001 Chromium modifier pilot covers positive parity, rollback, and save/reopen", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
const report = await page.evaluate(async () => {
|
||||
const { createModifierMain, createModifierRegistry, CorrectiveHistoryStore } = await import("/src/corrective-pilot-bridge.ts");
|
||||
const fixture = [{ uuid: "modifier:bevel", name: "Pilot Bevel", type: "BEVEL", enabled: false, showViewport: true, showRender: true }];
|
||||
const command = (overrides = {}) => ({
|
||||
schemaVersion: 1,
|
||||
requestId: "chromium-modifier-001",
|
||||
commandType: "modifierSetEnabled",
|
||||
baseRevision: 7,
|
||||
context: { mainId: "main:chromium-modifier", targetKind: "MODIFIER", targetId: "modifier:bevel", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "LOCAL", sha256: "a".repeat(64) } },
|
||||
payload: { modifierUuid: "modifier:bevel", enabled: true },
|
||||
...overrides,
|
||||
});
|
||||
const desktopMain = createModifierMain(fixture, 7, false);
|
||||
const wasmMain = createModifierMain(fixture, 7, false);
|
||||
const desktop = await createModifierRegistry(desktopMain).dispatch("DESKTOP", { command: command(), mainRevision: 7 });
|
||||
const wasm = await createModifierRegistry(wasmMain).dispatch("WASM", { command: command(), mainRevision: 7 });
|
||||
const rollbackMain = createModifierMain(fixture, 7, false);
|
||||
const registry = createModifierRegistry(rollbackMain);
|
||||
const malformed = await registry.dispatch("DESKTOP", { command: command({ payload: { modifierUuid: "modifier:bevel", enabled: true, unexpected: true } }), mainRevision: 7 });
|
||||
const stale = await registry.dispatch("WASM", { command: command({ baseRevision: 6 }), mainRevision: 7 });
|
||||
const unknown = await registry.dispatch("DESKTOP", { command: command({ payload: { modifierUuid: "modifier:missing", enabled: true } }), mainRevision: 7 });
|
||||
const clone = (value) => ({ modifiers: value.modifiers.map((modifier) => ({ ...modifier })) });
|
||||
const history = new CorrectiveHistoryStore({ modifiers: fixture }, 7, false, clone);
|
||||
await createModifierRegistry(history).dispatch("WASM", { command: command(), mainRevision: 7 });
|
||||
const saved = history.save();
|
||||
const undone = history.undo();
|
||||
const redone = history.redo();
|
||||
const reopened = history.reopen();
|
||||
return {
|
||||
positive: { desktop: desktop.result, wasm: wasm.result, desktopMain: desktopMain.snapshot(), wasmMain: wasmMain.snapshot() },
|
||||
negative: { malformed: malformed.result, stale: stale.result, unknown: unknown.result, rollbackMain: rollbackMain.snapshot() },
|
||||
persistence: { saved, undone, redone, reopened, final: history.snapshot() },
|
||||
parity: JSON.stringify(desktop.result) === JSON.stringify(wasm.result) && JSON.stringify(desktopMain.snapshot()) === JSON.stringify(wasmMain.snapshot()),
|
||||
};
|
||||
});
|
||||
fs.mkdirSync(evidenceRoot, { recursive: true });
|
||||
fs.writeFileSync(path.join(evidenceRoot, process.env.C4_PILOT_REPORT ?? "receipt-report.json"), `${JSON.stringify({ schemaVersion: 1, task: "C4-001", operation: "CORRECTIVE_MODIFIER_CHROMIUM_PILOT", browser: "chromium", queueMutation: false, ...report }, null, 2)}\n`);
|
||||
expect(report.parity).toBe(true);
|
||||
expect(report.positive.desktop.status).toBe("FINISHED");
|
||||
expect(report.positive.desktop.delta).toEqual({ modifierUuid: "modifier:bevel", previousEnabled: false, enabled: true });
|
||||
expect(report.positive.desktopMain.value.modifiers[0].enabled).toBe(true);
|
||||
expect(report.positive.desktopMain.dirty).toBe(true);
|
||||
expect(report.negative.malformed.code).toBe("COMMAND_MALFORMED");
|
||||
expect(report.negative.stale.code).toBe("REVISION_CONFLICT");
|
||||
expect(report.negative.unknown.code).toBe("COMMAND_UNSUPPORTED");
|
||||
expect(report.negative.rollbackMain).toEqual({ value: { modifiers: [{ uuid: "modifier:bevel", name: "Pilot Bevel", type: "BEVEL", enabled: false, showViewport: true, showRender: true }] }, revision: 7, dirty: false });
|
||||
expect(report.persistence.saved.dirty).toBe(false);
|
||||
expect(report.persistence.undone.value.modifiers[0].enabled).toBe(false);
|
||||
expect(report.persistence.redone.value.modifiers[0].enabled).toBe(true);
|
||||
expect(report.persistence.reopened.value.modifiers[0].enabled).toBe(true);
|
||||
expect(report.persistence.final.dirty).toBe(false);
|
||||
});
|
||||
27
web/tests/e2e/corrective-negative-matrix.spec.ts
Normal file
27
web/tests/e2e/corrective-negative-matrix.spec.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const evidenceRoot = path.resolve(import.meta.dirname, "../../../tests/golden/corrective/C4-003");
|
||||
|
||||
test("C4-003 Chromium negative matrix keeps all Main snapshots unchanged", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
const report = await page.evaluate(async () => {
|
||||
const { createAssetCatalogRegistry, AssetCatalogResourceResolver, InMemoryMainStore, createModifierMain, createModifierRegistry, createMeshMain, createMeshRegistry } = await import("/src/corrective-pilot-bridge.ts");
|
||||
const modifierFixture = [{ uuid: "modifier:one", name: "One", type: "BEVEL", enabled: false, showViewport: true, showRender: true }]; const meshFixture = [{ id: "vertex:0", x: 0, y: 0, z: 0 }];
|
||||
const modifierCommand = (overrides = {}) => ({ schemaVersion: 1, requestId: "chromium-negative-modifier", commandType: "modifierSetEnabled", baseRevision: 3, context: { mainId: "main:modifier", targetKind: "MODIFIER", targetId: "modifier:one", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "LOCAL", sha256: "c".repeat(64) } }, payload: { modifierUuid: "modifier:one", enabled: true }, ...overrides });
|
||||
const meshCommand = (overrides = {}) => ({ schemaVersion: 1, requestId: "chromium-negative-mesh", commandType: "meshTranslateVertex", baseRevision: 4, context: { mainId: "main:mesh", targetKind: "MESH", targetId: "mesh:one", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "LOCAL", sha256: "d".repeat(64) } }, payload: { vertexId: "vertex:0", delta: { x: 1, y: 0, z: 0 } }, ...overrides });
|
||||
const assetCommand = (overrides = {}) => ({ schemaVersion: 1, requestId: "chromium-negative-asset", commandType: "assetCatalogAppend", baseRevision: 2, context: { mainId: "main:asset", targetKind: "ASSET_LIBRARY", targetId: "library:one", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "EXTERNAL", sha256: "e".repeat(64) }, resourceProvider: "EXTERNAL_LIBRARY" }, payload: { id: "asset:one", name: "One", resource: { schemaVersion: 1, requestId: "resource-one", sourceKind: "EXTERNAL", sourceId: "library.blend", sha256: "e".repeat(64) } }, ...overrides });
|
||||
const modifierMain = createModifierMain(modifierFixture, 3, false); const meshMain = createMeshMain(meshFixture, 4, false); const assetMain = new InMemoryMainStore({ entries: [] }, 2, false, (value) => ({ entries: value.entries.map((entry) => ({ ...entry })) })); const resources = new AssetCatalogResourceResolver(); resources.setActiveLibraryContext({ libraryId: "library:one", sourceKind: "EXTERNAL", sourceId: "library.blend", generation: 1, revision: 2, readOnly: false });
|
||||
const cases = [
|
||||
["modifierMalformed", createModifierRegistry(modifierMain), "DESKTOP", modifierCommand({ payload: { modifierUuid: "modifier:one", enabled: true, extra: true } }), 3], ["modifierUnsupported", createModifierRegistry(modifierMain), "WASM", modifierCommand({ payload: { modifierUuid: "modifier:missing", enabled: true } }), 3], ["modifierRevision", createModifierRegistry(modifierMain), "DESKTOP", modifierCommand({ baseRevision: 2 }), 3],
|
||||
["meshMalformed", createMeshRegistry(meshMain), "WASM", meshCommand({ payload: { vertexId: "vertex:0", delta: { x: 1, y: 0, z: 0, extra: true } } }), 4], ["meshUnsupported", createMeshRegistry(meshMain), "DESKTOP", meshCommand({ payload: { vertexId: "vertex:missing", delta: { x: 1, y: 0, z: 0 } } }), 4], ["meshRevision", createMeshRegistry(meshMain), "WASM", meshCommand({ baseRevision: 3 }), 4],
|
||||
["assetMalformed", createAssetCatalogRegistry(assetMain, resources), "DESKTOP", assetCommand({ payload: { id: "bad id" } }), 2], ["assetResourceMissing", createAssetCatalogRegistry(assetMain, resources), "WASM", assetCommand(), 2], ["assetRevision", createAssetCatalogRegistry(assetMain, resources), "DESKTOP", assetCommand({ baseRevision: 1 }), 2],
|
||||
];
|
||||
const results = {}; for (const [name, registry, surface, command, mainRevision] of cases) results[name] = (await registry.dispatch(surface, { command, mainRevision })).result;
|
||||
return { results, snapshots: { modifier: modifierMain.snapshot(), mesh: meshMain.snapshot(), asset: assetMain.snapshot() }, unchanged: Object.values(results).every((result) => result.mainMutation === "UNCHANGED") };
|
||||
});
|
||||
fs.mkdirSync(evidenceRoot, { recursive: true }); fs.writeFileSync(path.join(evidenceRoot, process.env.C4_PILOT_REPORT ?? "chromium-negative-report.json"), `${JSON.stringify({ schemaVersion: 1, task: "C4-003", operation: "CORRECTIVE_NEGATIVE_MATRIX_CHROMIUM", browser: "chromium", queueMutation: false, ...report }, null, 2)}\n`);
|
||||
expect(report.unchanged).toBe(true); expect(report.results.modifierMalformed.code).toBe("COMMAND_MALFORMED"); expect(report.results.modifierUnsupported.code).toBe("COMMAND_UNSUPPORTED"); expect(report.results.modifierRevision.code).toBe("REVISION_CONFLICT"); expect(report.results.meshMalformed.code).toBe("COMMAND_MALFORMED"); expect(report.results.meshUnsupported.code).toBe("COMMAND_UNSUPPORTED"); expect(report.results.meshRevision.code).toBe("REVISION_CONFLICT"); expect(report.results.assetMalformed.code).toBe("COMMAND_MALFORMED"); expect(report.results.assetResourceMissing.code).toBe("RESOURCE_REQUIRED"); expect(report.results.assetRevision.code).toBe("REVISION_CONFLICT");
|
||||
expect(report.snapshots.modifier.revision).toBe(3); expect(report.snapshots.mesh.revision).toBe(4); expect(report.snapshots.asset.revision).toBe(2); expect(report.snapshots.modifier.dirty).toBe(false); expect(report.snapshots.mesh.dirty).toBe(false); expect(report.snapshots.asset.dirty).toBe(false);
|
||||
});
|
||||
21
web/tests/e2e/corrective-performance-security.spec.ts
Normal file
21
web/tests/e2e/corrective-performance-security.spec.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const evidenceRoot = path.resolve(import.meta.dirname, "../../../tests/golden/corrective/C6-002");
|
||||
|
||||
test("C6-002 Chromium performance and security boundaries stay within budget", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
const report = await page.evaluate(async () => {
|
||||
const { AssetCatalogResourceResolver, InMemoryMainStore, createAssetCatalogRegistry, createModifierMain, createModifierRegistry } = await import("/src/corrective-pilot-bridge.ts");
|
||||
const fixture = [{ uuid: "modifier:security", name: "Security Bevel", type: "BEVEL", enabled: false, showViewport: true, showRender: true }];
|
||||
const modifierCommand = (overrides = {}) => ({ schemaVersion: 1, requestId: "security-modifier-001", commandType: "modifierSetEnabled", baseRevision: 0, context: { mainId: "main:security", targetKind: "MODIFIER", targetId: "modifier:security", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "LOCAL", sha256: "2".repeat(64) } }, payload: { modifierUuid: "modifier:security", enabled: true }, ...overrides });
|
||||
const samples = []; for (let index = 0; index < 50; index += 1) { const main = createModifierMain(fixture, 0, false); const start = performance.now(); const receipt = await createModifierRegistry(main).dispatch("WASM", { command: modifierCommand({ requestId: `security-sample-${index}` }), mainRevision: 0 }); samples.push({ durationMs: performance.now() - start, status: receipt.result.status, revision: main.snapshot().revision }); }
|
||||
const replayMain = createModifierMain(fixture, 0, false); const replayRegistry = createModifierRegistry(replayMain); const replayCommand = modifierCommand(); const first = await replayRegistry.dispatch("DESKTOP", { command: replayCommand, mainRevision: 0 }); const replay = await replayRegistry.dispatch("DESKTOP", { command: replayCommand, mainRevision: 1 });
|
||||
const malformedMain = createModifierMain(fixture, 0, false); const malformed = await createModifierRegistry(malformedMain).dispatch("WASM", { command: modifierCommand({ payload: { modifierUuid: "modifier:security", enabled: true, extra: "x".repeat(4096) } }), mainRevision: 0 });
|
||||
const assetMain = new InMemoryMainStore({ entries: [] }, 0, false, (value) => ({ entries: value.entries.map((entry) => ({ ...entry })) })); const resolver = new AssetCatalogResourceResolver(); resolver.setActiveLibraryContext({ libraryId: "library:security", sourceKind: "EXTERNAL", sourceId: "library.blend", generation: 1, revision: 0, readOnly: false }); const pathCommand = { schemaVersion: 1, requestId: "security-path-001", commandType: "assetCatalogAppend", baseRevision: 0, context: { mainId: "main:asset-security", targetKind: "ASSET_LIBRARY", targetId: "library:security", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "EXTERNAL", sha256: "3".repeat(64) }, resourceProvider: "EXTERNAL_LIBRARY" }, payload: { id: "asset:escape", name: "Escape", resource: { schemaVersion: 1, requestId: "security-resource", sourceKind: "EXTERNAL", sourceId: "../escape.blend", sha256: "3".repeat(64) } } }; const pathResult = await createAssetCatalogRegistry(assetMain, resolver).dispatch("WASM", { command: pathCommand, mainRevision: 0 });
|
||||
const durations = samples.map((sample) => sample.durationMs).sort((a, b) => a - b); return { sampleCount: samples.length, latencyMs: { p50: durations[Math.floor(durations.length * 0.5)], p95: durations[Math.floor(durations.length * 0.95)], max: durations.at(-1) }, samples, security: { replay: replay.result, first: first.result, malformed: malformed.result, path: pathResult.result, snapshots: { replay: replayMain.snapshot(), malformed: malformedMain.snapshot(), path: assetMain.snapshot() } }, budgets: { p95Ms: 100, maxMs: 250, maxSamples: 50 }, withinBudget: durations[Math.floor(durations.length * 0.95)] < 100 && durations.at(-1) < 250 };
|
||||
});
|
||||
fs.mkdirSync(evidenceRoot, { recursive: true }); fs.writeFileSync(path.join(evidenceRoot, process.env.C4_PILOT_REPORT ?? "performance-security-report.json"), `${JSON.stringify({ schemaVersion: 1, task: "C6-002", operation: "CORRECTIVE_PERFORMANCE_SECURITY_CHROMIUM", browser: "chromium", queueMutation: false, ...report }, null, 2)}\n`);
|
||||
expect(report.sampleCount).toBe(50); expect(report.withinBudget).toBe(true); expect(report.security.first.status).toBe("FINISHED"); expect(report.security.replay.code).toBe("REVISION_CONFLICT"); expect(report.security.replay.mainMutation).toBe("UNCHANGED"); expect(report.security.malformed.code).toBe("COMMAND_MALFORMED"); expect(report.security.malformed.mainMutation).toBe("UNCHANGED"); expect(report.security.path.mainMutation).toBe("UNCHANGED"); expect(report.security.snapshots.replay.revision).toBe(1); expect(report.security.snapshots.malformed.revision).toBe(0); expect(report.security.snapshots.path.revision).toBe(0); expect(report.security.snapshots.replay.dirty).toBe(true); expect(report.security.snapshots.malformed.dirty).toBe(false); expect(report.security.snapshots.path.dirty).toBe(false);
|
||||
});
|
||||
18
web/tests/e2e/corrective-workflow-gate.spec.ts
Normal file
18
web/tests/e2e/corrective-workflow-gate.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const evidenceRoot = path.resolve(import.meta.dirname, "../../../tests/golden/corrective/C6-001");
|
||||
|
||||
test("C6-001 Chromium open/edit/undo/redo/save/reopen workflow is stable", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
const report = await page.evaluate(async () => {
|
||||
const { CorrectiveHistoryStore, createModifierRegistry } = await import("/src/corrective-pilot-bridge.ts");
|
||||
const fixture = [{ uuid: "modifier:workflow", name: "Workflow Bevel", type: "BEVEL", enabled: false, showViewport: true, showRender: true }]; const clone = (value) => ({ modifiers: value.modifiers.map((modifier) => ({ ...modifier })) }); const history = new CorrectiveHistoryStore({ modifiers: fixture }, 0, false, clone);
|
||||
const command = { schemaVersion: 1, requestId: "chromium-workflow-001", commandType: "modifierSetEnabled", baseRevision: 0, context: { mainId: "main:workflow", targetKind: "MODIFIER", targetId: "modifier:workflow", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "LOCAL", sha256: "1".repeat(64) } }, payload: { modifierUuid: "modifier:workflow", enabled: true } };
|
||||
const opened = history.snapshot(); const editedReceipt = await createModifierRegistry(history).dispatch("DESKTOP", { command, mainRevision: 0 }); const edited = history.snapshot(); const saved = history.save(); const undone = history.undo(); const redone = history.redo(); const reopened = history.reopen();
|
||||
return { opened, editedReceipt: editedReceipt.result, edited, saved, undone, redone, reopened, final: history.snapshot() };
|
||||
});
|
||||
fs.mkdirSync(evidenceRoot, { recursive: true }); fs.writeFileSync(path.join(evidenceRoot, process.env.C4_PILOT_REPORT ?? "workflow-report.json"), `${JSON.stringify({ schemaVersion: 1, task: "C6-001", operation: "CORRECTIVE_CHROMIUM_WORKFLOW_GATE", browser: "chromium", queueMutation: false, ...report }, null, 2)}\n`);
|
||||
expect(report.opened).toEqual({ value: { modifiers: [{ uuid: "modifier:workflow", name: "Workflow Bevel", type: "BEVEL", enabled: false, showViewport: true, showRender: true }] }, revision: 0, dirty: false }); expect(report.editedReceipt.status).toBe("FINISHED"); expect(report.edited.revision).toBe(1); expect(report.edited.dirty).toBe(true); expect(report.edited.value.modifiers[0].enabled).toBe(true); expect(report.saved.revision).toBe(1); expect(report.saved.dirty).toBe(false); expect(report.undone.revision).toBe(0); expect(report.undone.value.modifiers[0].enabled).toBe(false); expect(report.redone.revision).toBe(1); expect(report.redone.value.modifiers[0].enabled).toBe(true); expect(report.reopened.value.modifiers[0].enabled).toBe(true); expect(report.reopened.dirty).toBe(false); expect(report.final).toEqual(report.reopened);
|
||||
});
|
||||
Reference in New Issue
Block a user