Skip to content

Commit fd7fb2c

Browse files
author
DavidQ
committed
Fix Workspace Manager V2 return context and hydrate launched tool state - PR_26127_004-workspace-manager-v2-return-context-and-tool-launch-fixes
1 parent c70f0d9 commit fd7fb2c

13 files changed

Lines changed: 204 additions & 145 deletions
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# PR_26127_005-workspace-manager-v2-tool-tile-cleanup-preview-fix
2+
3+
## Scope
4+
5+
- Workspace Manager V2 UI and Preview Generator V2 workspace-launch hydration only.
6+
- Deprecated `tools/workspace-v2` was not modified.
7+
- Sample JSON was not modified.
8+
- No fallback behavior was added.
9+
10+
## Workspace Manager V2 UI Notes
11+
12+
- Removed the duplicate Workspace Context control from the center panel.
13+
- Kept Workspace JSON as the schema-valid manifest output surface.
14+
- Added Workspace Manager V2 tool tile grouping labels: Editors, Utilities, Viewers.
15+
- Added compact tile action labels: How To Use and Read Me.
16+
- Reordered the Workspace Manager V2 Status header controls so the visible order is Status, accordion icon, Clear.
17+
- Removed the user-facing Launch Context summary text that previously rendered `Schema-valid manifest is ready for Asteroids.`
18+
19+
## Preview Generator V2 Launch Notes
20+
21+
- Workspace Manager V2 launch hydration now derives the Preview Generator V2 asset folder from the loaded workspace manifest image asset paths.
22+
- Asteroids launch context now hydrates Preview Generator V2 with `assets/images`, producing preview lookup paths such as `/games/Asteroids/assets/images/preview.svg`.
23+
- The Generate action is labeled Generate Image and is moved into the workspace nav during Workspace Manager V2 launch so it is visible and enabled after valid context hydration.
24+
- The Preview Generator V2 workspace launch log records target source, hydrated asset folder, and existing preview load result.
25+
26+
## Validation
27+
28+
- `npm run test:workspace-v2` passed.
29+
- Result: 24 passed.
30+
- Playwright impacted: Yes.
31+
- Full samples smoke test skipped because this PR is Workspace Manager V2 UI and Preview Generator launch scoped.
32+
33+
## Playwright Coverage
34+
35+
- `docs/dev/reports/playwright_v8_coverage_report.txt` was regenerated by the workspace-v2 Playwright run.
36+
- Changed Workspace Manager V2 and Preview Generator V2 runtime files are listed in the coverage report.
37+
38+
## Manual Validation Notes
39+
40+
1. Open `tools/workspace-manager-v2/index.html`.
41+
2. Confirm the center panel shows Tools and Workspace JSON only; Workspace Context is not shown.
42+
3. Confirm tool tiles are grouped under Editors, Utilities, and Viewers and each tile shows How To Use and Read Me labels.
43+
4. Select Asteroids and launch Preview Generator V2 from the Preview Generator V2 tile.
44+
5. Confirm Preview Generator V2 shows Generate Image, uses `assets/images`, and logs the workspace launch hydration path.

tests/playwright/tools/AssetManagerV2.spec.mjs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -985,8 +985,8 @@ test.describe("Asset Manager V2", () => {
985985
try {
986986
await expect(page.locator("#seedUatManifestButton")).toBeVisible();
987987
await page.locator("#seedUatManifestButton").click();
988-
await expect(page.locator("#activePaletteSummary")).toContainText("Workspace Manager V2 UAT Sample Palette has 3 active colors.");
989-
await expect(page.locator("#activeAssetRegistrySummary")).toHaveText("Schema-ready Asset Manager V2 manifest payload contains 0 managed assets.");
988+
await expect(page.locator("#activePaletteSummary")).toHaveCount(0);
989+
await expect(page.locator("#activeAssetRegistrySummary")).toHaveCount(0);
990990
await page.locator('[data-workspace-tool-id="asset-manager-v2"]').click();
991991
await expect(page).toHaveURL(/asset-manager-v2\/index\.html.*launch=workspace/);
992992
await expect(page).not.toHaveURL(/workspace=uat/i);
@@ -1431,7 +1431,7 @@ test.describe("Asset Manager V2", () => {
14311431
await page.locator("#returnToWorkspaceButton").click();
14321432
await expect(page).toHaveURL(/workspace-manager-v2\/index\.html\?hostContextId=workspace-manager-v2-/);
14331433
await expect(page.locator("#activeGameSelect")).toHaveValue("Asteroids");
1434-
await expect(page.locator("#activeAssetRegistrySummary")).toHaveText("Schema-ready Asset Manager V2 manifest payload contains 17 managed assets.");
1434+
await expect(page.locator("#activeAssetRegistrySummary")).toHaveCount(0);
14351435
await expect(page.locator('[data-workspace-tool-id="asset-manager-v2"]')).toBeEnabled();
14361436
await expect(page.locator("#exportManifestButton")).toBeEnabled();
14371437
const downloadPromise = page.waitForEvent("download");

tests/playwright/tools/WorkspaceManagerV2.spec.mjs

Lines changed: 31 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -169,36 +169,37 @@ test.describe("Workspace Manager V2 bootstrap", () => {
169169
await expect(page.locator("#loadAsteroidsButton")).toHaveText("Load Asteroids");
170170
await expect(page.locator("#launchAssetManagerV2Button")).toHaveCount(0);
171171
await expect(page.locator("#workspaceToolsContent #workspaceToolTiles")).toBeVisible();
172-
await expect(page.locator("#workspaceContextContent #workspaceToolTiles")).toHaveCount(0);
173-
await expect(page.locator("#workspaceContextContent #workspaceContextOutput")).toHaveCount(0);
172+
await expect(page.locator("#workspaceContextContent")).toHaveCount(0);
174173
await expect(page.locator("#workspaceJsonContent #workspaceContextOutput")).toBeVisible();
175174
const centerControlLabels = await page.locator(".workspace-manager-v2__panel--center > .accordion-v2 > .accordion-v2__header span:first-child")
176175
.evaluateAll((labels) => labels.map((label) => label.textContent.trim()));
177-
expect(centerControlLabels.slice(0, 3)).toEqual(["Tools", "Workspace Context", "Workspace JSON"]);
176+
expect(centerControlLabels).toEqual(["Tools", "Workspace JSON"]);
177+
await expect(page.locator(".workspace-manager-v2__status-accordion-header")).toContainText("Status");
178+
const statusHeaderOrder = await page.locator(".workspace-manager-v2__status-accordion-header").evaluate((header) => Array.from(header.querySelectorAll(":scope > span, :scope > div > span, :scope > div > button"), (element) => element.textContent.trim()));
179+
expect(statusHeaderOrder).toEqual(["Status", "+", "Clear"]);
180+
await expect(page.locator(".workspace-manager-v2__tool-group-title")).toHaveText(["Editors", "Utilities", "Viewers"]);
178181
await expect(page.locator("#workspaceToolTiles [data-workspace-tool-id]")).toHaveCount(4);
179182
await expect(page.locator('[data-workspace-tool-id="workspace-manager-v2"]')).toHaveCount(0);
180183
expect(await page.locator("#workspaceToolTiles [data-workspace-tool-id]").evaluateAll((tiles) => tiles.every((tile) => tile.disabled))).toBe(true);
184+
expect(await page.locator("#workspaceToolTiles [data-workspace-tool-id]").evaluateAll((tiles) => (
185+
tiles.every((tile) => Array.from(tile.querySelectorAll(".workspace-manager-v2__tool-tile-action"), (action) => action.textContent.trim()).join("|") === "How To Use|Read Me")
186+
))).toBe(true);
181187
const compactCenterLayout = await page.evaluate(() => {
182188
const getRect = (selector) => {
183189
const element = document.querySelector(selector);
184190
return element ? element.getBoundingClientRect() : null;
185191
};
186192
const toolsRect = getRect(".workspace-manager-v2__accordion--tools");
187-
const toolGridRect = getRect("#workspaceToolTiles");
188-
const contextRect = getRect(".workspace-manager-v2__accordion--context");
189-
const summaryGridRect = getRect(".workspace-manager-v2__summary-grid");
193+
const toolGroupsRect = getRect("#workspaceToolTiles");
190194
const jsonRect = getRect(".workspace-manager-v2__accordion--json");
191195
return {
192-
contextExtraHeight: Math.round(contextRect.height - summaryGridRect.height),
193-
contextHeight: Math.round(contextRect.height),
194196
jsonTop: Math.round(jsonRect.top),
195197
toolsBottom: Math.round(toolsRect.bottom),
196-
toolsExtraHeight: Math.round(toolsRect.height - toolGridRect.height),
198+
toolsExtraHeight: Math.round(toolsRect.height - toolGroupsRect.height),
197199
toolsHeight: Math.round(toolsRect.height)
198200
};
199201
});
200202
expect(compactCenterLayout.toolsExtraHeight).toBeLessThanOrEqual(90);
201-
expect(compactCenterLayout.contextExtraHeight).toBeLessThanOrEqual(90);
202203
expect(compactCenterLayout.jsonTop).toBeGreaterThan(compactCenterLayout.toolsBottom);
203204
await expect(page.locator("#activeGameSelect option")).toHaveText([
204205
"Select a game",
@@ -209,22 +210,9 @@ test.describe("Workspace Manager V2 bootstrap", () => {
209210

210211
await page.locator("#activeGameSelect").selectOption("Asteroids");
211212
await expect(page.locator("#activeGameSummary")).toContainText("games/Asteroids/");
212-
await expect(page.locator("#activePaletteSummary")).toContainText("Asteroids Palette");
213-
await expect(page.locator("#activePaletteSummary")).toContainText("active colors");
214-
await expect(page.locator("#activeAssetRegistrySummary")).toHaveText("Schema-ready Asset Manager V2 manifest payload contains 13 managed assets.");
215-
await expect(page.locator("#launchContextSummary")).toHaveText("Schema-valid manifest is ready for Asteroids.");
216-
const workspaceContextTileHeights = await page.locator(".workspace-manager-v2__summary-card").evaluateAll((tiles) => tiles.map((tile) => Math.round(tile.getBoundingClientRect().height)));
217-
expect(new Set(workspaceContextTileHeights).size).toBe(1);
218-
expect(workspaceContextTileHeights.every((height) => height >= 148)).toBe(true);
219-
const workspaceContextTileScrollState = await page.locator(".workspace-manager-v2__summary-card").evaluateAll((tiles) => tiles.map((tile) => ({
220-
alignItems: getComputedStyle(tile).alignItems,
221-
justifyContent: getComputedStyle(tile).justifyContent,
222-
overflowY: getComputedStyle(tile).overflowY,
223-
scrolls: tile.scrollHeight > tile.clientHeight
224-
})));
225-
expect(workspaceContextTileScrollState.every((tile) => tile.justifyContent === "flex-start")).toBe(true);
226-
expect(workspaceContextTileScrollState.every((tile) => tile.overflowY === "visible")).toBe(true);
227-
expect(workspaceContextTileScrollState.every((tile) => tile.scrolls === false)).toBe(true);
213+
await expect(page.locator("#activePaletteSummary")).toHaveCount(0);
214+
await expect(page.locator("#activeAssetRegistrySummary")).toHaveCount(0);
215+
await expect(page.locator("#launchContextSummary")).toHaveCount(0);
228216
await expect(page.locator("#workspaceContextOutput")).toContainText('"gameRoot": "games/Asteroids/"');
229217
await expect(page.locator("#workspaceContextOutput")).toContainText('"assetsPath": "games/Asteroids/assets"');
230218
await expect(page.locator("#workspaceContextOutput")).toContainText('"source": "manifest"');
@@ -258,10 +246,10 @@ test.describe("Workspace Manager V2 bootstrap", () => {
258246
width: Math.round(tile.getBoundingClientRect().width)
259247
})));
260248
expect(tileLayout).toEqual([
261-
{ height: 118, width: 180 },
262-
{ height: 118, width: 180 },
263-
{ height: 118, width: 180 },
264-
{ height: 118, width: 180 }
249+
{ height: 142, width: 180 },
250+
{ height: 142, width: 180 },
251+
{ height: 142, width: 180 },
252+
{ height: 142, width: 180 }
265253
]);
266254
await expect(page.locator("#statusLog")).toHaveValue(/OK Loaded Asteroids from \/games\/Asteroids\/game\.manifest\.json with 11 active palette colors and 13 managed assets\./);
267255

@@ -394,7 +382,7 @@ test.describe("Workspace Manager V2 bootstrap", () => {
394382
await page.locator("#returnToWorkspaceButton").click();
395383
await expect(page).toHaveURL(/workspace-manager-v2\/index\.html\?hostContextId=workspace-manager-v2-/);
396384
await expect(page.locator("#activeGameSelect")).toHaveValue("Asteroids");
397-
await expect(page.locator("#activeAssetRegistrySummary")).toHaveText("Schema-ready Asset Manager V2 manifest payload contains 13 managed assets.");
385+
await expect(page.locator("#activeAssetRegistrySummary")).toHaveCount(0);
398386
await expect(page.locator('[data-workspace-tool-id="asset-manager-v2"]')).toBeEnabled();
399387
await expect(page.locator("#exportManifestButton")).toBeEnabled();
400388
await expect(page.locator("#statusLog")).toHaveValue(/OK Restored Asteroids workspace from session context workspace-manager-v2-/);
@@ -417,7 +405,7 @@ test.describe("Workspace Manager V2 bootstrap", () => {
417405
await expect(page.locator("#paletteStatus")).toHaveText("Loaded active workspace palette Asteroids Palette.");
418406
await page.locator("#returnToWorkspaceButton").click();
419407
await expect(page).toHaveURL(/workspace-manager-v2\/index\.html\?hostContextId=workspace-manager-v2-/);
420-
await page.route("**/games/Asteroids/assets/preview.svg", async (route) => {
408+
await page.route("**/games/Asteroids/assets/images/preview.svg", async (route) => {
421409
await route.fulfill({
422410
body: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8"><rect width="8" height="8"/></svg>',
423411
contentType: "image/svg+xml",
@@ -428,15 +416,18 @@ test.describe("Workspace Manager V2 bootstrap", () => {
428416
await expect(page).toHaveURL(/preview-generator-v2\/index\.html.*launch=workspace/);
429417
await expect(page.locator('[data-launch-mode-nav="tool"]')).toBeHidden();
430418
await expect(page.locator('[data-launch-mode-nav="workspace"]')).toBeVisible();
431-
await expect(page.locator('[data-launch-mode-nav="workspace"] button')).toHaveText(["Return to Workspace"]);
419+
await expect(page.locator('[data-launch-mode-nav="workspace"] button')).toHaveText(["Generate Image", "Return to Workspace"]);
420+
await expect(page.locator("#executeBtn")).toBeVisible();
421+
await expect(page.locator("#executeBtn")).toBeEnabled();
432422
await expect(page.locator("#repoSelectedValue")).toHaveText("Asteroids workspace (games/Asteroids)");
433423
await expect(page.locator("#targetTypeGames")).toBeChecked();
434-
await expect(page.locator("#assetFolder")).toHaveValue("assets");
424+
await expect(page.locator("#assetFolder")).toHaveValue("assets/images");
435425
await expect(page.locator("#sampleList")).toHaveValue("Asteroids");
436426
await expect(page.locator("#lastGeneratedImagePreview")).toBeVisible();
437427
await expect(page.locator("#lastGeneratedImageMeta")).toHaveText("Last generated: Asteroids preview.svg");
438428
await expect(page.locator("#log")).toContainText("OK Workspace launch context hydrated for Asteroids.");
439-
await expect(page.locator("#log")).toContainText("OK Loaded existing preview image from /games/Asteroids/assets/preview.svg.");
429+
await expect(page.locator("#log")).toContainText("Asset folder: assets\\images");
430+
await expect(page.locator("#log")).toContainText("OK Loaded existing preview image from /games/Asteroids/assets/images/preview.svg.");
440431
await page.locator("#returnToWorkspaceButton").click();
441432
await expect(page).toHaveURL(/workspace-manager-v2\/index\.html\?hostContextId=workspace-manager-v2-/);
442433
expect(pageErrors).toEqual([]);
@@ -465,7 +456,7 @@ test.describe("Workspace Manager V2 bootstrap", () => {
465456
});
466457
await expect(page.locator("#activeGameSelect")).toHaveValue("Asteroids");
467458
await expect(page.locator("#workspaceContextOutput")).toContainText('"id": "workspace-manager-v2-Asteroids-imported"');
468-
await expect(page.locator("#activeAssetRegistrySummary")).toHaveText("Schema-ready Asset Manager V2 manifest payload contains 13 managed assets.");
459+
await expect(page.locator("#activeAssetRegistrySummary")).toHaveCount(0);
469460
await expect(page.locator('[data-workspace-tool-id="asset-manager-v2"]')).toBeEnabled();
470461
await expect(page.locator("#statusLog")).toHaveValue(/OK Imported schema-valid Workspace Manager V2 manifest workspace-manager-v2-Asteroids-imported\./);
471462

@@ -528,7 +519,7 @@ test.describe("Workspace Manager V2 bootstrap", () => {
528519

529520
try {
530521
await page.locator("#activeGameSelect").selectOption("Asteroids");
531-
await expect(page.locator("#activeAssetRegistrySummary")).toHaveText("Schema-ready Asset Manager V2 manifest payload contains 0 managed assets.");
522+
await expect(page.locator("#activeAssetRegistrySummary")).toHaveCount(0);
532523
await expect(page.locator("#workspaceContextOutput")).toContainText('"assets": {}');
533524
await expect(page.locator("#workspaceContextOutput")).toContainText('"vector-map-editor"');
534525
await expect(page.locator("#statusLog")).toHaveValue(/INFO Warning: \/games\/Asteroids\/game\.manifest\.json has no Asteroids Asset Manager V2 assets; Workspace Manager V2 did not inject hardcoded assets\./);
@@ -559,8 +550,8 @@ test.describe("Workspace Manager V2 bootstrap", () => {
559550
}, uatManifest);
560551
expect(uatManifestValidation).toEqual({ ok: true });
561552
await expect(page.locator("#activeGameSelect")).toHaveValue("Asteroids");
562-
await expect(page.locator("#activePaletteSummary")).toContainText("Workspace Manager V2 UAT Sample Palette has 3 active colors.");
563-
await expect(page.locator("#activeAssetRegistrySummary")).toHaveText("Schema-ready Asset Manager V2 manifest payload contains 0 managed assets.");
553+
await expect(page.locator("#activePaletteSummary")).toHaveCount(0);
554+
await expect(page.locator("#activeAssetRegistrySummary")).toHaveCount(0);
564555
await expect(page.locator('[data-workspace-tool-id="templates-v2"]')).toContainText("Canonical V2 template");
565556
await expect(page.locator('[data-workspace-tool-id="asset-manager-v2"]')).toContainText("0 managed assets");
566557
await expect(page.locator('[data-workspace-tool-id="workspace-manager-v2"]')).toHaveCount(0);
@@ -581,7 +572,7 @@ test.describe("Workspace Manager V2 bootstrap", () => {
581572
await expect(page).toHaveURL(/workspace-manager-v2\/index\.html.*hostContextId=workspace-manager-v2-/);
582573
await expect(page).toHaveURL(/workspace=uat/);
583574
await expect(page.locator("#seedUatManifestButton")).toBeVisible();
584-
await expect(page.locator("#activeAssetRegistrySummary")).toHaveText("Schema-ready Asset Manager V2 manifest payload contains 0 managed assets.");
575+
await expect(page.locator("#activeAssetRegistrySummary")).toHaveCount(0);
585576
expect(pageErrors).toEqual([]);
586577
} finally {
587578
await coverageReporter.stop(page);

0 commit comments

Comments
 (0)