diff --git a/ui/frontend/src/lib/screens/lobby-create-screen.svelte b/ui/frontend/src/lib/screens/lobby-create-screen.svelte index 29a5711..61e9bf9 100644 --- a/ui/frontend/src/lib/screens/lobby-create-screen.svelte +++ b/ui/frontend/src/lib/screens/lobby-create-screen.svelte @@ -9,6 +9,7 @@ import { i18n, type TranslationKey } from "$lib/i18n/index.svelte"; import { loadCore } from "../../platform/core/index"; import { session } from "$lib/session-store.svelte"; + import { lobbyData } from "$lib/lobby-data.svelte"; const DEFAULT_MIN_PLAYERS = 2; const DEFAULT_MAX_PLAYERS = 8; @@ -102,9 +103,17 @@ turnSchedule: trimmedSchedule, targetEngineVersion: targetEngineVersion.trim() || DEFAULT_TARGET_ENGINE_VERSION, }); - // Land on the private-games panel where the freshly created - // game shows up — the lobby-data store will refresh on next - // mount. + // Refresh the lobby-data cache so the freshly-created game + // shows up in the private-games panel the moment we land + // there. The shared store is otherwise lazy (ensure-on- + // first-mount) and would render a stale list across the + // navigation. + try { + await lobbyData.refresh(); + } catch { + // Refresh failure does not block the navigation — + // the panel will retry on its own mount. + } appScreen.go("games-private-games"); } catch (err) { formError = describeLobbyError(err); diff --git a/ui/frontend/tests/e2e/game-shell-map.spec.ts b/ui/frontend/tests/e2e/game-shell-map.spec.ts index c26ab2b..436faf6 100644 --- a/ui/frontend/tests/e2e/game-shell-map.spec.ts +++ b/ui/frontend/tests/e2e/game-shell-map.spec.ts @@ -250,9 +250,12 @@ test("missing-membership game drops back to the lobby with an unavailable toast" ); // Back on the lobby (game shell unmounted), with the unavailable toast. + // F8-04b moved the `create new game` button into the `private games` + // sub-panel; the always-present lobby chrome signal is the identity + // strip, so assert that instead. await expect(page.getByTestId("toast")).toContainText( "this game is no longer available", ); - await expect(page.getByTestId("lobby-create-button")).toBeVisible(); + await expect(page.getByTestId("lobby-account-name")).toBeVisible(); await expect(page.getByTestId("game-shell")).toHaveCount(0); }); diff --git a/ui/frontend/tests/e2e/inspector-ship-group.spec.ts b/ui/frontend/tests/e2e/inspector-ship-group.spec.ts index a9989e3..7de4963 100644 --- a/ui/frontend/tests/e2e/inspector-ship-group.spec.ts +++ b/ui/frontend/tests/e2e/inspector-ship-group.spec.ts @@ -136,9 +136,13 @@ test("synthetic-report loader navigates from lobby to map and renders", async ({ page, }) => { await seedSession(page); - // Seeded session → the dispatcher renders the lobby; the synthetic - // loader lives there behind the dev-affordances flag. + // Seeded session → the dispatcher renders the lobby. F8-04b moved + // the synthetic-report loader off of Overview into its own + // dev-only top-level screen; jump straight to it via the dev nav + // surface so the spec is viewport-agnostic. await page.goto("/"); + await page.waitForFunction(() => window.__galaxyNav !== undefined); + await page.evaluate(() => window.__galaxyNav!.go("synthetic-reports")); await expect(page.getByTestId("lobby-synthetic-section")).toBeVisible(); const file = page.getByTestId("lobby-synthetic-file"); diff --git a/ui/frontend/tests/e2e/lobby-flow.spec.ts b/ui/frontend/tests/e2e/lobby-flow.spec.ts index 5e9d9cf..8ebf251 100644 --- a/ui/frontend/tests/e2e/lobby-flow.spec.ts +++ b/ui/frontend/tests/e2e/lobby-flow.spec.ts @@ -271,8 +271,11 @@ test.describe("Phase 8 — lobby flow", () => { // Default landing is `games-recruitment` (empty, no public games). await expect(page.getByTestId("lobby-recruitment-empty")).toBeVisible(); - // Paid tier exposes the `private games` sub-panel; navigate to it. - await page.getByTestId("lobby-nav-games-private-games").click(); + // Paid tier exposes the `private games` sub-panel; navigate to + // it via the dev nav surface so the spec is viewport-agnostic + // (the mobile sidebar hides the desktop submenu behind a + // dropdown — that UX is covered by lobby-submenu specs). + await page.evaluate(() => window.__galaxyNav!.go("games-private-games")); await expect(page.getByTestId("lobby-games-private-empty")).toBeVisible(); await page.getByTestId("lobby-create-button").click(); @@ -348,14 +351,16 @@ test.describe("Phase 8 — lobby flow", () => { }); await completeLogin(page); - // Navigate to the invitations sub-panel. - await page.getByTestId("lobby-nav-games-invitations").click(); + // Navigate to the invitations sub-panel via the dev nav surface + // (viewport-agnostic — the mobile sidebar hides the desktop + // submenu behind a dropdown). + await page.evaluate(() => window.__galaxyNav!.go("games-invitations")); await expect(page.getByTestId("lobby-invite-accept")).toBeVisible(); await page.getByTestId("lobby-invite-accept").click(); await expect(page.getByTestId("lobby-invite-accept")).toBeHidden(); // Active-past now has the invited game. - await page.getByTestId("lobby-nav-games-active-past").click(); + await page.evaluate(() => window.__galaxyNav!.go("games-active-past")); await expect(page.getByTestId("lobby-my-game-card")).toContainText("Invited Game"); expect(mocks.inviteRedeemCalls).toEqual([ { gameId: "private-1", inviteId: "invite-1" }, diff --git a/ui/frontend/tests/e2e/lobby-tier-gate.spec.ts b/ui/frontend/tests/e2e/lobby-tier-gate.spec.ts index 156f75e..ae2ab93 100644 --- a/ui/frontend/tests/e2e/lobby-tier-gate.spec.ts +++ b/ui/frontend/tests/e2e/lobby-tier-gate.spec.ts @@ -181,8 +181,10 @@ test.describe("F8-04b — tier gate", () => { await expect(privateGamesEntry).toBeVisible(); // Free-tier callers reach the create form via the DEV-visible - // entry, but the backend still rejects the POST. - await privateGamesEntry.click(); + // entry, but the backend still rejects the POST. Use the dev + // nav surface so the assertion works on mobile too (the mobile + // sidebar tucks the private-games entry behind a dropdown). + await page.evaluate(() => window.__galaxyNav!.go("games-private-games")); await page.getByTestId("lobby-create-button").click(); await expect(page.getByTestId("lobby-create-form")).toBeVisible(); @@ -198,7 +200,7 @@ test.describe("F8-04b — tier gate", () => { }); await completeLogin(page); - await page.getByTestId("lobby-nav-games-private-games").click(); + await page.evaluate(() => window.__galaxyNav!.go("games-private-games")); await page.getByTestId("lobby-create-button").click(); await expect(page.getByTestId("lobby-create-form")).toBeVisible(); @@ -227,7 +229,7 @@ test.describe("F8-04b — tier gate", () => { const mocks = await mockGatewayTier(page, { isPaid: true }); await completeLogin(page); - await page.getByTestId("lobby-nav-games-private-games").click(); + await page.evaluate(() => window.__galaxyNav!.go("games-private-games")); await expect(page.getByTestId("lobby-games-private-empty")).toBeVisible(); await expect(page.getByTestId("lobby-create-button")).toBeVisible(); await page.getByTestId("lobby-create-button").click(); diff --git a/ui/frontend/tests/e2e/profile-screen.spec.ts b/ui/frontend/tests/e2e/profile-screen.spec.ts index 476992d..c67c089 100644 --- a/ui/frontend/tests/e2e/profile-screen.spec.ts +++ b/ui/frontend/tests/e2e/profile-screen.spec.ts @@ -330,10 +330,10 @@ test.describe("F8-04 — profile screen", () => { await expect(page.getByTestId("lobby-account-name")).toContainText("Pilot"); // Navigate back to the games section. F8-04b replaced the bare - // `Overview` page with a `games` parent + sub-panels; clicking - // the parent resolves to the first visible sub-panel - // (`recruitment` for a no-games session). - await page.getByTestId("lobby-nav-games").click(); + // `Overview` page with a `games` parent + sub-panels; the dev + // nav surface goes straight to the canonical landing + // (`games-recruitment`) so the assertion is viewport-agnostic. + await page.evaluate(() => window.__galaxyNav!.go("games-recruitment")); await expect(page.getByTestId("lobby-recruitment-empty")).toBeVisible(); await expect(page.getByTestId("lobby-account-name")).toContainText("Pilot"); diff --git a/ui/frontend/tests/e2e/ship-group-send.spec.ts b/ui/frontend/tests/e2e/ship-group-send.spec.ts index 6ef068b..2894743 100644 --- a/ui/frontend/tests/e2e/ship-group-send.spec.ts +++ b/ui/frontend/tests/e2e/ship-group-send.spec.ts @@ -135,9 +135,13 @@ async function bootSession(page: Page): Promise { } async function loadSyntheticGame(page: Page): Promise { - // Seeded session → the dispatcher renders the lobby; the synthetic - // loader lives there behind the dev-affordances flag. + // Seeded session → the dispatcher renders the lobby. F8-04b moved + // the synthetic-report loader off of Overview into its own + // dev-only top-level screen; jump straight to it via the dev nav + // surface so the spec is viewport-agnostic. await page.goto("/"); + await page.waitForFunction(() => window.__galaxyNav !== undefined); + await page.evaluate(() => window.__galaxyNav!.go("synthetic-reports")); await expect(page.getByTestId("lobby-synthetic-section")).toBeVisible(); const file = page.getByTestId("lobby-synthetic-file"); await file.setInputFiles({