ui/order-draft: silence hydrate path on non-UUID game ids + Phase 10 e2e fixture upgrade

Phase 14's auto-sync calls `uuidToHiLo` on every layout boot. The
existing Phase 10 e2e specs use a placeholder string `test-shell`
as the game id, which throws in the FBS request encoder and
surfaced as a noisy `console.warn` plus a flaky webkit-desktop
test on the local-ci ARM runner.

`OrderDraftStore.hydrateFromServer` and `scheduleSync` now skip
when the active game id isn't a real UUID — the auto-sync path is
inert for fixture data and the placeholder-warning is gone. The
Phase 10 spec switches to a deterministic UUID
(`10101010-1010-1010-1010-101010101010`) so future Phase 14+
specs don't have to special-case it.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Ilia Denisov
2026-05-09 14:19:47 +02:00
parent 6d6a384bee
commit c4f1409329
2 changed files with 26 additions and 4 deletions
@@ -131,6 +131,14 @@ export class OrderDraftStore {
}): Promise<void> { }): Promise<void> {
if (this.status !== "ready") return; if (this.status !== "ready") return;
this.client = opts.client; this.client = opts.client;
// Guard against placeholder game ids the Phase 10 e2e specs
// still use — auto-sync needs a real UUID for the FBS request
// envelope, and a parser exception here would only be visible
// as a noisy `console.warn` deep in the layout boot path.
if (!isUuid(this.gameId)) {
this.syncStatus = "idle";
return;
}
this.syncStatus = "syncing"; this.syncStatus = "syncing";
this.syncError = null; this.syncError = null;
try { try {
@@ -232,6 +240,9 @@ export class OrderDraftStore {
private scheduleSync(): void { private scheduleSync(): void {
if (this.client === null) return; if (this.client === null) return;
// Same UUID guard as `hydrateFromServer` — placeholder game
// ids in test fixtures must not blow up the auto-sync path.
if (!isUuid(this.gameId)) return;
if (this.syncing !== null) { if (this.syncing !== null) {
this.pending = true; this.pending = true;
return; return;
@@ -379,6 +390,12 @@ export class OrderDraftStore {
} }
} }
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
function isUuid(value: string): boolean {
return UUID_RE.test(value);
}
function validateCommand(cmd: OrderCommand): CommandStatus { function validateCommand(cmd: OrderCommand): CommandStatus {
switch (cmd.kind) { switch (cmd.kind) {
case "planetRename": case "planetRename":
+9 -4
View File
@@ -1,7 +1,9 @@
// Phase 10 end-to-end coverage for the in-game shell. Every spec // Phase 10 end-to-end coverage for the in-game shell. Every spec
// boots an authenticated session through `/__debug/store` (no // boots an authenticated session through `/__debug/store` (the
// gateway calls — the shell makes none in Phase 10), navigates into // in-game shell makes a handful of gateway calls — for the lobby
// `/games/test-shell/map`, and exercises one slice of the chrome: // record, the report, and the order read-back; we don't mock them
// here, the shell tolerates ECONNREFUSED), navigates into
// `/games/<game-id>/map`, and exercises one slice of the chrome:
// header navigation, sidebar tab preservation, mobile bottom-tabs, // header navigation, sidebar tab preservation, mobile bottom-tabs,
// and the breakpoint switches at 768 / 1024 px. // and the breakpoint switches at 768 / 1024 px.
@@ -14,7 +16,10 @@ import { expect, test, type Page } from "@playwright/test";
// `setDeviceSessionId`); the merged global declaration covers both. // `setDeviceSessionId`); the merged global declaration covers both.
const SESSION_ID = "phase-10-shell-session"; const SESSION_ID = "phase-10-shell-session";
const GAME_ID = "test-shell"; // GAME_ID has to be a real UUID — Phase 14's auto-sync calls
// `uuidToHiLo` on it for the FBS request envelope, and an
// arbitrary string would throw on every layout boot.
const GAME_ID = "10101010-1010-1010-1010-101010101010";
async function bootShell(page: Page): Promise<void> { async function bootShell(page: Page): Promise<void> {
await page.goto("/__debug/store"); await page.goto("/__debug/store");