forked from phenom/healer-man
121 lines
5.8 KiB
TypeScript
121 lines
5.8 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
CLASS_ICON_BASENAME_BY_ID,
|
|
CLASSES,
|
|
COA_CLASS_IDS,
|
|
PLAYABLE_RACES,
|
|
RACES,
|
|
classIconUrl,
|
|
classesForRace,
|
|
clampAppearance,
|
|
contentCategoryForClass,
|
|
normalizeCharacterName,
|
|
randomAppearance,
|
|
supportedGenders,
|
|
totalRaceClassCombinations,
|
|
validateCharacterName,
|
|
} from "./characterCatalog";
|
|
import { CONTENT_CATEGORIES } from "./contentCategories";
|
|
|
|
describe("wow335a character catalog", () => {
|
|
it("limits normal play to the live-verified race roster", () => {
|
|
expect(PLAYABLE_RACES.filter((race) => race.categoryId !== "rom").map((race) => race.id)).toEqual([
|
|
"human",
|
|
"orc",
|
|
"dwarf",
|
|
"night-elf",
|
|
"undead",
|
|
"tauren",
|
|
"gnome",
|
|
"troll",
|
|
"blood-elf",
|
|
"draenei",
|
|
"goblin",
|
|
]);
|
|
});
|
|
|
|
it("matches the extracted Ascension playable catalog", () => {
|
|
const wowRaces = RACES.filter((race) => race.categoryId !== "rom");
|
|
const azerothClasses = CLASSES.filter((characterClass) => characterClass.categoryId !== "rom");
|
|
const wowClasses = CLASSES.filter((characterClass) => contentCategoryForClass(characterClass.id) === "wow");
|
|
const coaClasses = CLASSES.filter((characterClass) => contentCategoryForClass(characterClass.id) === "coa");
|
|
expect(wowRaces).toHaveLength(27);
|
|
expect(azerothClasses).toHaveLength(31);
|
|
expect(wowClasses).toHaveLength(10);
|
|
expect(coaClasses).toHaveLength(21);
|
|
expect(COA_CLASS_IDS).toHaveLength(21);
|
|
expect(wowRaces.reduce((total, race) => total + classesForRace(race.id).length, 0)).toBe(740);
|
|
expect(totalRaceClassCombinations()).toBe(758);
|
|
expect(wowRaces.map((race) => race.name)).toEqual([
|
|
"Human", "Orc", "Dwarf", "Night Elf", "Undead",
|
|
"Tauren", "Gnome", "Troll", "Blood Elf", "Draenei",
|
|
"Goblin", "Zandalari Troll", "Kul Tiran", "Vulpera", "Pandaren",
|
|
"Thin Human", "Fel Orc", "Broken", "Skeleton", "Vrykul", "Tuskarr",
|
|
"Forest Troll", "Taunka", "Northrend Skeleton", "Ice Troll", "Earthen",
|
|
"Human Cultist",
|
|
]);
|
|
expect(COA_CLASS_IDS.map((id) => coaClasses.find((entry) => entry.id === id)?.name)).toEqual([
|
|
"Barbarian", "Witch Doctor", "Felsworn", "Witch Hunter", "Stormbringer",
|
|
"Knight of Xoroth", "Guardian", "Templar", "Bloodmage", "Ranger",
|
|
"Chronomancer", "Necromancer", "Pyromancer", "Cultist", "Starcaller",
|
|
"Sun Cleric", "Tinker", "Venomancer", "Reaper", "Primalist", "Runemaster",
|
|
]);
|
|
});
|
|
|
|
it("separates default WoW, custom CoA, and RoM character creation categories", () => {
|
|
expect(CONTENT_CATEGORIES.map((category) => category.id)).toEqual(["wow", "rom", "coa"]);
|
|
expect(classesForRace("human", "wow").map((entry) => entry.id)).toContain("priest");
|
|
expect(classesForRace("human", "wow").map((entry) => entry.id)).not.toContain("barbarian");
|
|
expect(classesForRace("human", "coa").map((entry) => entry.id)).toContain("barbarian");
|
|
expect(classesForRace("human", "coa").map((entry) => entry.id)).not.toContain("priest");
|
|
expect(classesForRace("rom-human", "rom").map((entry) => entry.id)).toContain("rom-priest");
|
|
});
|
|
|
|
it("applies the race eligibility rows from CharBaseInfo.dbc", () => {
|
|
expect(classesForRace("human", "coa").map((entry) => entry.id)).toContain("barbarian");
|
|
expect(classesForRace("human", "coa").map((entry) => entry.id)).not.toContain("felsworn");
|
|
expect(classesForRace("draenei", "coa").map((entry) => entry.id)).toContain("felsworn");
|
|
expect(classesForRace("draenei", "coa").map((entry) => entry.id)).toContain("knight-of-xoroth");
|
|
expect(classesForRace("troll", "coa").map((entry) => entry.id)).toContain("venomancer");
|
|
expect(classesForRace("troll", "coa").map((entry) => entry.id)).not.toContain("knight-of-xoroth");
|
|
expect(classesForRace("goblin", "wow")).toHaveLength(10);
|
|
expect(classesForRace("goblin", "coa")).toHaveLength(21);
|
|
expect(classesForRace("human-cultist")).toHaveLength(31);
|
|
expect(supportedGenders("vrykul")).toEqual(["male"]);
|
|
expect(supportedGenders("earthen")).toEqual(["male", "female"]);
|
|
});
|
|
|
|
it("maps every class to its extracted Ascension class icon", () => {
|
|
const wowClasses = CLASSES.filter((characterClass) => characterClass.categoryId !== "rom");
|
|
expect(new Set(wowClasses.map((definition) => CLASS_ICON_BASENAME_BY_ID[definition.id])).size)
|
|
.toBe(wowClasses.length);
|
|
expect(CLASS_ICON_BASENAME_BY_ID.felsworn).toBe("classicon128_demonhunter");
|
|
expect(CLASS_ICON_BASENAME_BY_ID["knight-of-xoroth"]).toBe("classicon128_fleshwarden");
|
|
expect(CLASS_ICON_BASENAME_BY_ID.venomancer).toBe("classicon128_prophet");
|
|
expect(classIconUrl("runemaster")).toBe("/assets/ui/spells/classicon128_spiritmage.png");
|
|
});
|
|
|
|
it("preserves race and gender-specific customization counts", () => {
|
|
const tauren = RACES.find((race) => race.id === "tauren")!;
|
|
expect(tauren.labels.male.hairStyle).toBe("Horn Style");
|
|
expect(tauren.counts.male).toMatchObject({ skinColor: 19, hairColor: 3, feature: 7 });
|
|
expect(RACES.find((race) => race.id === "night-elf")!.labels.female.feature).toBe("Markings");
|
|
});
|
|
|
|
it("keeps generated and clamped appearance indexes within the selected model ranges", () => {
|
|
expect(randomAppearance("human", "female", () => 0.999)).toEqual({
|
|
skinColor: 9, face: 14, hairStyle: 23, hairColor: 9, feature: 6,
|
|
});
|
|
expect(clampAppearance("gnome", "male", {
|
|
skinColor: -2, face: 99, hairStyle: 4.7, hairColor: 20, feature: 2,
|
|
})).toEqual({ skinColor: 0, face: 6, hairStyle: 4, hairColor: 8, feature: 2 });
|
|
});
|
|
|
|
it("applies the original 2-12 letter naming boundary", () => {
|
|
expect(normalizeCharacterName(" hEAL3R!! ")).toBe("Healr");
|
|
expect(validateCharacterName("A")).toMatch(/2 to 12/);
|
|
expect(validateCharacterName("Healer-Man")).toMatch(/letters only/);
|
|
expect(validateCharacterName("Serenity")).toBeNull();
|
|
});
|
|
});
|