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 { return { ...EMPTY_ITEM_STATS, ...overrides }; } function item( instanceId: string, inventorySlot: string, overrides: Partial = {}, ): 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 }); }); });