// Phase 12 end-to-end coverage for the order composer skeleton. The // shell makes no gateway calls in this spec — the boot flow seeds an // authenticated session and a draft directly through `/__debug/store`, // then navigates into `/games//map` and exercises the order tab. // // Persistence is covered by reloading the page mid-spec: the // `OrderDraftStore` re-reads the same cache row on the next mount, // so the rendered list survives the round-trip. import { expect, test, type Page } from "@playwright/test"; // `window.__galaxyDebug` is owned by `routes/__debug/store/+page.svelte` // and typed by `tests/e2e/storage-keypair-persistence.spec.ts`. The // merged global declaration covers every helper this spec calls. const SESSION_ID = "phase-12-order-session"; const GAME_ID = "test-order"; const SEED = [ { kind: "placeholder" as const, id: "cmd-a", label: "first command" }, { kind: "placeholder" as const, id: "cmd-b", label: "second command" }, { kind: "placeholder" as const, id: "cmd-c", label: "third command" }, ]; async function bootDebug(page: Page): Promise { await page.goto("/__debug/store"); await expect(page.getByTestId("debug-store-ready")).toBeVisible(); await page.waitForFunction(() => window.__galaxyDebug?.ready === true); } async function seedShell(page: Page): Promise { await bootDebug(page); await page.evaluate(() => window.__galaxyDebug!.clearSession()); await page.evaluate( (id) => window.__galaxyDebug!.setDeviceSessionId(id), SESSION_ID, ); await page.evaluate( ({ gameId, commands }) => window.__galaxyDebug!.clearOrderDraft(gameId).then(() => window.__galaxyDebug!.seedOrderDraft(gameId, commands), ), { gameId: GAME_ID, commands: SEED }, ); } async function openOrderTool(page: Page, isMobile: boolean): Promise { if (isMobile) { await page.getByTestId("bottom-tab-order").click(); } else { await page.getByTestId("sidebar-tab-order").click(); } await expect(page.getByTestId("sidebar-tool-order")).toBeVisible(); } async function expectSeededRows(page: Page): Promise { const list = page.getByTestId("order-list"); await expect(list).toBeVisible(); for (let i = 0; i < SEED.length; i++) { const row = page.getByTestId(`order-command-${i}`); await expect(row).toBeVisible(); await expect(row.getByTestId(`order-command-label-${i}`)).toHaveText( SEED[i]!.label, ); } await expect(page.getByTestId("order-empty")).toHaveCount(0); } test("seeded draft renders on the order tab and survives a reload", async ({ page, }, testInfo) => { const isMobile = testInfo.project.name.startsWith("chromium-mobile"); await seedShell(page); await page.goto(`/games/${GAME_ID}/map`); await expect(page.getByTestId("game-shell")).toBeVisible(); await expect(page.getByTestId("active-view-map")).toBeVisible(); await openOrderTool(page, isMobile); await expectSeededRows(page); await page.reload(); await expect(page.getByTestId("game-shell")).toBeVisible(); await openOrderTool(page, isMobile); await expectSeededRows(page); }); test("removing a command from the order tab persists the removal", async ({ page, }, testInfo) => { const isMobile = testInfo.project.name.startsWith("chromium-mobile"); await seedShell(page); await page.goto(`/games/${GAME_ID}/map`); await expect(page.getByTestId("game-shell")).toBeVisible(); await openOrderTool(page, isMobile); await expect(page.getByTestId("order-command-1")).toBeVisible(); await page.getByTestId("order-command-delete-1").click(); // The remaining two commands shift up by one slot. await expect(page.getByTestId("order-command-label-0")).toHaveText( SEED[0]!.label, ); await expect(page.getByTestId("order-command-label-1")).toHaveText( SEED[2]!.label, ); await expect(page.getByTestId("order-command-2")).toHaveCount(0); await page.reload(); await expect(page.getByTestId("game-shell")).toBeVisible(); await openOrderTool(page, isMobile); await expect(page.getByTestId("order-command-label-0")).toHaveText( SEED[0]!.label, ); await expect(page.getByTestId("order-command-label-1")).toHaveText( SEED[2]!.label, ); await expect(page.getByTestId("order-command-2")).toHaveCount(0); }); test("empty draft renders the empty-state copy", async ({ page, }, testInfo) => { const isMobile = testInfo.project.name.startsWith("chromium-mobile"); await bootDebug(page); await page.evaluate(() => window.__galaxyDebug!.clearSession()); await page.evaluate( (id) => window.__galaxyDebug!.setDeviceSessionId(id), SESSION_ID, ); await page.evaluate( (gameId) => window.__galaxyDebug!.clearOrderDraft(gameId), GAME_ID, ); await page.goto(`/games/${GAME_ID}/map`); await expect(page.getByTestId("game-shell")).toBeVisible(); await openOrderTool(page, isMobile); await expect(page.getByTestId("order-empty")).toBeVisible(); await expect(page.getByTestId("order-list")).toHaveCount(0); });