e2e: local system smoke tests (staggered bodies, explore row state, inventory accumulation) + explored-state persistence across restart
This commit is contained in:
+27
-5
@@ -8,9 +8,11 @@ import { expect, test } from '@playwright/test';
|
||||
const repoRoot = path.join(__dirname, '..');
|
||||
const composeArgs = process.env.E2E_COMPOSE_ARGS ?? '';
|
||||
|
||||
// Mirrors the /api/world response shape (lib/game/save.ts) — kept local so the spec stays self-contained.
|
||||
// Mirrors the /api/world + /api/system response shapes (lib/game/save.ts) — kept local so the spec stays self-contained.
|
||||
interface WorldSystemDto { id: number; name: string; x: number; y: number; discovered: boolean; current: boolean }
|
||||
interface WorldState { systems: WorldSystemDto[]; edges: [number, number][]; turn: number }
|
||||
interface PlanetDto { id: number; name: string; type: string; hazard: boolean; explored: boolean; parent: number | null }
|
||||
interface SystemState { systemId: number; systemName: string; planets: PlanetDto[]; inventory: { kind: string; name: string; qty: number }[]; turn: number }
|
||||
|
||||
test('app survives a container restart (stack + volume persistence)', async ({ page }) => {
|
||||
test.setTimeout(180_000);
|
||||
@@ -28,7 +30,22 @@ test('app survives a container restart (stack + volume persistence)', async ({ p
|
||||
const targetId = edge[0] === currentId ? edge[1] : edge[0];
|
||||
const jumpRes = await page.request.post('/api/jump', { data: { systemId: targetId } });
|
||||
expect(jumpRes.status()).toBe(200);
|
||||
const worldJumped = (await jumpRes.json()) as WorldState;
|
||||
|
||||
// Exploration baseline: scan one body so explored state + inventory must survive too.
|
||||
// (Earlier specs may have exhausted the current system, so jump until an unscanned body shows up.)
|
||||
let sysBefore = (await (await page.request.get('/api/system')).json()) as SystemState;
|
||||
for (let i = 0; !sysBefore.planets.some((p) => !p.explored) && i < 20; i++) {
|
||||
const world = (await (await page.request.get('/api/world')).json()) as WorldState;
|
||||
const curId = world.systems.find((s) => s.current)!.id;
|
||||
const e = world.edges.find(([a, b]) => a === curId || b === curId)!;
|
||||
const tId = e[0] === curId ? e[1] : e[0];
|
||||
expect((await page.request.post('/api/jump', { data: { systemId: tId } })).status()).toBe(200);
|
||||
sysBefore = (await (await page.request.get('/api/system')).json()) as SystemState;
|
||||
}
|
||||
const targetPlanet = sysBefore.planets.find((p) => !p.explored)!;
|
||||
const exploreRes = await page.request.post('/api/explore', { data: { planetId: targetPlanet.id } });
|
||||
expect(exploreRes.status()).toBe(200);
|
||||
const sysExplored = (await exploreRes.json()) as SystemState;
|
||||
|
||||
// Restart the app container mid-run — the named DB volume must survive it.
|
||||
execSync(`docker compose ${composeArgs} restart space-wanderer`, { cwd: repoRoot, stdio: 'pipe' });
|
||||
@@ -50,10 +67,15 @@ test('app survives a container restart (stack + volume persistence)', async ({ p
|
||||
expect(after).toBeDefined();
|
||||
expect(after!.version).toBe(before.version); // same build, not a re-seeded stack
|
||||
|
||||
// Game state survived: same turn counter and jumped-to current system as before the restart.
|
||||
// Game state survived: same turn counter and current system as before the restart.
|
||||
const worldAfter = (await (await page.request.get('/api/world')).json()) as WorldState;
|
||||
expect(worldAfter.turn).toBe(worldJumped.turn);
|
||||
expect(worldAfter.systems.find((s) => s.current)?.id).toBe(targetId);
|
||||
expect(worldAfter.turn).toBe(sysExplored.turn);
|
||||
expect(worldAfter.systems.find((s) => s.current)?.id).toBe(sysExplored.systemId);
|
||||
|
||||
// Exploration state survived too: the scanned body is still explored.
|
||||
const sysAfter = (await (await page.request.get('/api/system')).json()) as SystemState;
|
||||
expect(sysAfter.turn).toBe(sysExplored.turn);
|
||||
expect(sysAfter.planets.find((p) => p.id === targetPlanet.id)?.explored).toBe(true);
|
||||
|
||||
// The page itself serves again with the landing title.
|
||||
await page.goto('/');
|
||||
|
||||
Reference in New Issue
Block a user