Files
healer-man/src/game/tbcDifficultyContract.test.ts
T
2026-09-09 11:21:33 -04:00

82 lines
3.0 KiB
TypeScript

import { describe, expect, it } from "vitest";
import campaign from "../../dungeon-pipeline/dungeon-campaign.json";
import { requireDungeonDefinition } from "./dungeonRegistry";
import type { DungeonDifficultyVariant, DungeonSourceRecipe } from "./dungeonTypes";
const recipeModules = import.meta.glob<DungeonSourceRecipe>(
"../../dungeon-pipeline/recipes/*.json",
{ eager: true, import: "default" },
);
const TBC_DUNGEON_IDS = campaign.dungeons
.filter((dungeon) => dungeon.source === "burning-crusade")
.map((dungeon) => dungeon.slug);
function requireRecipe(dungeonId: string): DungeonSourceRecipe {
const path = `../../dungeon-pipeline/recipes/${dungeonId}.json`;
const recipe = recipeModules[path];
if (!recipe) throw new Error(`Missing Burning Crusade recipe: ${path}`);
return recipe;
}
function expectSelectableDifficultyContract(
label: string,
variants: readonly DungeonDifficultyVariant[],
): void {
const normal = variants.find((variant) => variant.id === "normal");
const heroic = variants.find((variant) => variant.id === "heroic");
expect(normal, `${label}:normal`).toMatchObject({
difficulty: "normal",
spawnMask: 1,
});
expect(heroic, `${label}:heroic`).toMatchObject({
difficulty: "heroic",
spawnMask: 2,
levelRange: [70, 70],
});
expect(new Set(variants.map((variant) => variant.id)).size, `${label}:unique-ids`)
.toBe(variants.length);
}
describe("Burning Crusade difficulty contract", () => {
it("advertises selectable normal and level-70 heroic variants in every recipe and compiled definition", () => {
expect(TBC_DUNGEON_IDS).toHaveLength(14);
for (const dungeonId of TBC_DUNGEON_IDS) {
const recipe = requireRecipe(dungeonId);
const definition = requireDungeonDefinition(dungeonId);
expect(recipe.slug, dungeonId).toBe(dungeonId);
expect(recipe.expansion, dungeonId).toBe("burning-crusade");
expectSelectableDifficultyContract(`${dungeonId}:recipe`, recipe.difficultyVariants);
expectSelectableDifficultyContract(`${dungeonId}:runtime`, definition.difficultyVariants);
}
});
it("only uses encounter difficulty guards that players can select", () => {
for (const dungeonId of TBC_DUNGEON_IDS) {
const definition = requireDungeonDefinition(dungeonId);
const selectableDifficultyIds = new Set(
definition.difficultyVariants.map((variant) => variant.id),
);
for (const encounter of definition.encounters ?? []) {
for (const rule of encounter.rules) {
for (const guard of rule.guards ?? []) {
if (guard.kind !== "difficulty") continue;
expect(guard.difficultyIds.length, `${dungeonId}:${encounter.id}:${rule.id}`)
.toBeGreaterThan(0);
for (const difficultyId of guard.difficultyIds) {
expect(
selectableDifficultyIds.has(difficultyId),
`${dungeonId}:${encounter.id}:${rule.id}:${difficultyId}`,
).toBe(true);
}
}
}
}
}
});
});