fix(ui-e2e): Phase 29 map-toggles spec passes across all four projects
Tests · UI / test (push) Failing after 10m52s
Tests · UI / test (push) Failing after 10m52s
Three independent bugs in `tests/e2e/map-toggles.spec.ts` made the fresh-Phase-29 suite red on CI #216: 1. `visiblePlanets` filtered on `p.id < 1_000_000`, which JS interprets in signed space — high-bit-prefix primitives (cargo route 0x80…, battle 0xa0…, bombing 0xc0…) are stored as negative Numbers and leaked into the planet list. Filter switched to a `0 < id < 1e7` window that matches the engine planet-number range exactly. 2. The `visibleHighBitCount` helper now ToUint32-converts the id before masking so the bitmask comparison works regardless of whether the id is stored as positive or negative. 3. The fog and wrap-mode tests read the renderer state synchronously after the click — the Svelte effect re-runs asynchronously, so the tests saw stale state. Both now `waitForFunction` on the canonical "settled" signal: empty fog circles for the fog flip, and a new `getMapMode()` debug accessor for the wrap-mode remount. Renderer side: registers a `MapModeProvider` next to the existing camera / fog providers and exposes `getMapMode()` through the debug surface. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -69,6 +69,7 @@ preference the store already manages.
|
||||
installRendererDebugSurface,
|
||||
registerMapCameraProvider,
|
||||
registerMapFogProvider,
|
||||
registerMapModeProvider,
|
||||
registerMapPickStateProvider,
|
||||
registerMapPrimitivesProvider,
|
||||
type MapCameraSnapshot,
|
||||
@@ -505,11 +506,15 @@ preference the store already manages.
|
||||
const detachFog = registerMapFogProvider(() => ({
|
||||
circles: currentFogCircles.map((c) => ({ ...c })),
|
||||
}) satisfies MapFogSnapshot);
|
||||
const detachMode = registerMapModeProvider(() =>
|
||||
handle === null ? null : handle.getMode(),
|
||||
);
|
||||
detachDebugProviders = (): void => {
|
||||
detachPrim();
|
||||
detachPick();
|
||||
detachCamera();
|
||||
detachFog();
|
||||
detachMode();
|
||||
};
|
||||
mountedTurn = report.turn;
|
||||
mountedGameId = targetGameId;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
// lazily on every read so the returned data always reflects the
|
||||
// current frame, not the value at registration time.
|
||||
|
||||
import type { Primitive, PrimitiveID } from "../map/world";
|
||||
import type { Primitive, PrimitiveID, WrapMode } from "../map/world";
|
||||
|
||||
/** Snapshot returned by `getMapPrimitives()`. The renderer applies
|
||||
* pick-mode dimming via the underlying `Graphics.alpha`, so the
|
||||
@@ -73,11 +73,13 @@ type PrimitivesProvider = () => readonly MapPrimitiveSnapshot[];
|
||||
type PickStateProvider = () => MapPickStateSnapshot;
|
||||
type CameraProvider = () => MapCameraSnapshot | null;
|
||||
type FogProvider = () => MapFogSnapshot;
|
||||
type ModeProvider = () => WrapMode | null;
|
||||
|
||||
let primitivesProvider: PrimitivesProvider | null = null;
|
||||
let pickStateProvider: PickStateProvider | null = null;
|
||||
let cameraProvider: CameraProvider | null = null;
|
||||
let fogProvider: FogProvider | null = null;
|
||||
let modeProvider: ModeProvider | null = null;
|
||||
|
||||
/**
|
||||
* registerMapPrimitivesProvider attaches a provider that yields the
|
||||
@@ -134,6 +136,22 @@ export function registerMapFogProvider(provider: FogProvider): () => void {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* registerMapModeProvider attaches a provider that yields the
|
||||
* renderer's current `WrapMode` ('torus' or 'no-wrap'). Used by
|
||||
* Phase 29 e2e specs to await the renderer remount after a
|
||||
* wrap-mode flip — `getMapCamera()` alone is not a reliable signal
|
||||
* because the same camera survives across a remount, so the spec
|
||||
* watches the mode flip instead. Same idempotent semantics as the
|
||||
* other providers.
|
||||
*/
|
||||
export function registerMapModeProvider(provider: ModeProvider): () => void {
|
||||
modeProvider = provider;
|
||||
return () => {
|
||||
if (modeProvider === provider) modeProvider = null;
|
||||
};
|
||||
}
|
||||
|
||||
const EMPTY_PICK_STATE: MapPickStateSnapshot = {
|
||||
active: false,
|
||||
sourcePlanetNumber: null,
|
||||
@@ -166,12 +184,20 @@ export function getMapFog(): MapFogSnapshot {
|
||||
return fogProvider?.() ?? { circles: [] };
|
||||
}
|
||||
|
||||
/** Pulls the renderer's current `WrapMode`. Returns `null` when no
|
||||
* map view is mounted (the surface is queried during navigation or
|
||||
* before the first render). */
|
||||
export function getMapMode(): WrapMode | null {
|
||||
return modeProvider?.() ?? null;
|
||||
}
|
||||
|
||||
interface RendererDebugWindow {
|
||||
__galaxyDebug?: {
|
||||
getMapPrimitives?: () => readonly MapPrimitiveSnapshot[];
|
||||
getMapPickState?: () => MapPickStateSnapshot;
|
||||
getMapCamera?: () => MapCameraSnapshot | null;
|
||||
getMapFog?: () => MapFogSnapshot;
|
||||
getMapMode?: () => WrapMode | null;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
}
|
||||
@@ -195,6 +221,7 @@ export function installRendererDebugSurface(): () => void {
|
||||
getMapPickState,
|
||||
getMapCamera,
|
||||
getMapFog,
|
||||
getMapMode,
|
||||
};
|
||||
win.__galaxyDebug = surface;
|
||||
return (): void => {
|
||||
@@ -215,5 +242,8 @@ export function installRendererDebugSurface(): () => void {
|
||||
if (current.getMapFog === getMapFog) {
|
||||
delete current.getMapFog;
|
||||
}
|
||||
if (current.getMapMode === getMapMode) {
|
||||
delete current.getMapMode;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user