Skip to content

Commit 4864d1b

Browse files
author
DavidQ
committed
Create Object Vector Studio V2 schema contract from consolidated vector tools and enforce schema-gated loading - PR_26132_008-object-vector-studio-v2-schema-contract
1 parent 7090569 commit 4864d1b

7 files changed

Lines changed: 1049 additions & 174 deletions

File tree

docs/dev/reports/playwright_v8_coverage.txt

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ Exercised tool entry points detected:
2020
(0%) Workspace Manager - not exercised by this Playwright run
2121

2222
Changed runtime JS files covered:
23-
(88%) tools/object-vector-studio-v2/js/ToolStarterApp.js - executed lines 1476/1476; executed functions 159/181
24-
(94%) tools/object-vector-studio-v2/js/services/ObjectVectorStudioV2SchemaService.js - executed lines 196/196; executed functions 15/16
25-
(100%) tools/object-vector-studio-v2/js/bootstrap.js - executed lines 68/68; executed functions 4/4
23+
(80%) tools/object-vector-studio-v2/js/bootstrap.js - executed lines 70/70; executed functions 4/5
24+
(89%) tools/object-vector-studio-v2/js/ToolStarterApp.js - executed lines 1541/1541; executed functions 166/187
25+
(94%) tools/object-vector-studio-v2/js/services/ObjectVectorStudioV2SchemaService.js - executed lines 249/249; executed functions 31/33
2626

2727
Files with executed line/function counts where available:
2828
(2%) src/engine/input/ActionInputService.js - executed lines 397/397; executed functions 1/51
@@ -173,6 +173,7 @@ Files with executed line/function counts where available:
173173
(80%) src/engine/persistence/StorageService.js - executed lines 49/49; executed functions 4/5
174174
(80%) tools/asset-manager-v2/js/controls/AccordionSection.js - executed lines 27/27; executed functions 4/5
175175
(80%) tools/asset-manager-v2/js/controls/AssetFormControl.js - executed lines 563/563; executed functions 49/61
176+
(80%) tools/object-vector-studio-v2/js/bootstrap.js - executed lines 70/70; executed functions 4/5
176177
(80%) tools/palette-manager-v2/modules/PaletteHistoryStack.js - executed lines 54/54; executed functions 8/10
177178
(80%) tools/preview-generator-v2/controls/AccordionSection.js - executed lines 31/31; executed functions 4/5
178179
(80%) tools/preview-generator-v2/PreviewGeneratorV2Logger.js - executed lines 19/19; executed functions 4/5
@@ -189,12 +190,12 @@ Files with executed line/function counts where available:
189190
(86%) tools/workspace-manager-v2/js/controls/RepoDestinationControl.js - executed lines 25/25; executed functions 6/7
190191
(86%) tools/workspace-manager-v2/js/WorkspaceManagerV2App.js - executed lines 945/945; executed functions 42/49
191192
(88%) games/Pong/game/PongInputController.js - executed lines 77/77; executed functions 7/8
192-
(88%) tools/object-vector-studio-v2/js/ToolStarterApp.js - executed lines 1476/1476; executed functions 159/181
193193
(88%) tools/preview-generator-v2/PreviewGeneratorV2App.js - executed lines 1498/1498; executed functions 107/121
194194
(88%) tools/shared/toolLaunchSSoTData.js - executed lines 112/112; executed functions 14/16
195195
(88%) tools/text2speech-V2/js/controls/TextInputControl.js - executed lines 24/24; executed functions 7/8
196196
(88%) tools/world-vector-studio-v2/js/controls/SourceInputControl.js - executed lines 33/33; executed functions 7/8
197197
(89%) tools/asset-manager-v2/js/services/AssetSchemaValidator.js - executed lines 295/295; executed functions 25/28
198+
(89%) tools/object-vector-studio-v2/js/ToolStarterApp.js - executed lines 1541/1541; executed functions 166/187
198199
(89%) tools/preview-generator-v2/controls/StatusLogControl.js - executed lines 32/32; executed functions 8/9
199200
(90%) tools/palette-manager-v2/modules/PaletteValidationService.js - executed lines 88/88; executed functions 9/10
200201
(90%) tools/text2speech-V2/js/controls/ActionNavControl.js - executed lines 117/117; executed functions 19/21
@@ -211,7 +212,7 @@ Files with executed line/function counts where available:
211212
(93%) tools/workspace-manager-v2/js/controls/ToolTilesControl.js - executed lines 130/130; executed functions 14/15
212213
(94%) games/shared/workspaceGameMetadataHydrator.js - executed lines 106/106; executed functions 16/17
213214
(94%) tools/common/PaletteSortService.js - executed lines 103/103; executed functions 17/18
214-
(94%) tools/object-vector-studio-v2/js/services/ObjectVectorStudioV2SchemaService.js - executed lines 196/196; executed functions 15/16
215+
(94%) tools/object-vector-studio-v2/js/services/ObjectVectorStudioV2SchemaService.js - executed lines 249/249; executed functions 31/33
215216
(95%) tools/session-inspector-v2/js/services/SessionInspectorV2StorageService.js - executed lines 142/142; executed functions 18/19
216217
(100%) games/Asteroids/flow/attract.js - executed lines 17/17; executed functions 1/1
217218
(100%) games/Asteroids/flow/highscore.js - executed lines 16/16; executed functions 1/1
@@ -253,7 +254,6 @@ Files with executed line/function counts where available:
253254
(100%) src/shared/utils/textWrapUtils.js - executed lines 34/34; executed functions 4/4
254255
(100%) tools/asset-manager-v2/js/bootstrap.js - executed lines 70/70; executed functions 4/4
255256
(100%) tools/asset-manager-v2/js/controls/InspectorControl.js - executed lines 8/8; executed functions 3/3
256-
(100%) tools/object-vector-studio-v2/js/bootstrap.js - executed lines 68/68; executed functions 4/4
257257
(100%) tools/object-vector-studio-v2/js/controls/AccordionSection.js - executed lines 27/27; executed functions 5/5
258258
(100%) tools/preview-generator-v2/controls/AssetFolderControl.js - executed lines 20/20; executed functions 6/6
259259
(100%) tools/preview-generator-v2/controls/CaptureModeControl.js - executed lines 25/25; executed functions 9/9
@@ -293,7 +293,6 @@ Uncovered or low-coverage changed JS files:
293293

294294
Changed JS files considered:
295295
(0%) tests/playwright/tools/WorkspaceManagerV2.spec.mjs - changed JS file not collected as browser runtime coverage
296-
(0%) tools/object-vector-studio-v2/tests/playwright/FirstClassToolStarter.spec.mjs - changed JS file not collected as browser runtime coverage
297-
(88%) tools/object-vector-studio-v2/js/ToolStarterApp.js - changed JS file with browser V8 coverage
296+
(80%) tools/object-vector-studio-v2/js/bootstrap.js - changed JS file with browser V8 coverage
297+
(89%) tools/object-vector-studio-v2/js/ToolStarterApp.js - changed JS file with browser V8 coverage
298298
(94%) tools/object-vector-studio-v2/js/services/ObjectVectorStudioV2SchemaService.js - changed JS file with browser V8 coverage
299-
(100%) tools/object-vector-studio-v2/js/bootstrap.js - changed JS file with browser V8 coverage
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# PR_26132_008-object-vector-studio-v2-schema-contract
2+
3+
## Purpose
4+
5+
Create the Object Vector Studio V2 JSON Schema contract and make it the runtime acceptance gate.
6+
7+
## Scope
8+
9+
- Added `tools/schemas/tools/object-vector-studio-v2.schema.json`.
10+
- Derived the schema shape from SVG Asset Studio palette/vector authoring state and Vector Map Editor object, point, style, and transform document contracts.
11+
- Schema covers Object Vector Studio V2 root payloads, palette swatches, objects, shapes, transform data, selection state, viewport state, and JSON export metadata.
12+
- Root payloads now reject unknown root properties.
13+
- Object/shape payloads are rejected before render through schema validation.
14+
- Workspace/session launches require a palette-backed payload before render.
15+
- Import, Copy JSON, and Export JSON flows validate against the schema contract.
16+
- Runtime now loads the schema file and uses the schema service as the only payload acceptance gate.
17+
- Did not modify World Vector Studio V2 or deprecated SVG Asset Studio, Primitive Skin Editor, or Vector Map Editor.
18+
19+
## Validation
20+
21+
Playwright impacted: Yes.
22+
23+
Command run:
24+
25+
```powershell
26+
npm run test:workspace-v2
27+
```
28+
29+
Result:
30+
31+
```text
32+
39 passed
33+
```
34+
35+
Additional checks:
36+
37+
```powershell
38+
node --check tools/object-vector-studio-v2/js/services/ObjectVectorStudioV2SchemaService.js
39+
node --check tools/object-vector-studio-v2/js/ToolStarterApp.js
40+
node --check tools/object-vector-studio-v2/js/bootstrap.js
41+
node --check tests/playwright/tools/WorkspaceManagerV2.spec.mjs
42+
node -e "JSON.parse(require('fs').readFileSync('tools/schemas/tools/object-vector-studio-v2.schema.json','utf8')); console.log('schema json ok')"
43+
```
44+
45+
All checks passed.
46+
47+
## Playwright Coverage
48+
49+
The Workspace Manager V2 suite now validates:
50+
51+
- Valid Object Vector Studio V2 schema payload import and render.
52+
- Unknown root property rejection.
53+
- Invalid shape payload rejection through schema validation before render.
54+
- Missing palette rejection from workspace/session launch.
55+
- Copy JSON writes a schema-valid Object Vector Studio V2 payload.
56+
- Export JSON downloads a schema-valid Object Vector Studio V2 payload.
57+
58+
Expected pass behavior:
59+
60+
- Valid payloads with palette, objects, and schema-valid shapes load and render.
61+
- Copy and export payloads validate against the Object Vector Studio V2 schema.
62+
63+
Expected fail behavior:
64+
65+
- Unknown root properties, missing workspace/session palette, and invalid shape payloads log `FAIL` and do not partially render.
66+
67+
## V8 Coverage
68+
69+
Required V8 coverage reports:
70+
71+
```text
72+
docs/dev/reports/playwright_v8_coverage_report.txt
73+
docs/dev/reports/playwright_v8_coverage.txt
74+
docs/dev/reports/coverage_changed_js_guardrail.txt
75+
```
76+
77+
Changed runtime JavaScript coverage includes:
78+
79+
```text
80+
(80%) tools/object-vector-studio-v2/js/bootstrap.js
81+
(89%) tools/object-vector-studio-v2/js/ToolStarterApp.js
82+
(94%) tools/object-vector-studio-v2/js/services/ObjectVectorStudioV2SchemaService.js
83+
```
84+
85+
The coverage guardrail reported no changed-runtime-JS warnings.
86+
87+
## Full Samples Smoke Test
88+
89+
Skipped. This PR is limited to Object Vector Studio V2 schema/runtime gate behavior and targeted Workspace Manager V2 Playwright coverage. It does not change shared sample loading or broad sample runtime behavior.
90+
91+
## Manual Test Steps
92+
93+
1. Open `tools/object-vector-studio-v2/index.html`.
94+
2. Confirm Status Log reports the schema contract loaded.
95+
3. Import a valid payload with `palette.swatches` and `objects[]`; confirm object tiles render.
96+
4. Import a payload with an unexpected root property; confirm it is rejected and nothing partially renders.
97+
5. Launch with workspace/session payload missing `palette`; confirm it is rejected.
98+
6. After loading a valid payload, use Copy JSON and Export JSON and validate the output against `object-vector-studio-v2.schema.json`.
99+
100+
## Out Of Scope
101+
102+
- World Vector Studio V2 changes.
103+
- Deprecated SVG Asset Studio, Primitive Skin Editor, or Vector Map Editor runtime changes.
104+
- Workspace manifest write-back for Object Vector Studio V2.
105+
- Full samples smoke test.

tests/playwright/tools/WorkspaceManagerV2.spec.mjs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1173,6 +1173,7 @@ test.describe("Workspace Manager V2 bootstrap", () => {
11731173
await page.goto(`${server.baseUrl}/tools/object-vector-studio-v2/index.html`, { waitUntil: "networkidle" });
11741174
await expect(page.locator("body.tools-platform-tool-page[data-tool-id='object-vector-studio-v2']")).toBeVisible();
11751175
await expect(page.locator("[data-tool-starter-header]")).toContainText("Object Vector Studio V2");
1176+
await expect(page.locator("#statusLog")).toHaveValue(/OK Object Vector Studio V2 schema contract loaded from \/tools\/schemas\/tools\/object-vector-studio-v2\.schema\.json\./);
11761177
await expect(page.locator('[data-launch-mode-nav="tool"]')).toBeVisible();
11771178
await expect(page.locator('[data-launch-mode-nav="tool"] button')).toHaveText(["Import", "Copy JSON", "Export"]);
11781179
await expect(page.locator('[data-launch-mode-nav="workspace"]')).toBeHidden();
@@ -1210,6 +1211,21 @@ test.describe("Workspace Manager V2 bootstrap", () => {
12101211
await expect(page.locator("#objectVectorStudioV2ObjectTiles")).toContainText("No objects loaded");
12111212
await expect(page.locator("#objectVectorStudioV2JsonDetails")).toHaveText("{}");
12121213

1214+
const unknownRootPayloadPath = testInfo.outputPath("object-vector-unknown-root.json");
1215+
await writeFile(unknownRootPayloadPath, JSON.stringify({
1216+
palette: {
1217+
id: "arcade-primary",
1218+
swatches: [
1219+
{ id: "white", value: "#ffffff" }
1220+
]
1221+
},
1222+
objects: [],
1223+
unexpected: true
1224+
}, null, 2), "utf8");
1225+
await page.locator("#objectVectorStudioV2ImportJsonInput").setInputFiles(unknownRootPayloadPath);
1226+
await expect(page.locator("#statusLog")).toHaveValue(/FAIL Object Vector Studio V2 schema validation failed from import:object-vector-unknown-root\.json: root\.unexpected is not allowed\./);
1227+
await expect(page.locator("#objectVectorStudioV2JsonDetails")).toHaveText("{}");
1228+
12131229
const invalidShapePayloadPath = testInfo.outputPath("object-vector-invalid-shape.json");
12141230
await writeFile(invalidShapePayloadPath, JSON.stringify({
12151231
palette: {
@@ -1238,7 +1254,7 @@ test.describe("Workspace Manager V2 bootstrap", () => {
12381254
]
12391255
}, null, 2), "utf8");
12401256
await page.locator("#objectVectorStudioV2ImportJsonInput").setInputFiles(invalidShapePayloadPath);
1241-
await expect(page.locator("#statusLog")).toHaveValue(/FAIL Object Vector Studio V2 schema validation failed from import:object-vector-invalid-shape\.json: root\.objects\[0\]\.shapes\[0\]\.type must be one of rectangle, circle, ellipse, line, polygon, arc, text\./);
1257+
await expect(page.locator("#statusLog")).toHaveValue(/FAIL Object Vector Studio V2 schema validation failed from import:object-vector-invalid-shape\.json: root\.objects\[0\]\.shapes\[0\] must match exactly one Object Vector Studio V2 shape schema\./);
12421258
await expect(page.locator("#objectVectorStudioV2ObjectTiles")).toContainText("No objects loaded");
12431259
await expect(page.locator("#objectVectorStudioV2JsonDetails")).toHaveText("{}");
12441260

@@ -1374,6 +1390,35 @@ test.describe("Workspace Manager V2 bootstrap", () => {
13741390
await expect(page.locator("#objectVectorStudioV2RenderSurface")).toHaveAttribute("viewBox", "0 0 320 220");
13751391
await expect(page.locator("#statusLog")).toHaveValue(/OK Viewport reset to 100% at origin\./);
13761392

1393+
await page.evaluate(() => {
1394+
Object.defineProperty(navigator, "clipboard", {
1395+
configurable: true,
1396+
value: {
1397+
async writeText(text) {
1398+
sessionStorage.setItem("object-vector-studio-v2.copied-json", text);
1399+
}
1400+
}
1401+
});
1402+
});
1403+
await page.locator("#objectVectorStudioV2CopyJsonButton").click();
1404+
const copiedPayload = await page.evaluate(() => JSON.parse(sessionStorage.getItem("object-vector-studio-v2.copied-json")));
1405+
expect(copiedPayload.selection.selectedObjectId).toBe("object-1");
1406+
expect(copiedPayload.selection.selectedShapeId).toBe("rectangle-1");
1407+
expect(copiedPayload.viewport.zoom).toBe(1);
1408+
expect(copiedPayload.export.format).toBe("json");
1409+
const copiedSchemaValidation = await page.evaluate((payload) => window.__objectVectorStudioV2App.schemaService.validatePayload(payload), copiedPayload);
1410+
expect(copiedSchemaValidation).toEqual({ errors: [], ok: true, payload: copiedPayload });
1411+
1412+
const downloadPromise = page.waitForEvent("download");
1413+
await page.locator("#objectVectorStudioV2ExportJsonButton").click();
1414+
const download = await downloadPromise;
1415+
const exportPath = testInfo.outputPath("object-vector-export.json");
1416+
await download.saveAs(exportPath);
1417+
const exportedPayload = JSON.parse(await readFile(exportPath, "utf8"));
1418+
expect(exportedPayload.selection.selectedShapeIds).toContain("rectangle-1");
1419+
const exportedSchemaValidation = await page.evaluate((payload) => window.__objectVectorStudioV2App.schemaService.validatePayload(payload), exportedPayload);
1420+
expect(exportedSchemaValidation).toEqual({ errors: [], ok: true, payload: exportedPayload });
1421+
13771422
await page.locator('[data-object-id="object-2"]').click();
13781423
await expect(page.locator('[data-object-id="object-2"]')).toHaveAttribute("aria-pressed", "true");
13791424
await expect(page.locator("#objectVectorStudioV2ObjectDetails")).toContainText("Object 2");
@@ -1465,6 +1510,14 @@ test.describe("Workspace Manager V2 bootstrap", () => {
14651510
expect(fullscreenLayout.centerWidth).toBeGreaterThan(300);
14661511
expect(fullscreenLayout.centerHeight).toBeGreaterThan(300);
14671512

1513+
await page.evaluate(() => {
1514+
sessionStorage.setItem("workspace.tools.object-vector-studio-v2", JSON.stringify({ objects: [] }));
1515+
});
1516+
await page.goto(`${server.baseUrl}/tools/object-vector-studio-v2/index.html?launch=workspace&fromTool=workspace-manager-v2&hostContextId=object-vector-v2-missing-palette&workspaceMode=uat`, { waitUntil: "networkidle" });
1517+
await expect(page.locator("#statusLog")).toHaveValue(/FAIL Object Vector Studio V2 schema validation failed from workspace\.tools\.object-vector-studio-v2: root\.palette is required\./);
1518+
await page.evaluate(() => {
1519+
sessionStorage.removeItem("workspace.tools.object-vector-studio-v2");
1520+
});
14681521
await page.goto(`${server.baseUrl}/tools/object-vector-studio-v2/index.html?launch=workspace&fromTool=workspace-manager-v2&hostContextId=object-vector-v2-shell&workspaceMode=uat`, { waitUntil: "networkidle" });
14691522
await expect(page.locator('[data-launch-mode-nav="tool"]')).toBeHidden();
14701523
await expect(page.locator('[data-launch-mode-nav="workspace"] button')).toHaveText(["Return to Workspace"]);

0 commit comments

Comments
 (0)