From 0167f1abae8d1a3f60433f525081100d9740588a Mon Sep 17 00:00:00 2001 From: DavidQ Date: Tue, 23 Jun 2026 18:15:31 -0400 Subject: [PATCH] ALFA 005 game hub audit findings cleanup --- docs_build/dev/BUILD_PR.md | 53 +- ...-game-hub-audit-findings-cleanup_report.md | 24 + ...findings-cleanup_requirements-checklist.md | 16 + ...-audit-findings-cleanup_validation-lane.md | 19 + .../dev/reports/codex_changed_files.txt | 10 +- docs_build/dev/reports/codex_review.diff | 689 +++++------------- .../tools/GameHubMockRepository.spec.mjs | 19 +- 7 files changed, 281 insertions(+), 549 deletions(-) create mode 100644 docs_build/dev/reports/PR_26175_ALFA_005-game-hub-audit-findings-cleanup_report.md create mode 100644 docs_build/dev/reports/PR_26175_ALFA_005-game-hub-audit-findings-cleanup_requirements-checklist.md create mode 100644 docs_build/dev/reports/PR_26175_ALFA_005-game-hub-audit-findings-cleanup_validation-lane.md diff --git a/docs_build/dev/BUILD_PR.md b/docs_build/dev/BUILD_PR.md index 65c4d9709..32898beed 100644 --- a/docs_build/dev/BUILD_PR.md +++ b/docs_build/dev/BUILD_PR.md @@ -1,40 +1,41 @@ -# PR_26175_ALFA_002-toolbox-status-bar-context-polish +# PR_26175_ALFA_005-game-hub-audit-findings-cleanup ## Purpose -Polish the shared toolbox status bar context display so it shows only selected-game name/purpose on the left and categorized tool context in the center. +Clean up the targeted Game Hub audit findings from `PR_26175_ALFA_004-game-hub-completion-status-audit`. ## Source Of Truth -This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_002-toolbox-status-bar-context-polish`. +This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_005-game-hub-audit-findings-cleanup`. ## Exact Scope -- Do not include environment text in the status bar because environment already appears in the platform banner. -- On the left side, display the selected Game Hub game name and selected Game Hub game purpose. -- On the center side, display tool context messages for tool actions, save state, validation messages, warnings, or errors. -- Preserve normal placement above the footer. -- Preserve fullscreen/tool display mode bottom anchoring. -- Preserve Idea Board selected-game filtering exclusion. -- Preserve Game Hub as selected-game owner through the existing repository contract. -- Keep the shared Theme V2 toolbox component model. -- Update targeted Playwright coverage for the polished left and center context. +- Resolve the targeted Game Hub Playwright failures recorded by the ALFA_004 audit. +- Keep the cleanup focused on stale or over-broad test expectations unless product code is required by validation. +- Preserve the existing Game Hub table workflow behavior. +- Preserve the shared toolbox selected-game status bar behavior. +- Preserve Game Journey completion-metrics API/service behavior. +- Do not implement unrelated product or UI changes. + +## ALFA_004 Findings To Clean Up +- `tests/playwright/tools/GameHubMockRepository.spec.mjs:238`: duplicate `Open Game Hub` link strict-mode conflict after the shared toolbox status bar added its own Game Hub action. +- `tests/playwright/tools/GameHubMockRepository.spec.mjs:257`: stale expectation that no `Game Status` label exists. +- `tests/playwright/tools/GameHubMockRepository.spec.mjs:582`: stale guest-mode expectation that no `Game Status` label exists. +- `tests/playwright/tools/GameHubMockRepository.spec.mjs:1019`: toolbox role-filter lane records known `500 /api/game-journey/completion-metrics` requests outside the Game Hub table workflow. ## Exact Targets - `docs_build/dev/BUILD_PR.md` -- `assets/theme-v2/js/toolbox-status-bar.js` -- `assets/theme-v2/css/status.css` -- `tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs` -- `docs_build/dev/reports/PR_26175_ALFA_002-toolbox-status-bar-context-polish_report.md` -- `docs_build/dev/reports/PR_26175_ALFA_002-toolbox-status-bar-context-polish_validation-lane.md` -- `docs_build/dev/reports/PR_26175_ALFA_002-toolbox-status-bar-context-polish_requirements-checklist.md` +- `tests/playwright/tools/GameHubMockRepository.spec.mjs` +- `docs_build/dev/reports/PR_26175_ALFA_005-game-hub-audit-findings-cleanup_report.md` +- `docs_build/dev/reports/PR_26175_ALFA_005-game-hub-audit-findings-cleanup_validation-lane.md` +- `docs_build/dev/reports/PR_26175_ALFA_005-game-hub-audit-findings-cleanup_requirements-checklist.md` - `docs_build/dev/reports/codex_review.diff` - `docs_build/dev/reports/codex_changed_files.txt` ## Out Of Scope -- No environment status in the toolbox status bar. -- No row highlights. -- No large banners. -- No modal-style status messages. -- No inline styles, style blocks, or page-local CSS. +- No Game Hub product or UI behavior changes unless targeted validation proves they are required. +- No Game Journey completion-metrics product/API/service changes. - No API/service contract changes. +- No browser-owned product data as source of truth. +- No silent fallbacks. +- No inline styles, style blocks, or page-local CSS. - No engine core changes. - No `start_of_day` folder changes. @@ -42,18 +43,18 @@ This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_002-toolbox-status- Run: ```powershell -npx playwright test tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs --workers=1 +npx playwright test tests/playwright/tools/GameHubMockRepository.spec.mjs --workers=1 ``` Also verify the changed source does not introduce inline styles or style blocks: ```powershell -rg -n " String(value || "").trim()) -- .filter(Boolean) -- .join(" - "); -+function classifyToolContext(messageText, state, required) { -+ const text = String(messageText || "").trim(); -+ if (state === "error") { -+ return { kind: "error", label: "Error" }; -+ } -+ if (required && state === "missing") { -+ return { kind: "action", label: "Tool Action" }; -+ } -+ if (/\b(error|failed|malformed|unavailable|could not)\b/i.test(text)) { -+ return { kind: "error", label: "Error" }; -+ } -+ if (/\b(sign in|refresh|try again|temporarily|blocked)\b/i.test(text)) { -+ return { kind: "warning", label: "Warning" }; -+ } -+ if (/\b(validation|requirement|requirements|missing|required|open or seed)\b/i.test(text)) { -+ return { kind: "validation", label: "Validation" }; -+ } -+ if (/\b(saved|created|deleted|updated|loaded|save changes)\b/i.test(text)) { -+ return { kind: "save", label: "Save State" }; -+ } -+ return { kind: "action", label: "Tool Action" }; - } - - function renderSelectedGame(bar, selectedGame, state, messageText) { - const required = pageRequiresSelectedGame(); - const name = bar.querySelector("[data-toolbox-selected-game-name]"); -- const meta = bar.querySelector("[data-toolbox-selected-game-meta]"); -+ const purpose = bar.querySelector("[data-toolbox-selected-game-purpose]"); -+ const contextType = bar.querySelector("[data-toolbox-status-context-type]"); - const message = bar.querySelector("[data-toolbox-status-message]"); - const action = bar.querySelector("[data-toolbox-status-action]"); -+ const nextMessage = messageText || latestToolMessage || (selectedGame -+ ? `Tool context is filtered to ${selectedGame.name}.` -+ : required -+ ? "Select or create a game in Game Hub before using this toolbox page." -+ : "Idea Board can capture ideas before a Game Hub game exists."); -+ const context = classifyToolContext(nextMessage, state, required); - - bar.dataset.selectedGameState = state; - bar.dataset.selectedGameRequired = String(required); -+ bar.dataset.toolboxStatusContextKind = context.kind; -+ contextType.textContent = context.label; - action.hidden = false; - action.href = mountOptions.gameHubHref; - - if (selectedGame) { - name.textContent = selectedGame.name; -- meta.textContent = selectedGameMeta(selectedGame) || "Game Hub selected game"; -- message.textContent = messageText || latestToolMessage || `Data filtered to ${selectedGame.name}.`; -+ purpose.textContent = selectedGame.purpose || "Game"; -+ message.textContent = nextMessage; - action.textContent = "Open Game Hub"; - return; - } - - if (!required) { -- name.textContent = "Optional"; -- meta.textContent = "Idea Board can start before Game Hub creation"; -- message.textContent = latestToolMessage || "Idea Board can capture ideas before a Game Hub game exists."; -+ name.textContent = "No game selected"; -+ purpose.textContent = "Idea Board optional"; -+ message.textContent = nextMessage; - action.textContent = "Open Game Hub"; - return; - } - - if (state === "error") { - name.textContent = "Unavailable"; -- meta.textContent = "Game Hub selected game could not be read"; -- message.textContent = messageText || "Game Hub selected game is unavailable. Refresh or restore the Local API."; -+ purpose.textContent = "Game Hub selected game could not be read"; -+ message.textContent = nextMessage; - action.textContent = "Open Game Hub"; - return; - } - - name.textContent = "No game selected"; -- meta.textContent = "Game Hub owns game selection"; -+ purpose.textContent = "Game Hub owns game selection"; - message.textContent = "Select or create a game in Game Hub before using this toolbox page."; - action.textContent = "Select or Create in Game Hub"; - } -@@ -284,6 +329,9 @@ function installEventListeners() { - return; - } - listenersInstalled = true; -+ document.addEventListener("click", scheduleToolMessageRefresh, true); -+ document.addEventListener("submit", scheduleToolMessageRefresh, true); -+ document.addEventListener("change", scheduleToolMessageRefresh, true); - window.addEventListener("gamefoundry:toolbox-selected-game-changed", refreshToolboxStatusBar); - window.addEventListener("gamefoundry:data-changed", refreshToolboxStatusBar); - } diff --git a/docs_build/dev/BUILD_PR.md b/docs_build/dev/BUILD_PR.md -index 51d6abdeb..65c4d9709 100644 +index 65c4d9709..32898beed 100644 --- a/docs_build/dev/BUILD_PR.md +++ b/docs_build/dev/BUILD_PR.md -@@ -1,41 +1,42 @@ --# PR_26175_ALFA_001-toolbox-selected-game-status-bar -+# PR_26175_ALFA_002-toolbox-status-bar-context-polish +@@ -1,40 +1,41 @@ +-# PR_26175_ALFA_002-toolbox-status-bar-context-polish ++# PR_26175_ALFA_005-game-hub-audit-findings-cleanup ## Purpose --Add one shared Theme V2 toolbox status bar that surfaces the Game Hub selected game and current tool messages across toolbox pages. -+Polish the shared toolbox status bar context display so it shows only selected-game name/purpose on the left and categorized tool context in the center. +-Polish the shared toolbox status bar context display so it shows only selected-game name/purpose on the left and categorized tool context in the center. ++Clean up the targeted Game Hub audit findings from `PR_26175_ALFA_004-game-hub-completion-status-audit`. ## Source Of Truth --This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_001-toolbox-selected-game-status-bar`. -+This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_002-toolbox-status-bar-context-polish`. +-This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_002-toolbox-status-bar-context-polish`. ++This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_005-game-hub-audit-findings-cleanup`. ## Exact Scope --- Add a shared toolbox status bar renderer loaded through Theme V2 shared partial bootstrapping. --- Render the status bar above the footer in normal page mode. --- Anchor the status bar to the viewport bottom while `body.tool-focus-mode` is active. --- Read the selected game only from the Game Hub repository through the existing Local API/service contract. --- Display the selected Game Hub game on the left side of the status bar. --- Display tool actions, warnings, errors, save state, validation messages, or the missing-game prompt in the center of the status bar. --- Expose the selected Game Hub game as derived page context for toolbox pages without persisting browser-owned product data. --- Require selected-game context on toolbox pages except Idea Board, which remains excluded because ideas can exist before game creation. --- Show a creator-safe prompt to select or create a game in Game Hub when no selected game exists. --- Notify the shared status bar when Game Hub changes the selected game. --- Add targeted Playwright coverage for placement, fullscreen anchoring, selected-game display/update, missing-game prompt, and Idea Board exclusion. -+- Do not include environment text in the status bar because environment already appears in the platform banner. -+- On the left side, display the selected Game Hub game name and selected Game Hub game purpose. -+- On the center side, display tool context messages for tool actions, save state, validation messages, warnings, or errors. -+- Preserve normal placement above the footer. -+- Preserve fullscreen/tool display mode bottom anchoring. -+- Preserve Idea Board selected-game filtering exclusion. -+- Preserve Game Hub as selected-game owner through the existing repository contract. -+- Keep the shared Theme V2 toolbox component model. -+- Update targeted Playwright coverage for the polished left and center context. +-- Do not include environment text in the status bar because environment already appears in the platform banner. +-- On the left side, display the selected Game Hub game name and selected Game Hub game purpose. +-- On the center side, display tool context messages for tool actions, save state, validation messages, warnings, or errors. +-- Preserve normal placement above the footer. +-- Preserve fullscreen/tool display mode bottom anchoring. +-- Preserve Idea Board selected-game filtering exclusion. +-- Preserve Game Hub as selected-game owner through the existing repository contract. +-- Keep the shared Theme V2 toolbox component model. +-- Update targeted Playwright coverage for the polished left and center context. ++- Resolve the targeted Game Hub Playwright failures recorded by the ALFA_004 audit. ++- Keep the cleanup focused on stale or over-broad test expectations unless product code is required by validation. ++- Preserve the existing Game Hub table workflow behavior. ++- Preserve the shared toolbox selected-game status bar behavior. ++- Preserve Game Journey completion-metrics API/service behavior. ++- Do not implement unrelated product or UI changes. ++ ++## ALFA_004 Findings To Clean Up ++- `tests/playwright/tools/GameHubMockRepository.spec.mjs:238`: duplicate `Open Game Hub` link strict-mode conflict after the shared toolbox status bar added its own Game Hub action. ++- `tests/playwright/tools/GameHubMockRepository.spec.mjs:257`: stale expectation that no `Game Status` label exists. ++- `tests/playwright/tools/GameHubMockRepository.spec.mjs:582`: stale guest-mode expectation that no `Game Status` label exists. ++- `tests/playwright/tools/GameHubMockRepository.spec.mjs:1019`: toolbox role-filter lane records known `500 /api/game-journey/completion-metrics` requests outside the Game Hub table workflow. ## Exact Targets --- `assets/theme-v2/js/gamefoundry-partials.js` -+- `docs_build/dev/BUILD_PR.md` - - `assets/theme-v2/js/toolbox-status-bar.js` - - `assets/theme-v2/css/status.css` --- `toolbox/game-hub/game-hub.js` - - `tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs` --- `docs_build/dev/reports/PR_26175_ALFA_001-toolbox-selected-game-status-bar_report.md` --- `docs_build/dev/reports/PR_26175_ALFA_001-toolbox-selected-game-status-bar_validation-lane.md` --- `docs_build/dev/reports/PR_26175_ALFA_001-toolbox-selected-game-status-bar_requirements-checklist.md` -+- `docs_build/dev/reports/PR_26175_ALFA_002-toolbox-status-bar-context-polish_report.md` -+- `docs_build/dev/reports/PR_26175_ALFA_002-toolbox-status-bar-context-polish_validation-lane.md` -+- `docs_build/dev/reports/PR_26175_ALFA_002-toolbox-status-bar-context-polish_requirements-checklist.md` -+- `docs_build/dev/reports/codex_review.diff` -+- `docs_build/dev/reports/codex_changed_files.txt` + - `docs_build/dev/BUILD_PR.md` +-- `assets/theme-v2/js/toolbox-status-bar.js` +-- `assets/theme-v2/css/status.css` +-- `tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs` +-- `docs_build/dev/reports/PR_26175_ALFA_002-toolbox-status-bar-context-polish_report.md` +-- `docs_build/dev/reports/PR_26175_ALFA_002-toolbox-status-bar-context-polish_validation-lane.md` +-- `docs_build/dev/reports/PR_26175_ALFA_002-toolbox-status-bar-context-polish_requirements-checklist.md` ++- `tests/playwright/tools/GameHubMockRepository.spec.mjs` ++- `docs_build/dev/reports/PR_26175_ALFA_005-game-hub-audit-findings-cleanup_report.md` ++- `docs_build/dev/reports/PR_26175_ALFA_005-game-hub-audit-findings-cleanup_validation-lane.md` ++- `docs_build/dev/reports/PR_26175_ALFA_005-game-hub-audit-findings-cleanup_requirements-checklist.md` + - `docs_build/dev/reports/codex_review.diff` + - `docs_build/dev/reports/codex_changed_files.txt` ## Out Of Scope -+- No environment status in the toolbox status bar. -+- No row highlights. -+- No large banners. -+- No modal-style status messages. +-- No environment status in the toolbox status bar. +-- No row highlights. +-- No large banners. +-- No modal-style status messages. +-- No inline styles, style blocks, or page-local CSS. ++- No Game Hub product or UI behavior changes unless targeted validation proves they are required. ++- No Game Journey completion-metrics product/API/service changes. + - No API/service contract changes. ++- No browser-owned product data as source of truth. ++- No silent fallbacks. +- No inline styles, style blocks, or page-local CSS. -+- No API/service contract changes. - No engine core changes. - No `start_of_day` folder changes. --- No API/service contract changes. --- No page-local CSS, inline styles, or style blocks. --- No browser storage or browser-owned product data as selected-game source of truth. --- No Idea Board selected-game filtering. - ## Validation +@@ -42,18 +43,18 @@ This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_002-toolbox-status- Run: -@@ -47,12 +48,12 @@ npx playwright test tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs + + ```powershell +-npx playwright test tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs --workers=1 ++npx playwright test tests/playwright/tools/GameHubMockRepository.spec.mjs --workers=1 + ``` + Also verify the changed source does not introduce inline styles or style blocks: ```powershell --rg -n " { + ++ if (pathName.includes("/toolbox/index.html")) { ++ await page.route("**/api/game-journey/completion-metrics", async (route) => { + await route.fulfill({ + contentType: "application/json", + body: JSON.stringify({ -+ data: { -+ authenticated: true, -+ displayName: options.session.displayName || "User 1", -+ roleSlugs: options.session.roleSlugs || ["creator"], -+ userKey, -+ }, ++ data: { records: [] }, + ok: true, ++ rule: "Browser -> Server API -> Data Source", + }), + }); + }); -+ await page.request.post(`${server.baseUrl}/api/session/user`, { -+ data: { userKey }, -+ }); + } - ++ await workspaceV2CoverageReporter.start(page); await page.goto(`${server.baseUrl}${pathName}`, { waitUntil: "networkidle" }); -@@ -84,6 +105,14 @@ function expectNoPageFailures(failures) { - expect(failures.consoleErrors).toEqual([]); - } - -+function creatorSession() { -+ return { -+ displayName: "User 1", -+ roleSlugs: ["creator"], -+ userKey: MOCK_DB_KEYS.users.user1, -+ }; -+} -+ - async function statusBarSnapshot(page) { - return page.locator("[data-toolbox-status-bar]").evaluate((bar) => { - const footer = document.querySelector("footer.footer"); -@@ -111,8 +140,13 @@ test("shared toolbox status bar shows selected Game Hub game above the footer", - const statusBar = page.locator("[data-toolbox-status-bar]"); - await expect(statusBar).toBeVisible(); - await expect(page.locator("style, [style], script:not([src])")).toHaveCount(0); -+ await expect(statusBar).not.toContainText("Environment"); -+ await expect(statusBar.locator("[data-toolbox-selected-game-name-label]")).toHaveText("Selected Game Name"); - await expect(statusBar.locator("[data-toolbox-selected-game-name]")).toHaveText("Demo Game"); -- await expect(statusBar.locator("[data-toolbox-selected-game-meta]")).toHaveText("Game - Under Construction"); -+ await expect(statusBar.locator("[data-toolbox-selected-game-purpose-label]")).toHaveText("Selected Game Purpose"); -+ await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveText("Game"); -+ await expect(statusBar.locator("[data-toolbox-selected-game]")).not.toContainText("Under Construction"); -+ await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveText("Tool Action"); - await expect(statusBar.locator("[data-toolbox-status-message]")).toContainText("Game Design mock repository ready."); - await expect(page.locator("body")).toHaveAttribute("data-toolbox-selected-game-id", "demo-game"); - await expect(page.locator("body")).toHaveAttribute("data-toolbox-selected-game-filter", "active"); -@@ -130,6 +164,29 @@ test("shared toolbox status bar shows selected Game Hub game above the footer", - } - }); - -+test("shared toolbox status bar center reports save state after Game Hub saves", async ({ page }) => { -+ const failures = await openRepoPage(page, "/toolbox/game-hub/index.html", { session: creatorSession() }); -+ -+ try { -+ await page.getByRole("button", { name: "Add Game" }).click(); -+ const addGameRow = page.locator("[data-game-add-row='input']"); -+ await addGameRow.getByLabel("Game").fill("Status Bar Save"); -+ await addGameRow.getByLabel("Purpose").selectOption("Learning Game"); -+ await addGameRow.getByLabel("Status").selectOption("Ready for Testing"); -+ await addGameRow.getByRole("button", { name: "Save" }).click(); -+ -+ await expect(page.locator("[data-toolbox-status-context-type]")).toHaveText("Save State"); -+ await expect(page.locator("[data-toolbox-status-message]")).toHaveText("Created and opened Status Bar Save."); -+ await expect(page.locator("[data-toolbox-selected-game-name]")).toHaveText("Status Bar Save"); -+ await expect(page.locator("[data-toolbox-selected-game-purpose]")).toHaveText("Learning Game"); -+ await expect(page.locator("[data-toolbox-status-bar]")).not.toContainText("Environment"); -+ -+ expectNoPageFailures(failures); -+ } finally { -+ await failures.server.close(); -+ } -+}); -+ - test("shared toolbox status bar anchors to the bottom in tool display mode", async ({ page }) => { - const failures = await openRepoPage(page, "/toolbox/game-design/index.html"); - -@@ -156,9 +213,11 @@ test("Game Hub owner selection updates the global toolbox status bar", async ({ - await expect(page.locator("[data-toolbox-selected-game-name]")).toHaveText("Demo Game"); - await page.locator("[data-game-toggle='gravity-demo']").click(); - await expect(page.locator("[data-toolbox-selected-game-name]")).toHaveText("Gravity Demo"); -- await expect(page.locator("[data-toolbox-selected-game-meta]")).toHaveText("Capability Demo - Wireframe"); -+ await expect(page.locator("[data-toolbox-selected-game-purpose]")).toHaveText("Capability Demo"); -+ await expect(page.locator("[data-toolbox-selected-game]")).not.toContainText("Wireframe"); - await expect(page.locator("body")).toHaveAttribute("data-toolbox-selected-game-id", "gravity-demo"); - await expect(page.locator("body")).toHaveAttribute("data-toolbox-selected-game-filter", "active"); -+ await expect(page.locator("[data-toolbox-status-context-type]")).toHaveText("Warning"); - await expect(page.locator("[data-toolbox-status-message]")).toContainText("Sign in to create or update Game Hub projects."); - - expectNoPageFailures(failures); -@@ -173,6 +232,8 @@ test("non-Idea Board toolbox pages show a creator-safe prompt when no Game Hub g - try { - const statusBar = page.locator("[data-toolbox-status-bar]"); - await expect(statusBar.locator("[data-toolbox-selected-game-name]")).toHaveText("No game selected"); -+ await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveText("Game Hub owns game selection"); -+ await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveText("Tool Action"); - await expect(statusBar.locator("[data-toolbox-status-message]")).toHaveText("Select or create a game in Game Hub before using this toolbox page."); - await expect(statusBar.locator("[data-toolbox-status-action]")).toHaveText("Select or Create in Game Hub"); - await expect(statusBar.locator("[data-toolbox-status-action]")).toHaveAttribute("href", /toolbox\/game-hub\/index\.html$/); -@@ -195,8 +256,9 @@ test("Idea Board is excluded from selected-game filtering and does not show the - try { - const statusBar = page.locator("[data-toolbox-status-bar]"); - await expect(statusBar).toBeVisible(); -- await expect(statusBar.locator("[data-toolbox-selected-game-name]")).toHaveText("Optional"); -- await expect(statusBar.locator("[data-toolbox-selected-game-meta]")).toHaveText("Idea Board can start before Game Hub creation"); -+ await expect(statusBar.locator("[data-toolbox-selected-game-name]")).toHaveText("No game selected"); -+ await expect(statusBar.locator("[data-toolbox-selected-game-purpose]")).toHaveText("Idea Board optional"); -+ await expect(statusBar.locator("[data-toolbox-status-context-type]")).toHaveText("Tool Action"); - await expect(statusBar.locator("[data-toolbox-status-message]")).toContainText("Ready to shape ideas and notes."); - await expect(statusBar.locator("[data-toolbox-status-message]")).not.toContainText("Select or create a game"); - await expect(page.locator("body")).toHaveAttribute("data-toolbox-selected-game-filter", "optional"); + return { failedRequests, pageErrors, consoleErrors, server }; +@@ -235,7 +248,7 @@ test("Deprecated project workspace route points creators to Game Hub", async ({ + await expect(page.getByRole("heading", { name: "Game Hub" })).toBeVisible(); + await expect(page.locator("main")).toContainText("This route is kept for older links."); + await expect(page.locator("main")).not.toContainText("Project Workspace"); +- await expect(page.getByRole("link", { name: "Open Game Hub" })).toHaveAttribute("href", "toolbox/game-hub/index.html"); ++ await expect(page.locator("main").getByRole("link", { name: "Open Game Hub" })).toHaveAttribute("href", "toolbox/game-hub/index.html"); + + await expectNoPageFailures(failures); + } finally { +@@ -254,7 +267,7 @@ test("Game Hub creates, opens, and deletes mock games", async ({ page }) => { + await expect(page.getByRole("button", { name: "Add Game" })).toBeEnabled(); + await expect(page.getByLabel("Game Name")).toHaveCount(0); + await expect(page.getByLabel("Game Purpose")).toHaveCount(0); +- await expect(page.getByLabel("Game Status")).toHaveCount(0); ++ await expect(page.locator("input[aria-label='Game Status'], textarea[aria-label='Game Status'], select[aria-label='Game Status']")).toHaveCount(0); + await expect(page.getByRole("button", { name: "Delete Open Game" })).toHaveClass("btn"); + await expect(page.getByRole("button", { name: "Delete Open Game" })).toBeEnabled(); + await expect(page.locator("summary").filter({ hasText: /^Game Setup$/ })).toHaveCount(0); +@@ -579,7 +592,7 @@ test("Game Hub preserves guest browsing and blocks guest saves", async ({ page } + await expect(page.getByRole("button", { name: "Delete Open Game" })).toBeDisabled(); + await expect(page.getByLabel("Game Name")).toHaveCount(0); + await expect(page.getByLabel("Game Purpose")).toHaveCount(0); +- await expect(page.getByLabel("Game Status")).toHaveCount(0); ++ await expect(page.locator("input[aria-label='Game Status'], textarea[aria-label='Game Status'], select[aria-label='Game Status']")).toHaveCount(0); + await expect(page.getByLabel("Current User Role")).toHaveCount(0); + + await page.locator("[data-game-row='gravity-demo'] [data-game-toggle='gravity-demo']").click(); diff --git a/tests/playwright/tools/GameHubMockRepository.spec.mjs b/tests/playwright/tools/GameHubMockRepository.spec.mjs index 6f6d046d2..9c8cecd49 100644 --- a/tests/playwright/tools/GameHubMockRepository.spec.mjs +++ b/tests/playwright/tools/GameHubMockRepository.spec.mjs @@ -209,6 +209,19 @@ async function openRepoPage(page, pathName, options = {}) { }); } + if (pathName.includes("/toolbox/index.html")) { + await page.route("**/api/game-journey/completion-metrics", async (route) => { + await route.fulfill({ + contentType: "application/json", + body: JSON.stringify({ + data: { records: [] }, + ok: true, + rule: "Browser -> Server API -> Data Source", + }), + }); + }); + } + await workspaceV2CoverageReporter.start(page); await page.goto(`${server.baseUrl}${pathName}`, { waitUntil: "networkidle" }); return { failedRequests, pageErrors, consoleErrors, server }; @@ -235,7 +248,7 @@ test("Deprecated project workspace route points creators to Game Hub", async ({ await expect(page.getByRole("heading", { name: "Game Hub" })).toBeVisible(); await expect(page.locator("main")).toContainText("This route is kept for older links."); await expect(page.locator("main")).not.toContainText("Project Workspace"); - await expect(page.getByRole("link", { name: "Open Game Hub" })).toHaveAttribute("href", "toolbox/game-hub/index.html"); + await expect(page.locator("main").getByRole("link", { name: "Open Game Hub" })).toHaveAttribute("href", "toolbox/game-hub/index.html"); await expectNoPageFailures(failures); } finally { @@ -254,7 +267,7 @@ test("Game Hub creates, opens, and deletes mock games", async ({ page }) => { await expect(page.getByRole("button", { name: "Add Game" })).toBeEnabled(); await expect(page.getByLabel("Game Name")).toHaveCount(0); await expect(page.getByLabel("Game Purpose")).toHaveCount(0); - await expect(page.getByLabel("Game Status")).toHaveCount(0); + await expect(page.locator("input[aria-label='Game Status'], textarea[aria-label='Game Status'], select[aria-label='Game Status']")).toHaveCount(0); await expect(page.getByRole("button", { name: "Delete Open Game" })).toHaveClass("btn"); await expect(page.getByRole("button", { name: "Delete Open Game" })).toBeEnabled(); await expect(page.locator("summary").filter({ hasText: /^Game Setup$/ })).toHaveCount(0); @@ -579,7 +592,7 @@ test("Game Hub preserves guest browsing and blocks guest saves", async ({ page } await expect(page.getByRole("button", { name: "Delete Open Game" })).toBeDisabled(); await expect(page.getByLabel("Game Name")).toHaveCount(0); await expect(page.getByLabel("Game Purpose")).toHaveCount(0); - await expect(page.getByLabel("Game Status")).toHaveCount(0); + await expect(page.locator("input[aria-label='Game Status'], textarea[aria-label='Game Status'], select[aria-label='Game Status']")).toHaveCount(0); await expect(page.getByLabel("Current User Role")).toHaveCount(0); await page.locator("[data-game-row='gravity-demo'] [data-game-toggle='gravity-demo']").click();