157 lines
7.3 KiB
TypeScript
157 lines
7.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
DUNGEON_CATALOG,
|
|
DUNGEON_CATEGORIES,
|
|
dungeonById,
|
|
dungeonsByCategory,
|
|
randomDungeonByCategory,
|
|
randomRegularDungeon,
|
|
randomizedBiteSizedDungeons,
|
|
randomRandomizedBiteSizedDungeon,
|
|
} from "./dungeonCatalog";
|
|
import { DUNGEON_MANIFEST } from "./dungeonManifest";
|
|
import { RUNEWAKER_DUNGEON_DEFINITIONS } from "./generated/runewakerDungeonDefinitions.generated";
|
|
import { compareDungeonReleaseOrder } from "./dungeonReleaseStage";
|
|
import availability from "./generated/dungeonAvailability.json";
|
|
import queuePolicyCatalog from "./generated/dungeonLeaderboardCatalog.generated.json";
|
|
|
|
describe("dungeon catalog", () => {
|
|
it("lists the complete campaign and bite-sized variants", () => {
|
|
expect(DUNGEON_CATALOG).toHaveLength(98);
|
|
expect(DUNGEON_CATALOG.find((dungeon) => dungeon.id === "stormwind-stockade")).toMatchObject({
|
|
id: "stormwind-stockade",
|
|
releaseStage: "beta",
|
|
available: true,
|
|
});
|
|
expect(dungeonById(DUNGEON_MANIFEST.id)).toMatchObject({
|
|
title: DUNGEON_MANIFEST.title,
|
|
mapId: DUNGEON_MANIFEST.mapId,
|
|
entranceName: DUNGEON_MANIFEST.entrance.name,
|
|
releaseStage: "alpha",
|
|
});
|
|
expect(DUNGEON_CATALOG.find((dungeon) => dungeon.id === "deadmines")).toMatchObject({
|
|
id: "deadmines",
|
|
mapId: 36,
|
|
available: true,
|
|
});
|
|
expect(DUNGEON_CATALOG.find((dungeon) => dungeon.id === "forsaken-abbey")).toMatchObject({
|
|
id: "forsaken-abbey",
|
|
category: "rom",
|
|
mapId: 102,
|
|
available: true,
|
|
});
|
|
});
|
|
|
|
it("separates WoW, RoM, and bite-sized dungeons", () => {
|
|
expect(DUNGEON_CATEGORIES.map((category) => category.id)).toEqual(["wow", "rom", "bite-sized"]);
|
|
expect(dungeonsByCategory("rom").map((dungeon) => dungeon.id).sort()).toEqual([
|
|
"forsaken-abbey",
|
|
...RUNEWAKER_DUNGEON_DEFINITIONS.map((definition) => definition.id),
|
|
].sort());
|
|
expect(dungeonsByCategory("wow")).not.toContainEqual(
|
|
expect.objectContaining({ id: "forsaken-abbey" }),
|
|
);
|
|
expect(dungeonsByCategory("rom")).toHaveLength(30);
|
|
expect(dungeonsByCategory("bite-sized").map((dungeon) => dungeon.id).sort())
|
|
.toEqual(["bite-sized-barren-caves-anglo", "bite-sized-deadmines-ship", "bite-sized-forsaken-abbey-ancalon",
|
|
"bite-sized-grafu-castle-barkud", "bite-sized-hall-of-survivors-pursuer", "bite-sized-hoto-teeth",
|
|
"bite-sized-kawaks-tomb-linobia", "bite-sized-mystic-altar-golem", "bite-sized-paspers-shrine-hafiz",
|
|
"bite-sized-stormwind-stockade", "bite-sized-utgarde-pinnacle-skadi",
|
|
"bite-sized-wailing-caverns"]);
|
|
});
|
|
|
|
it("selects another available category dungeon", () => {
|
|
expect(randomDungeonByCategory("bite-sized", "bite-sized-stormwind-stockade", () => 0)?.id)
|
|
.not.toBe("bite-sized-stormwind-stockade");
|
|
expect(randomDungeonByCategory("wow", "stormwind-stockade", () => 0)?.id)
|
|
.not.toBe("stormwind-stockade");
|
|
});
|
|
|
|
it("selects regular full dungeons without entering either Bite-Sized pool", () => {
|
|
const first = randomRegularDungeon(undefined, () => 0);
|
|
const last = randomRegularDungeon(undefined, () => 0.999999);
|
|
for (const dungeon of [first, last]) {
|
|
expect(dungeon?.available).toBe(true);
|
|
expect(["wow", "rom"]).toContain(dungeon?.category);
|
|
}
|
|
expect(randomRegularDungeon(first?.id, () => 0)?.id).not.toBe(first?.id);
|
|
expect(randomRegularDungeon(undefined, () => 0, () => false)).toBeNull();
|
|
});
|
|
|
|
it("keeps randomized replay in the separate randomized Bite-Sized location pool", () => {
|
|
expect(randomizedBiteSizedDungeons().map((dungeon) => dungeon.id))
|
|
.toEqual(["randomized-bite-sized-stormwind-stockade", "randomized-bite-sized-stormwind-stockade-available"]);
|
|
expect(randomRandomizedBiteSizedDungeon("randomized-bite-sized-stormwind-stockade", () => 0)?.id)
|
|
.toBe("randomized-bite-sized-stormwind-stockade-available");
|
|
});
|
|
|
|
it("keeps stable unique ids and resolves only catalogued dungeons", () => {
|
|
const ids = DUNGEON_CATALOG.map((dungeon) => dungeon.id);
|
|
expect(new Set(ids).size).toBe(ids.length);
|
|
expect(dungeonById(DUNGEON_MANIFEST.id)).toBe(DUNGEON_CATALOG.find((dungeon) => dungeon.id === DUNGEON_MANIFEST.id));
|
|
expect(dungeonById("missing-dungeon")).toBeNull();
|
|
});
|
|
|
|
it("keeps every queue candidate in the server policy validation catalog", () => {
|
|
const policyIds = new Set(queuePolicyCatalog.dungeons.map((dungeon) => dungeon.id));
|
|
expect(DUNGEON_CATALOG.every((dungeon) => policyIds.has(dungeon.id))).toBe(true);
|
|
});
|
|
|
|
it("provides centralized display copy for every entry", () => {
|
|
for (const dungeon of DUNGEON_CATALOG) {
|
|
expect(dungeon.location.trim()).not.toBe("");
|
|
expect(dungeon.theme.trim()).not.toBe("");
|
|
expect(dungeon.summary.trim()).not.toBe("");
|
|
}
|
|
});
|
|
|
|
it("keeps all Stockades experiences in Beta and alphabetizes each release group", () => {
|
|
expect(DUNGEON_CATALOG.filter((dungeon) => dungeon.releaseStage === "beta").map((dungeon) => dungeon.id))
|
|
.toEqual([
|
|
"bite-sized-barren-caves-anglo",
|
|
"bite-sized-forsaken-abbey-ancalon",
|
|
"bite-sized-grafu-castle-barkud",
|
|
"bite-sized-hall-of-survivors-pursuer",
|
|
"bite-sized-hoto-teeth",
|
|
"bite-sized-kawaks-tomb-linobia",
|
|
"bite-sized-mystic-altar-golem",
|
|
"bite-sized-paspers-shrine-hafiz",
|
|
"randomized-bite-sized-stormwind-stockade",
|
|
"randomized-bite-sized-stormwind-stockade-available",
|
|
"stormwind-stockade",
|
|
"bite-sized-stormwind-stockade",
|
|
"bite-sized-deadmines-ship",
|
|
"bite-sized-utgarde-pinnacle-skadi",
|
|
"bite-sized-wailing-caverns",
|
|
]);
|
|
expect(DUNGEON_CATALOG.filter((dungeon) => !dungeon.id.includes("stormwind-stockade")
|
|
&& !dungeon.id.startsWith("bite-sized-"))
|
|
.every((dungeon) => dungeon.releaseStage === "alpha"))
|
|
.toBe(true);
|
|
for (const category of DUNGEON_CATEGORIES) {
|
|
const dungeons = dungeonsByCategory(category.id);
|
|
expect(dungeons).toEqual([...dungeons].sort(compareDungeonReleaseOrder));
|
|
}
|
|
const stages = [
|
|
{ title: "Zeta", releaseStage: "alpha" as const },
|
|
{ title: "Beta Z", releaseStage: "beta" as const },
|
|
{ title: "Released Z", releaseStage: "full-release" as const },
|
|
{ title: "Alpha", releaseStage: "alpha" as const },
|
|
{ title: "Beta A", releaseStage: "beta" as const },
|
|
{ title: "Released A", releaseStage: "full-release" as const },
|
|
];
|
|
expect(stages.sort(compareDungeonReleaseOrder).map((entry) => entry.title))
|
|
.toEqual(["Released A", "Released Z", "Beta A", "Beta Z", "Alpha", "Zeta"]);
|
|
});
|
|
|
|
it("shares the complete dungeon identity list used to validate reports on the server", () => {
|
|
expect(DUNGEON_CATALOG.map((dungeon) => dungeon.id).sort())
|
|
.toEqual(["bite-sized-barren-caves-anglo", "bite-sized-deadmines-ship", "bite-sized-forsaken-abbey-ancalon",
|
|
"bite-sized-grafu-castle-barkud", "bite-sized-hall-of-survivors-pursuer", "bite-sized-hoto-teeth",
|
|
"bite-sized-kawaks-tomb-linobia", "bite-sized-mystic-altar-golem", "bite-sized-paspers-shrine-hafiz", "bite-sized-stormwind-stockade",
|
|
"bite-sized-utgarde-pinnacle-skadi", "bite-sized-wailing-caverns",
|
|
"randomized-bite-sized-stormwind-stockade", "randomized-bite-sized-stormwind-stockade-available", "forsaken-abbey",
|
|
...Object.keys(availability.enabled)].sort());
|
|
});
|
|
});
|