v1.3.0: per-player money & reputation in engine + actions (ISS-110)
CI / build + unit + e2e (pull_request) Successful in 13m20s
CI / build + unit + e2e (pull_request) Successful in 13m20s
This commit is contained in:
@@ -5,7 +5,8 @@ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
||||
import { loadAirportsGeoJson } from '@/lib/airports';
|
||||
import { haversineKm } from '@/lib/geo';
|
||||
import { FUEL_PRICE_PER_L, PLANE_TYPES, SELL_FRACTION } from '@/lib/game/catalog';
|
||||
import { createSession } from '@/lib/auth';
|
||||
import { createSession, hashPassword } from '@/lib/auth';
|
||||
import * as schema from '@/lib/db/schema';
|
||||
import { getGameDb } from '@/lib/db/client';
|
||||
import { GET } from './route';
|
||||
|
||||
@@ -113,4 +114,23 @@ describe('GET /api/state', () => {
|
||||
expect(snap.fuelPricePerL).toBe(FUEL_PRICE_PER_L);
|
||||
expect(snap.sellFraction).toBe(SELL_FRACTION);
|
||||
});
|
||||
|
||||
it('returns the SESSION player\'s economy in account, not the local one (v1.3.0, ISS-110)', async () => {
|
||||
const inst = await getGameDb();
|
||||
// A second account with a distinct economy — rows minted like /api/register does.
|
||||
const id = 'test-player-b';
|
||||
await inst.db.insert(schema.users).values({
|
||||
id, username: 'e2e-owner-b', passwordHash: hashPassword('unused'), admin: false, createdAt: Date.now(),
|
||||
});
|
||||
await inst.db.insert(schema.players).values({
|
||||
id, provider: 'local', username: 'e2e-owner-b', cash: 12_345.67, reputation: 42.5,
|
||||
});
|
||||
const sid = await createSession(inst, id);
|
||||
|
||||
const res = await GET(new Request('http://localhost/api/state', { headers: { 'X-Flight-Session': sid } }));
|
||||
expect(res.status).toBe(200);
|
||||
const body = (await res.json()) as { account: { cash: number; reputation: number } };
|
||||
expect(body.account.cash).toBeCloseTo(12_345.67, 9); // the session player's row…
|
||||
expect(body.account.reputation).toBeCloseTo(42.5, 9); // …not the seeded local account
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,7 +3,8 @@ import { tickNow } from '@/lib/sim/engine';
|
||||
import { getStateSnapshot } from '@/lib/game/state';
|
||||
|
||||
// v1.1.0 (ISS-107): guarded — 401 without a live X-Flight-Session. The snapshot shape is
|
||||
// unchanged; per-player snapshots are a later step.
|
||||
// unchanged; per-player snapshots are a later step (#112).
|
||||
// v1.3.0 (ISS-110): `account` carries the SESSION player's economy row.
|
||||
export async function GET(req: Request) {
|
||||
const auth = await requireAuth(req);
|
||||
if (!auth.ok) return auth.response;
|
||||
@@ -11,7 +12,7 @@ export async function GET(req: Request) {
|
||||
// Tick-on-read (v0.7.0): advance the sim clock before snapshotting so every
|
||||
// read reflects current game time (expiry/finalize/spawn run inside the tick).
|
||||
await tickNow();
|
||||
return Response.json(await getStateSnapshot());
|
||||
return Response.json(await getStateSnapshot(auth.player.id));
|
||||
} catch (err) {
|
||||
console.error('failed to load game state', err);
|
||||
return Response.json({ error: 'failed to load game state' }, { status: 500 });
|
||||
|
||||
Reference in New Issue
Block a user