deadhead-space-freight-tycoon/apps/server/test/new-company.test.ts

78 lines
2.9 KiB
TypeScript

import { content } from "@deadhead/content";
import { playerStateSchema, type PlayerState } from "@deadhead/schema";
import { eq } from "drizzle-orm";
import { describe, expect, it } from "vitest";
import { players } from "../src/db/schema";
import { resolveArrivalsJob } from "../src/jobs/definitions";
import { setCredits, useTestDatabase } from "./db";
import {
call,
getState,
insertDispatch,
signUp,
signUpOwner,
testContract,
useTestApp,
} from "./game";
const database = useTestDatabase();
const testApp = useTestApp(database);
/** The parts of a state that must match a brand-new guest's (ids differ). */
const shape = (s: PlayerState) => ({
credits: s.company.credits,
loanBalance: s.company.loanBalance,
ships: s.ships.length,
bays: s.bays.length,
pilots: s.pilots.map((p) => ({
isAvatar: p.isAvatar,
locationId: p.locationId,
level: p.level,
assignedShipId: p.assignedShipId,
})),
discovered: s.locations.filter((l) => l.discovered).map((l) => l.id),
tutorial: s.tutorial,
activeDispatches: s.activeDispatches.length,
summaries: s.summaries.length,
goals: s.goals,
});
describe("start a new company (Step 10K.6)", () => {
it("turns a mid-game company back into a fresh guest start, with a new world seed", async () => {
const { app, clock } = testApp();
const { db } = database();
const owner = await signUpOwner(app, db);
await setCredits(db, owner.playerId, 50_000);
await call(app, owner, "POST", "/api/bays", { locationId: "moon" });
await call(app, owner, "POST", `/api/ships/${owner.shipId}/upgrades`, { upgradeId: "engines" });
const flight = await insertDispatch(db, {
playerId: owner.playerId,
shipId: owner.shipId,
pilotId: owner.avatarId,
departAt: clock.now,
contract: testContract(),
});
const [before] = await db.select().from(players).where(eq(players.id, owner.playerId));
const response = await call(app, owner, "POST", "/api/company/new", {});
expect(response.statusCode).toBe(200);
const fresh = playerStateSchema.parse(response.json());
const guest = await signUp(app);
expect(shape(fresh)).toEqual(shape(await getState(app, guest)));
expect(fresh.tutorial).toMatchObject({ loanerLocationId: "earth", runsCompleted: 0 });
expect(fresh.company.credits).toBe(content.config.startingCredits);
expect(shape(fresh).discovered.sort()).toEqual(["earth", "moon"]);
const [after] = await db.select().from(players).where(eq(players.id, owner.playerId));
expect(after!.worldSeed).not.toBe(before!.worldSeed);
expect(after!.id).toBe(before!.id);
// The old flight's arrival job finds nothing and changes nothing.
clock.now = flight.arrivalAt + 1000;
await expect(
resolveArrivalsJob({ db, clock: clock.read }, { playerId: owner.playerId }),
).resolves.toBeUndefined();
expect(shape(await getState(app, owner))).toEqual(shape(fresh));
});
});