Skip to content

Commit 56571f0

Browse files
author
DavidQ
committed
Fix storage cookies preview output workspace dirty state and Object Vector future shapes - PR_26133_098-storage-preview-workspace-and-object-vector-fix-batch
1 parent 191ae84 commit 56571f0

15 files changed

Lines changed: 481 additions & 80 deletions

File tree

docs/dev/reports/playwright_v8_coverage_report.md

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,14 @@ Exercised tool entry points detected:
2323
(0%) Workspace Manager - not exercised by this Playwright run
2424
2525
Changed runtime JS files covered:
26-
(94%) tools/object-vector-studio-v2/js/ToolStarterApp.js - executed lines 8334/8334; executed functions 818/866
26+
(86%) src/engine/runtime/fullscreenBezel.js - executed lines 1042/1042; executed functions 62/72
27+
(86%) tools/workspace-manager-v2/js/WorkspaceManagerV2App.js - executed lines 963/963; executed functions 42/49
28+
(88%) tools/preview-generator-v2/PreviewGeneratorV2App.js - executed lines 1500/1500; executed functions 107/121
29+
(92%) src/engine/runtime/gameImageConvention.js - executed lines 233/233; executed functions 23/25
30+
(95%) tools/object-vector-studio-v2/js/ToolStarterApp.js - executed lines 8380/8380; executed functions 826/874
31+
(98%) tools/storage-inspector-v2/js/StorageInspectorV2App.js - executed lines 348/348; executed functions 52/53
32+
(100%) tools/storage-inspector-v2/js/controls/FilterControl.js - executed lines 35/35; executed functions 9/9
33+
(100%) tools/storage-inspector-v2/js/services/StorageInspectorV2StorageService.js - executed lines 259/259; executed functions 39/39
2734
2835
Files with executed line/function counts where available:
2936
(2%) src/engine/input/ActionInputService.js - executed lines 397/397; executed functions 1/51
@@ -98,9 +105,7 @@ Files with executed line/function counts where available:
98105
(43%) games/Asteroids/systems/AsteroidsInitialsEntry.js - executed lines 71/71; executed functions 3/7
99106
(43%) games/Pong/game/PongAudio.js - executed lines 57/57; executed functions 3/7
100107
(44%) games/Asteroids/systems/ShipDebrisSystem.js - executed lines 84/84; executed functions 4/9
101-
(44%) src/engine/runtime/fullscreenBezel.js - executed lines 1034/1034; executed functions 29/66
102108
(47%) src/engine/input/InputService.js - executed lines 185/185; executed functions 14/30
103-
(47%) src/engine/runtime/backgroundImage.js - executed lines 205/205; executed functions 8/17
104109
(47%) src/engine/runtime/RuntimeMonitoringHooks.js - executed lines 191/191; executed functions 8/17
105110
(50%) games/Asteroids/index.js - executed lines 211/211; executed functions 6/12
106111
(50%) src/engine/camera/ZoneCameraSystem.js - executed lines 26/26; executed functions 1/2
@@ -146,12 +151,12 @@ Files with executed line/function counts where available:
146151
(68%) tools/palette-manager-v2/controls/UserPaletteControl.js - executed lines 95/95; executed functions 13/19
147152
(70%) games/Asteroids/systems/AsteroidsHighScoreService.js - executed lines 73/73; executed functions 7/10
148153
(71%) src/engine/input/KeyboardState.js - executed lines 34/34; executed functions 5/7
154+
(71%) src/engine/runtime/backgroundImage.js - executed lines 205/205; executed functions 12/17
149155
(71%) src/engine/runtime/FullscreenService.js - executed lines 123/123; executed functions 10/14
150156
(71%) src/shared/utils/debugConfigUtils.js - executed lines 89/89; executed functions 5/7
151157
(71%) tools/asset-manager-v2/js/assetPreviewHelpers.js - executed lines 156/156; executed functions 10/14
152158
(71%) tools/palette-manager-v2/controls/PaletteValidationErrorControl.js - executed lines 30/30; executed functions 5/7
153159
(71%) tools/world-vector-studio-v2/js/controls/ActionNavControl.js - executed lines 76/76; executed functions 5/7
154-
(73%) src/engine/runtime/gameImageConvention.js - executed lines 207/207; executed functions 16/22
155160
(73%) src/engine/theme/mount-shared-header.js - executed lines 143/143; executed functions 8/11
156161
(75%) games/Pong/game/PongModeConfig.js - executed lines 88/88; executed functions 3/4
157162
(75%) games/shared/workspaceGameRuntimeContext.js - executed lines 58/58; executed functions 3/4
@@ -175,34 +180,35 @@ Files with executed line/function counts where available:
175180
(80%) tools/workspace-manager-v2/js/controls/AccordionSection.js - executed lines 27/27; executed functions 4/5
176181
(80%) tools/world-vector-studio-v2/js/controls/AccordionSection.js - executed lines 27/27; executed functions 4/5
177182
(81%) games/Asteroids/game/asteroidsObjectVectorRoles.js - executed lines 174/174; executed functions 13/16
178-
(82%) src/engine/rendering/CanvasRenderer.js - executed lines 100/100; executed functions 9/11
179183
(82%) tools/storage-inspector-v2/js/controls/EntryListControl.js - executed lines 59/59; executed functions 9/11
180184
(83%) games/Asteroids/entities/Asteroid.js - executed lines 61/61; executed functions 5/6
181185
(83%) tools/object-vector-studio-v2/js/bootstrap.js - executed lines 110/110; executed functions 5/6
182186
(83%) tools/palette-manager-v2/main.js - executed lines 227/227; executed functions 15/18
183187
(83%) tools/storage-inspector-v2/js/controls/AccordionSection.js - executed lines 41/41; executed functions 5/6
188+
(85%) src/engine/audio/GaplessLoopPlayer.js - executed lines 187/187; executed functions 17/20
184189
(86%) games/Asteroids/systems/AsteroidsAudio.js - executed lines 134/134; executed functions 12/14
185190
(86%) games/shared/gameSkinLoader.js - executed lines 352/352; executed functions 18/21
186191
(86%) src/engine/audio/WebAudioToneBackend.js - executed lines 65/65; executed functions 6/7
192+
(86%) src/engine/runtime/fullscreenBezel.js - executed lines 1042/1042; executed functions 62/72
187193
(86%) tools/asset-manager-v2/js/controls/AssetCatalogControl.js - executed lines 134/134; executed functions 12/14
188194
(86%) tools/workspace-manager-v2/js/controls/RepoDestinationControl.js - executed lines 25/25; executed functions 6/7
189195
(86%) tools/workspace-manager-v2/js/WorkspaceManagerV2App.js - executed lines 963/963; executed functions 42/49
190196
(88%) games/Pong/game/PongInputController.js - executed lines 77/77; executed functions 7/8
191197
(88%) games/shared/workspaceGameAssetCatalog.js - executed lines 313/313; executed functions 23/26
192-
(88%) tools/preview-generator-v2/PreviewGeneratorV2App.js - executed lines 1498/1498; executed functions 107/121
198+
(88%) tools/preview-generator-v2/PreviewGeneratorV2App.js - executed lines 1500/1500; executed functions 107/121
193199
(88%) tools/shared/toolLaunchSSoTData.js - executed lines 112/112; executed functions 14/16
194200
(88%) tools/text2speech-V2/js/controls/TextInputControl.js - executed lines 24/24; executed functions 7/8
195201
(88%) tools/world-vector-studio-v2/js/controls/SourceInputControl.js - executed lines 33/33; executed functions 7/8
196202
(89%) games/Asteroids/game/asteroidObjectGeometry.js - executed lines 82/82; executed functions 16/18
197203
(89%) tools/asset-manager-v2/js/services/AssetSchemaValidator.js - executed lines 295/295; executed functions 25/28
198204
(89%) tools/preview-generator-v2/controls/StatusLogControl.js - executed lines 32/32; executed functions 8/9
199-
(89%) tools/storage-inspector-v2/js/controls/FilterControl.js - executed lines 34/34; executed functions 8/9
200-
(90%) src/engine/audio/GaplessLoopPlayer.js - executed lines 187/187; executed functions 18/20
201205
(90%) tools/palette-manager-v2/modules/PaletteValidationService.js - executed lines 88/88; executed functions 9/10
202206
(90%) tools/text2speech-V2/js/controls/ActionNavControl.js - executed lines 117/117; executed functions 19/21
203207
(90%) tools/text2speech-V2/js/TextToSpeechToolApp.js - executed lines 807/807; executed functions 62/69
208+
(91%) src/engine/rendering/CanvasRenderer.js - executed lines 100/100; executed functions 10/11
204209
(91%) tools/object-vector-studio-v2/js/controls/ActionNavControl.js - executed lines 78/78; executed functions 10/11
205210
(91%) tools/toolRegistry.js - executed lines 526/526; executed functions 10/11
211+
(92%) src/engine/runtime/gameImageConvention.js - executed lines 233/233; executed functions 23/25
206212
(92%) tools/object-vector-studio-v2/js/controls/ToolStarterShellControl.js - executed lines 112/112; executed functions 11/12
207213
(92%) tools/workspace-manager-v2/js/services/WorkspaceManagerV2ContextService.js - executed lines 1662/1662; executed functions 149/162
208214
(93%) tools/asset-manager-v2/js/services/WorkspaceBridge.js - executed lines 305/305; executed functions 25/27
@@ -212,9 +218,9 @@ Files with executed line/function counts where available:
212218
(94%) games/shared/workspaceGameMetadataHydrator.js - executed lines 106/106; executed functions 16/17
213219
(94%) src/engine/rendering/ObjectVectorRuntimeAssetService.js - executed lines 1136/1136; executed functions 111/118
214220
(94%) tools/common/PaletteSortService.js - executed lines 103/103; executed functions 17/18
215-
(94%) tools/object-vector-studio-v2/js/ToolStarterApp.js - executed lines 8334/8334; executed functions 818/866
216221
(95%) tools/object-vector-studio-v2/js/services/ObjectVectorStudioV2SchemaService.js - executed lines 458/458; executed functions 56/59
217-
(98%) tools/storage-inspector-v2/js/StorageInspectorV2App.js - executed lines 347/347; executed functions 51/52
222+
(95%) tools/object-vector-studio-v2/js/ToolStarterApp.js - executed lines 8380/8380; executed functions 826/874
223+
(98%) tools/storage-inspector-v2/js/StorageInspectorV2App.js - executed lines 348/348; executed functions 52/53
218224
(100%) games/Asteroids/flow/attract.js - executed lines 17/17; executed functions 1/1
219225
(100%) games/Asteroids/flow/highscore.js - executed lines 16/16; executed functions 1/1
220226
(100%) games/Asteroids/flow/intro.js - executed lines 18/18; executed functions 1/1
@@ -275,10 +281,11 @@ Files with executed line/function counts where available:
275281
(100%) tools/storage-inspector-v2/js/bootstrap.js - executed lines 55/55; executed functions 4/4
276282
(100%) tools/storage-inspector-v2/js/controls/DataControl.js - executed lines 23/23; executed functions 5/5
277283
(100%) tools/storage-inspector-v2/js/controls/DirtyControl.js - executed lines 30/30; executed functions 6/6
284+
(100%) tools/storage-inspector-v2/js/controls/FilterControl.js - executed lines 35/35; executed functions 9/9
278285
(100%) tools/storage-inspector-v2/js/controls/JsonControl.js - executed lines 19/19; executed functions 5/5
279286
(100%) tools/storage-inspector-v2/js/controls/StatusLogControl.js - executed lines 32/32; executed functions 10/10
280287
(100%) tools/storage-inspector-v2/js/services/StorageInspectorV2RuntimeContract.js - executed lines 10/10; executed functions 2/2
281-
(100%) tools/storage-inspector-v2/js/services/StorageInspectorV2StorageService.js - executed lines 184/184; executed functions 29/29
288+
(100%) tools/storage-inspector-v2/js/services/StorageInspectorV2StorageService.js - executed lines 259/259; executed functions 39/39
282289
(100%) tools/text2speech-V2/js/controls/OutputSummaryControl.js - executed lines 8/8; executed functions 3/3
283290
(100%) tools/text2speech-V2/js/controls/SpeechOptionsControl.js - executed lines 451/451; executed functions 47/47
284291
(100%) tools/text2speech-V2/js/controls/StatusLogControl.js - executed lines 28/28; executed functions 8/8
@@ -297,5 +304,12 @@ Uncovered or low-coverage changed JS files:
297304
298305
Changed JS files considered:
299306
(0%) tests/playwright/tools/WorkspaceManagerV2.spec.mjs - changed JS file not collected as browser runtime coverage
300-
(94%) tools/object-vector-studio-v2/js/ToolStarterApp.js - changed JS file with browser V8 coverage
307+
(86%) src/engine/runtime/fullscreenBezel.js - changed JS file with browser V8 coverage
308+
(86%) tools/workspace-manager-v2/js/WorkspaceManagerV2App.js - changed JS file with browser V8 coverage
309+
(88%) tools/preview-generator-v2/PreviewGeneratorV2App.js - changed JS file with browser V8 coverage
310+
(92%) src/engine/runtime/gameImageConvention.js - changed JS file with browser V8 coverage
311+
(95%) tools/object-vector-studio-v2/js/ToolStarterApp.js - changed JS file with browser V8 coverage
312+
(98%) tools/storage-inspector-v2/js/StorageInspectorV2App.js - changed JS file with browser V8 coverage
313+
(100%) tools/storage-inspector-v2/js/controls/FilterControl.js - changed JS file with browser V8 coverage
314+
(100%) tools/storage-inspector-v2/js/services/StorageInspectorV2StorageService.js - changed JS file with browser V8 coverage
301315
```
Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
1-
# npm run test:workspace-v2
1+
# Workspace V2 Playwright Results
22

3-
Exit code: 0
3+
PR: PR_26133_098-storage-preview-workspace-and-object-vector-fix-batch
4+
Date: 2026-05-18
5+
6+
## Command
47

58
```text
6-
> html-javascript-gaming@1.0.0 test:workspace-v2
7-
> playwright test tests/playwright/tools/WorkspaceManagerV2.spec.mjs --project=playwright --workers=1 --reporter=list
9+
npm run test:workspace-v2
10+
```
811

9-
Running 55 tests using 1 worker
12+
## Result
1013

11-
Result: 55 passed (6.1m)
14+
PASS: 56/56 Playwright tests passed using the `playwright` project with 1 worker.
1215

13-
Result for PR_26133_097:
14-
- PASS small pointer movement inside selected bounds does not start preview drag
15-
- PASS selected shape repeated click preserves the selected set
16-
- PASS empty canvas drag/click outside selected bounds follows normal deselect/no-move behavior
17-
- PASS single-shape live drag updates selection bounds and resize/point handle positions before mouseup
18-
- PASS multi-selected shapes and grouped shapes still move together from preview selection bounds
19-
- PASS realtime drag transform values remain max 3 decimals
16+
## Focused Coverage From This PR
2017

21-
Additional focused checks run before the full suite:
22-
- drags selected Object Vector Studio V2 shapes from preview selection bounds
23-
- Object Vector Studio V2 layout shell and schema-only palette gate
24-
```
18+
- Storage Inspector V2: cookies are listed read-only, cookie delete is supported, and storage survival footer notes are visible for sessionStorage, localStorage, and cookies.
19+
- Asteroids: background resolves to `/games/Asteroids/assets/images/deluxe.png`; fullscreen bezel resolves to `/games/Asteroids/assets/images/bezel.png` and uses the transparent-window fit layout.
20+
- Preview Generator V2: missing repo-root path produces an actionable selection error and does not silently fallback.
21+
- Object Vector Studio V2: Auto Origin uses raw visible geometry bounds, and future shape tools are disabled/grayed out in alphabetized Shapes order.
22+
- Workspace Manager V2: dirty lifecycle buttons follow dirty/clean contracts: dirty enables Save/Cancel and disables Close; clean disables Save/Cancel and enables Close.
23+
24+
## Console/Runtime Errors
25+
26+
PASS: no page errors were observed by the workspace-v2 Playwright suite.

src/engine/runtime/fullscreenBezel.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -258,15 +258,23 @@ function parseStretchConfigPayload(payload, configPath = "") {
258258
return parsed;
259259
}
260260

261-
const flatAssetEntries = payload?.tools?.["asset-browser"]?.assets;
262-
if (flatAssetEntries && typeof flatAssetEntries === "object") {
261+
const assetEntriesByTool = [
262+
payload?.tools?.["asset-browser"]?.assets,
263+
payload?.tools?.["asset-manager-v2"]?.assets
264+
];
265+
for (const flatAssetEntries of assetEntriesByTool) {
266+
if (!flatAssetEntries || typeof flatAssetEntries !== "object") {
267+
continue;
268+
}
263269
const bezelAssetEntry = Object.entries(flatAssetEntries).find(([assetId, entry]) => {
264270
const normalizedAssetId = typeof assetId === "string" ? assetId.trim().toLowerCase() : "";
265271
const normalizedKind = typeof entry?.kind === "string" ? entry.kind.trim().toLowerCase() : "";
272+
const normalizedType = typeof entry?.type === "string" ? entry.type.trim().toLowerCase() : "";
273+
const normalizedRole = typeof entry?.role === "string" ? entry.role.trim().toLowerCase() : "";
266274
const hasStretch = entry?.stretchOverride && typeof entry.stretchOverride === "object";
267275
return hasStretch
268-
&& normalizedKind === "image"
269-
&& (normalizedAssetId.includes(".bezel") || normalizedAssetId.endsWith("bezel"));
276+
&& (normalizedKind === "image" || normalizedType === "image" || normalizedRole === "bezel")
277+
&& (normalizedRole === "bezel" || normalizedAssetId.includes(".bezel") || normalizedAssetId.endsWith("bezel"));
270278
});
271279
if (bezelAssetEntry && typeof bezelAssetEntry[1] === "object") {
272280
const stretchConfig = parseStretchConfigObject(bezelAssetEntry[1].stretchOverride);

src/engine/runtime/gameImageConvention.js

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,36 +52,64 @@ function deriveManifestPath(options = {}) {
5252
return deriveManifestPathFromGameId(gameId);
5353
}
5454

55-
function normalizeAssetEntry(rawEntry, fallbackId = "") {
55+
function resolveManifestRelativePath(pathValue, manifestPath) {
56+
const normalized = normalizePath(pathValue);
57+
if (!normalized || hasUrlProtocol(normalized) || normalized.startsWith("/") || normalized.startsWith("//")) {
58+
return normalized;
59+
}
60+
const baseManifestPath = normalizeManifestPath(manifestPath);
61+
if (!baseManifestPath) {
62+
return normalized;
63+
}
64+
const slashIndex = baseManifestPath.lastIndexOf("/");
65+
const baseFolder = slashIndex >= 0 ? baseManifestPath.slice(0, slashIndex) : "";
66+
return `${baseFolder}/${normalized.replace(/^\/+/, "")}`;
67+
}
68+
69+
function normalizeAssetEntry(rawEntry, fallbackId = "", manifestPath = "") {
5670
const entry = toObject(rawEntry);
57-
const path = normalizePath(entry.path || entry.runtimePath || entry.href);
71+
const path = resolveManifestRelativePath(entry.path || entry.runtimePath || entry.href, manifestPath);
5872
if (!path) {
5973
return null;
6074
}
6175
return {
6276
id: safeText(entry.id, "") || safeText(fallbackId, ""),
6377
kind: safeText(entry.kind, "").toLowerCase(),
64-
path
78+
path,
79+
role: safeText(entry.role, "").toLowerCase(),
80+
type: safeText(entry.type, "").toLowerCase()
6581
};
6682
}
6783

68-
function collectImageEntriesFromManifest(manifestPayload) {
84+
function collectImageEntriesFromManifest(manifestPayload, { manifestPath = "" } = {}) {
6985
const payload = toObject(manifestPayload);
7086
const entries = [];
7187

88+
const isImageEntry = (entry) => entry.type === "image"
89+
|| entry.kind === "image"
90+
|| entry.role === "background"
91+
|| entry.role === "bezel"
92+
|| entry.role === "preview"
93+
|| safeText(entry.id, "").toLowerCase().includes(".image.");
94+
7295
const pushEntry = (entry) => {
7396
if (!entry || !entry.path) {
7497
return;
7598
}
76-
if (entry.kind && entry.kind !== "image") {
99+
if (!isImageEntry(entry)) {
77100
return;
78101
}
79102
entries.push(entry);
80103
};
81104

82105
const assetBrowserAssets = toObject(payload?.tools?.["asset-browser"]?.assets);
83106
Object.entries(assetBrowserAssets).forEach(([assetId, rawEntry]) => {
84-
pushEntry(normalizeAssetEntry(rawEntry, assetId));
107+
pushEntry(normalizeAssetEntry(rawEntry, assetId, manifestPath));
108+
});
109+
110+
const assetManagerAssets = toObject(payload?.tools?.["asset-manager-v2"]?.assets);
111+
Object.entries(assetManagerAssets).forEach(([assetId, rawEntry]) => {
112+
pushEntry(normalizeAssetEntry(rawEntry, assetId, manifestPath));
85113
});
86114

87115
return entries;
@@ -97,7 +125,8 @@ function chooseSemanticImagePath(entries, semanticToken) {
97125

98126
const byId = normalizedEntries.find((entry) => {
99127
const id = safeText(entry?.id, "").toLowerCase();
100-
return id.includes(token);
128+
const role = safeText(entry?.role, "").toLowerCase();
129+
return role === token || id.includes(token);
101130
});
102131
if (byId?.path) {
103132
return byId.path;
@@ -205,7 +234,7 @@ export async function resolveManifestChromeAssetPaths(options = {}) {
205234
};
206235
}
207236

208-
const imageEntries = collectImageEntriesFromManifest(manifestPayload);
237+
const imageEntries = collectImageEntriesFromManifest(manifestPayload, { manifestPath: base.manifestPath });
209238
return {
210239
...base,
211240
manifestPayload,

0 commit comments

Comments
 (0)