78 lines
2.9 KiB
TypeScript
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));
|
|
});
|
|
});
|