import { content } from "@deadhead/content"; import { describe, expect, it } from "vitest"; import { completedGoals, type GoalProgress } from "../src/index"; const goals = content.onboardingGoals; /** Just after the deal: a ship, an Earth bay and the full loan. */ const fresh: GoalProgress = { ownShipDeliveries: 0, skillPointsSpent: 0, shipsOwned: 1, pilotsHired: 0, locationsDiscovered: 0, dealAccepted: true, loanBalance: content.config.dealLoanAmount, }; const isComplete = (id: string, progress: GoalProgress) => completedGoals(goals, progress).includes(id); /** For each goal: a summary just short of its condition, and one that meets it. */ const cases: [string, Partial, Partial][] = [ ["first-own-delivery", { ownShipDeliveries: 0 }, { ownShipDeliveries: 1 }], ["first-skill-point", { skillPointsSpent: 0 }, { skillPointsSpent: 1 }], ["second-ship", { shipsOwned: 1 }, { shipsOwned: 2 }], ["first-hire", { pilotsHired: 0 }, { pilotsHired: 1 }], ["first-discovery", { locationsDiscovered: 0 }, { locationsDiscovered: 1 }], ["loan-paid-off", { loanBalance: 1 }, { loanBalance: 0 }], ]; describe("onboarding goal evaluation", () => { it("covers every goal in content, in order", () => { expect(cases.map(([id]) => id)).toEqual(goals.map((g) => g.id)); }); it.each(cases)( "%s: incomplete just short of the condition, complete once met", (id, short, met) => { expect(isComplete(id, { ...fresh, ...short })).toBe(false); expect(isComplete(id, { ...fresh, ...met })).toBe(true); }, ); it("does not count a loan as paid off before the deal", () => { expect(isComplete("loan-paid-off", { ...fresh, dealAccepted: false, loanBalance: 0 })).toBe( false, ); }); it("returns completed goals in content order, identically for identical inputs", () => { const progress: GoalProgress = { ...fresh, pilotsHired: 3, ownShipDeliveries: 5 }; expect(completedGoals(goals, progress)).toEqual(["first-own-delivery", "first-hire"]); expect(completedGoals(goals, progress)).toEqual(completedGoals(goals, { ...progress })); }); });