test(ui): migrate suite to the app-shell (state-driven navigation)
- Unit: repoint moved screen imports (lib/screens, lib/game), mock $lib/app-nav (appScreen/activeView) instead of $app/navigation, drop the removed gameId props, assert screen/view selection. - e2e: add a dev-only window.__galaxyNav affordance; specs enter a game via enterGame(...) instead of a /games/:id URL; URL assertions become content assertions (the URL stays /game/); reload uses waitUntil:"commit" (shallow routing) and mocks /rpc on game entry. - Remove the obsolete report scroll-restore test (it relied on a SvelteKit route Snapshot that no longer exists); update the missing-membership test to the new lobby-redirect+toast behaviour. Fix a stale report.svelte docstring. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,15 +7,9 @@ section is its own component under `lib/active-view/report/` — the
|
||||
data shapes are too varied for one generic table, and the
|
||||
component-per-section seam matches Phase 23's targeted-test contract.
|
||||
|
||||
Active-section highlighting and scroll save/restore land here:
|
||||
- `IntersectionObserver` rooted on the active-view-host element
|
||||
(`bind:this` in `+layout.svelte`, plumbed through
|
||||
`ACTIVE_VIEW_HOST_CONTEXT_KEY`) watches every `<section
|
||||
id="report-<slug>">` and updates a local `activeSlug` rune.
|
||||
- The matching `+page.svelte` exports a SvelteKit `Snapshot` that
|
||||
captures and restores `host.element.scrollTop`, so navigating to
|
||||
/map and back lands on the same scroll position. The save lives in
|
||||
`+page.svelte` because SvelteKit binds snapshots per route.
|
||||
Active-section highlighting lands here: an `IntersectionObserver`
|
||||
rooted on the viewport watches every `<section id="report-<slug>">`
|
||||
and updates a local `activeSlug` rune that drives the TOC highlight.
|
||||
|
||||
The 20-section list lives here as a single source of truth so the
|
||||
TOC and the body iterate the same data.
|
||||
|
||||
@@ -6,8 +6,16 @@
|
||||
// layout intercepts the `loading` and `unsupported` session states
|
||||
// before this component renders, so here `session.status` is either
|
||||
// `anonymous` (login) or `authenticated` (lobby / create / game).
|
||||
import { onMount } from "svelte";
|
||||
import { dev } from "$app/environment";
|
||||
import { session } from "$lib/session-store.svelte";
|
||||
import { appScreen } from "$lib/app-nav.svelte";
|
||||
import {
|
||||
appScreen,
|
||||
activeView,
|
||||
type AppScreen,
|
||||
type GameView,
|
||||
type GameViewState,
|
||||
} from "$lib/app-nav.svelte";
|
||||
import LoginScreen from "$lib/screens/login-screen.svelte";
|
||||
import LobbyScreen from "$lib/screens/lobby-screen.svelte";
|
||||
import LobbyCreateScreen from "$lib/screens/lobby-create-screen.svelte";
|
||||
@@ -15,6 +23,39 @@
|
||||
import { pushState } from "$app/navigation";
|
||||
import { page } from "$app/state";
|
||||
|
||||
// Dev-only navigation affordance for the Playwright e2e suite. The
|
||||
// single-URL app-shell has no per-screen / per-view routes, so a
|
||||
// spec can no longer drive the UI by `page.goto("/games/:id/:view")`.
|
||||
// Instead the suite seeds the session, loads `/` (which lands on the
|
||||
// authenticated lobby), then calls `window.__galaxyNav.enterGame(...)`
|
||||
// to switch the in-memory screen and view. Guarded by `dev` so it is
|
||||
// stripped from the production bundle — `import.meta.env.DEV` (and the
|
||||
// SvelteKit `dev` re-export) is statically `false` there, so the
|
||||
// whole `onMount` body tree-shakes away.
|
||||
type ViewParams = Omit<GameViewState, "view">;
|
||||
interface NavSurface {
|
||||
enterGame(gameId: string, view?: GameView, params?: ViewParams): void;
|
||||
select(view: GameView, params?: ViewParams): void;
|
||||
go(screen: AppScreen, opts?: { gameId?: string }): void;
|
||||
}
|
||||
type NavWindow = typeof globalThis & { __galaxyNav?: NavSurface };
|
||||
|
||||
onMount(() => {
|
||||
if (!dev) return;
|
||||
(window as NavWindow).__galaxyNav = {
|
||||
enterGame(gameId, view = "map", params = {}): void {
|
||||
activeView.select(view, params);
|
||||
appScreen.go("game", { gameId });
|
||||
},
|
||||
select(view, params = {}): void {
|
||||
activeView.select(view, params);
|
||||
},
|
||||
go(screen, opts = {}): void {
|
||||
appScreen.go(screen, opts);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
// Screen-level browser history (Back → lobby) without changing the URL.
|
||||
// On the first authenticated render, stamp a restored overlay (game /
|
||||
// lobby-create) on top of the load entry so Back falls through to lobby.
|
||||
|
||||
Reference in New Issue
Block a user