103 lines
2.8 KiB
TypeScript
103 lines
2.8 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import type { z } from "zod";
|
|
import {
|
|
cargoTypeSchema,
|
|
gameConfigSchema,
|
|
locationSchema,
|
|
shipModelSchema,
|
|
skillSchema,
|
|
} from "../src/index";
|
|
|
|
const validLocation = {
|
|
id: "earth",
|
|
name: "Earth",
|
|
type: "atmospheric-world",
|
|
landingRequirement: "atmospheric",
|
|
body: "earth",
|
|
launchCostMultiplier: 3,
|
|
startsDiscovered: true,
|
|
bayLeasePrice: 5000,
|
|
produces: ["standard"],
|
|
demands: ["heavy"],
|
|
};
|
|
|
|
const validShipModel = {
|
|
id: "courier",
|
|
name: "Courier",
|
|
archetype: "courier",
|
|
price: 20000,
|
|
cruiseSpeedKmPerGameHour: 300000,
|
|
cargoCapacityTonnes: 10,
|
|
fuelRangeMillionKm: 5,
|
|
hullRating: 1,
|
|
landingClass: "atmospheric",
|
|
overheadGameHours: 2,
|
|
fuelCostPerMillionKm: 100,
|
|
};
|
|
|
|
const validCargoType = {
|
|
id: "standard",
|
|
name: "Standard",
|
|
basePayPerTonnePerMillionKm: 10,
|
|
tierPayMultiplier: 1,
|
|
requiredSkillId: null,
|
|
};
|
|
|
|
const validSkill = {
|
|
id: "long-haul",
|
|
name: "Long Haul",
|
|
maxLevel: 5,
|
|
description: "Access to longer routes.",
|
|
};
|
|
|
|
const validGameConfig = {
|
|
timeCompression: 60,
|
|
epoch: { realStart: "2026-01-01T00:00:00Z", ephemerisDate: "2100-01-01T00:00:00Z" },
|
|
startingCredits: 0,
|
|
tutorialPayoutShare: 0.2,
|
|
contractBoardSize: 8,
|
|
tutorialBoardSize: 50,
|
|
contractBoardPeriodRealMinutes: 60,
|
|
firstContactChance: 0.1,
|
|
firstContactPayoutMultiplier: 2,
|
|
contractMassTonnes: { min: 1, max: 100 },
|
|
longHaulCutoffsMillionKm: [100, 200, 300, 400, 500],
|
|
xpPerDelivery: { base: 10, perMillionKm: 0.1, perCargoTier: 5 },
|
|
pilotLevelXpThresholds: [100, 250, 500],
|
|
skillPointsPerLevel: 1,
|
|
pilotHireCost: 1000,
|
|
pilotPayPerDelivery: 100,
|
|
};
|
|
|
|
const cases: [string, z.ZodType, Record<string, unknown>][] = [
|
|
["Location", locationSchema, validLocation],
|
|
["ShipModel", shipModelSchema, validShipModel],
|
|
["CargoType", cargoTypeSchema, validCargoType],
|
|
["Skill", skillSchema, validSkill],
|
|
["GameConfig", gameConfigSchema, validGameConfig],
|
|
];
|
|
|
|
describe.each(cases)("%s schema", (_name, schema, valid) => {
|
|
it("accepts a valid example", () => {
|
|
expect(schema.safeParse(valid).success).toBe(true);
|
|
});
|
|
|
|
it.each(Object.keys(valid))("rejects an object missing %s", (field) => {
|
|
const missing = { ...valid };
|
|
delete missing[field];
|
|
expect(schema.safeParse(missing).success).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("GameConfig refinements", () => {
|
|
it("rejects a mass range with min above max", () => {
|
|
const config = { ...validGameConfig, contractMassTonnes: { min: 50, max: 10 } };
|
|
expect(gameConfigSchema.safeParse(config).success).toBe(false);
|
|
});
|
|
|
|
it("rejects Long Haul cut-offs that are not increasing", () => {
|
|
const config = { ...validGameConfig, longHaulCutoffsMillionKm: [100, 100, 300] };
|
|
expect(gameConfigSchema.safeParse(config).success).toBe(false);
|
|
});
|
|
});
|