Files
healer-man/src/game/equipment.test.ts
T
2026-08-14 15:56:39 -04:00

100 lines
3.9 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type { InventoryItem } from "./lootTypes";
import {
PLAYER_EQUIPMENT_OWNER_ID,
classCanEquipItem,
equipInventoryItem,
equipmentItemLevel,
equipmentStats,
normalizeEquipment,
unequipInventorySlot,
} from "./equipment";
import { EMPTY_ITEM_STATS, type ItemStats } from "./itemStats";
function stats(overrides: Partial<ItemStats>): ItemStats {
return { ...EMPTY_ITEM_STATS, ...overrides };
}
function item(
instanceId: string,
inventorySlot: string,
overrides: Partial<InventoryItem> = {},
): InventoryItem {
return {
instanceId,
itemId: 1,
itemKey: instanceId,
name: instanceId,
quality: "uncommon",
inventorySlot,
armorType: null,
weaponType: null,
itemLevel: 12,
sourceItemLevel: 20,
stats: stats({ spellPower: 3, stamina: 2 }),
quantity: 1,
sourceBossKey: "kresh",
sourceBossName: "Kresh",
acquiredAt: 1,
...overrides,
};
}
describe("equipment assignments", () => {
it("moves a unique item between the player and companions", () => {
const cloak = item("cloak", "back");
const player = equipInventoryItem({}, [cloak], PLAYER_EQUIPMENT_OWNER_ID, "priest", cloak.instanceId);
expect(player.ok).toBe(true);
expect(player.assignments.player?.back).toBe("cloak");
const companion = equipInventoryItem(player.assignments, [cloak], "party-damage-1-mage", "mage", cloak.instanceId);
expect(companion.ok).toBe(true);
expect(companion.assignments.player).toBeUndefined();
expect(companion.assignments["party-damage-1-mage"]?.back).toBe("cloak");
});
it("enforces armor, shield, and weapon compatibility", () => {
const leather = item("leather", "chest", { armorType: "leather" });
const shield = item("shield", "off-hand", { armorType: "shield" });
const bow = item("bow", "ranged", { weaponType: "bow" });
expect(classCanEquipItem("priest", leather)).toBe(false);
expect(classCanEquipItem("warrior", leather)).toBe(true);
expect(classCanEquipItem("mage", shield)).toBe(false);
expect(classCanEquipItem("shaman", shield)).toBe(true);
expect(classCanEquipItem("hunter", bow)).toBe(true);
expect(classCanEquipItem("warlock", bow)).toBe(false);
});
it("handles two-handed conflicts, unequipping, normalization, and item level", () => {
const staff = item("staff", "two-hand", { weaponType: "staff", itemLevel: 18 });
const shield = item("shield", "off-hand", { armorType: "shield", itemLevel: 14 });
const main = equipInventoryItem({}, [staff, shield], "player", "warrior", staff.instanceId);
const offhand = equipInventoryItem(main.assignments, [staff, shield], "player", "warrior", shield.instanceId);
expect(offhand.assignments.player?.["main-hand"]).toBeUndefined();
expect(offhand.assignments.player?.["off-hand"]).toBe("shield");
expect(equipmentItemLevel(offhand.assignments, [staff, shield], "player")).toBe(14);
const unequipped = unequipInventorySlot(offhand.assignments, "player", "off-hand");
expect(unequipped.player).toBeUndefined();
expect(normalizeEquipment({ player: { back: "missing", "off-hand": "shield" } }, [shield]))
.toEqual({ player: { "off-hand": "shield" } });
});
it("totals only the items worn by the selected owner", () => {
const cloak = item("cloak", "back", { stats: stats({ spellPower: 3, stamina: 4, armor: 9 }) });
const staff = item("staff", "two-hand", {
weaponType: "staff",
stats: stats({ strength: 8, stamina: 2 }),
});
const assignments = {
player: { back: cloak.instanceId },
companion: { "main-hand": staff.instanceId },
};
expect(equipmentStats(assignments, [cloak, staff], "player"))
.toMatchObject({ spellPower: 3, stamina: 4, armor: 9 });
expect(equipmentStats(assignments, [cloak, staff], "companion"))
.toMatchObject({ strength: 8, stamina: 2, armor: 0 });
});
});