82 lines
3.0 KiB
TypeScript
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|