deadhead-space-freight-tycoon/packages/content/test/locations.test.ts

77 lines
2.7 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { cargoTypes, goods, locationSchema, locations } from "../src/index";
const cargoTypeIds = cargoTypes.map((c) => c.id);
describe("locations", () => {
it("all pass the schema", () => {
for (const location of locations) {
expect(() => locationSchema.parse(location)).not.toThrow();
}
});
it("has exactly eight locations with unique ids (CR-016)", () => {
expect(locations).toHaveLength(8);
expect(new Set(locations.map((l) => l.id)).size).toBe(8);
});
it("starts with exactly Earth and Moon discovered", () => {
const discovered = locations.filter((l) => l.startsDiscovered).map((l) => l.id);
expect(discovered.sort()).toEqual(["earth", "moon"]);
});
it("references only existing goods, and cargo classes in its class mix", () => {
const goodIds = goods.map((g) => g.id);
for (const location of locations) {
for (const goodId of [...location.produces, ...location.demands]) {
expect(goodIds).toContain(goodId);
}
const { produces, demands } = location.cargoClassMix;
for (const cargoId of [...produces, ...demands]) expect(cargoTypeIds).toContain(cargoId);
}
});
it("has at least one shipper per location (CR-007)", () => {
for (const location of locations) expect(location.shippers.length).toBeGreaterThan(0);
});
it("orders fuel prices Jupiter < Europa < Ceres < Io < Moon < Venus < Mars < Earth (CR-016)", () => {
const price = (id: string) => locations.find((l) => l.id === id)!.fuelPrice;
const order = [
"jupiter-cloud-platform",
"europa-ice-station",
"ceres-station",
"io-sulfur-works",
"moon",
"venus-cloud-city",
"mars",
"earth",
];
for (let i = 1; i < order.length; i++) {
expect(price(order[i - 1]!), order[i]).toBeLessThan(price(order[i]!));
}
});
it("sells fuel at every base location (CR-015 §3)", () => {
for (const location of locations) expect(location.sellsFuel, location.id).toBe(true);
});
it("gives every location its own map sprite key (CR-003)", () => {
const sprites = locations.map((x) => x.sprite);
for (const sprite of sprites) expect(sprite).toMatch(/^[a-z][a-z-]*$/);
expect(new Set(sprites).size).toBe(sprites.length);
});
it("gives every location a positive launch range factor (CR-012)", () => {
for (const l of locations) expect(l.launchRangeFactor, l.id).toBeGreaterThan(0);
const factor = (id: string) => locations.find((l) => l.id === id)!.launchRangeFactor;
expect([
factor("earth"),
factor("moon"),
factor("mars"),
factor("ceres-station"),
factor("jupiter-cloud-platform"),
]).toEqual([1, 1.3, 1.15, 1.3, 1]);
});
});