deadhead-space-freight-tycoon/apps/server/test/skills.test.ts

62 lines
2.4 KiB
TypeScript

import { content } from "@deadhead/content";
import { errorResponseSchema, pilotResponseSchema } from "@deadhead/schema";
import { eq } from "drizzle-orm";
import { describe, expect, it } from "vitest";
import { pilots } from "../src/db/schema";
import { makeOwner, useTestDatabase } from "./db";
import { call, signUp, useTestApp, type Guest } from "./game";
const database = useTestDatabase();
const testApp = useTestApp(database);
/** An owner whose avatar has `xp` XP and the given skills and points spent. */
async function pilotWith(xp: number, skills: Record<string, number> = {}, spent = 0) {
const guest = await signUp(testApp().app);
await makeOwner(database().db, guest.playerId, guest.avatarId);
await database()
.db.update(pilots)
.set({ xp, skills, skillPointsSpent: spent })
.where(eq(pilots.id, guest.avatarId));
return guest;
}
function spend(guest: Guest, skillId: string) {
return call(testApp().app, guest, "POST", `/api/pilots/${guest.avatarId}/skills`, { skillId });
}
const errorCode = (response: { json(): unknown }) =>
errorResponseSchema.parse(response.json()).error.code;
// Level 1 gives `skillPointsPerLevel` points.
const level1Xp = content.config.pilotLevelXpThresholds[0]!;
describe("spending skill points", () => {
it("raises the skill by one and uses one point", async () => {
const guest = await pilotWith(level1Xp);
const response = await spend(guest, "heavy-cargo");
expect(response.statusCode).toBe(200);
const { pilot } = pilotResponseSchema.parse(response.json());
expect(pilot.skills).toEqual({ "heavy-cargo": 1 });
expect(pilot.skillPointsAvailable).toBe(content.config.skillPointsPerLevel - 1);
});
it("refuses with no points available", async () => {
const guest = await pilotWith(0);
const response = await spend(guest, "heavy-cargo");
expect(response.statusCode).toBe(409);
expect(errorCode(response)).toBe("no-skill-points");
});
it("refuses a skill already at max level", async () => {
const guest = await pilotWith(level1Xp, { "long-haul": 5 });
expect(errorCode(await spend(guest, "long-haul"))).toBe("skill-maxed");
});
it("refuses an unknown skill", async () => {
const guest = await pilotWith(level1Xp);
const response = await spend(guest, "juggling");
expect(response.statusCode).toBe(404);
expect(errorCode(response)).toBe("unknown-skill");
});
});