import { expect } from "@esm-bundle/chai"; import { InventoryManager } from "../../src/managers/InventoryManager.js"; import { InventoryContainer } from "../../src/models/InventoryContainer.js"; import { Item } from "../../src/items/Item.js"; describe("Manager: InventoryManager", () => { let manager; let mockItemRegistry; let mockUnit; let runStash; let hubStash; beforeEach(() => { // Mock Item Registry mockItemRegistry = { get: (defId) => { const items = { "ITEM_RUSTY_BLADE": new Item({ id: "ITEM_RUSTY_BLADE", name: "Rusty Blade", type: "WEAPON", stats: { attack: 3 }, requirements: {}, }), "ITEM_SCRAP_PLATE": new Item({ id: "ITEM_SCRAP_PLATE", name: "Scrap Plate", type: "ARMOR", stats: { defense: 3 }, requirements: {}, }), "ITEM_TINKER_GUN": new Item({ id: "ITEM_TINKER_GUN", name: "Tinker Gun", type: "WEAPON", stats: { attack: 5 }, requirements: { class_lock: ["CLASS_TINKER"] }, }), "ITEM_TWO_HANDED_SWORD": new Item({ id: "ITEM_TWO_HANDED_SWORD", name: "Greatsword", type: "WEAPON", stats: { attack: 10 }, requirements: {}, tags: ["TWO_HANDED"], }), "ITEM_SHIELD": new Item({ id: "ITEM_SHIELD", name: "Shield", type: "UTILITY", stats: { defense: 2 }, requirements: {}, }), "ITEM_HEALTH_POTION": new Item({ id: "ITEM_HEALTH_POTION", name: "Health Potion", type: "CONSUMABLE", stats: {}, requirements: {}, }), }; return items[defId] || null; }, }; // Mock Unit (Explorer) mockUnit = { id: "UNIT_001", activeClassId: "CLASS_VANGUARD", baseStats: { health: 100, attack: 10, defense: 5, magic: 0, speed: 10, willpower: 5, movement: 4, tech: 0, }, loadout: { mainHand: null, offHand: null, body: null, accessory: null, belt: [null, null], }, recalculateStats: () => { // Mock stat recalculation }, }; runStash = new InventoryContainer("RUN_LOOT"); hubStash = new InventoryContainer("HUB_VAULT"); manager = new InventoryManager(mockItemRegistry, runStash, hubStash); }); describe("canEquip", () => { it("should return true if unit meets requirements", () => { const itemInstance = { uid: "ITEM_001", defId: "ITEM_RUSTY_BLADE", isNew: false, quantity: 1, }; const canEquip = manager.canEquip(mockUnit, itemInstance); expect(canEquip).to.be.true; }); it("should return false if unit does not meet class requirements", () => { const itemInstance = { uid: "ITEM_002", defId: "ITEM_TINKER_GUN", isNew: false, quantity: 1, }; const canEquip = manager.canEquip(mockUnit, itemInstance); expect(canEquip).to.be.false; }); it("should return false if item definition not found", () => { const itemInstance = { uid: "ITEM_003", defId: "ITEM_NONEXISTENT", isNew: false, quantity: 1, }; const canEquip = manager.canEquip(mockUnit, itemInstance); expect(canEquip).to.be.false; }); }); describe("equipItem", () => { it("should equip item to mainHand slot", () => { const itemInstance = { uid: "ITEM_001", defId: "ITEM_RUSTY_BLADE", isNew: false, quantity: 1, }; hubStash.addItem(itemInstance); const result = manager.equipItem(mockUnit, itemInstance, "MAIN_HAND"); expect(result).to.be.true; expect(mockUnit.loadout.mainHand).to.deep.equal(itemInstance); expect(hubStash.findItem("ITEM_001")).to.be.null; // Removed from stash }); it("should swap item if slot is occupied", () => { const existingItem = { uid: "ITEM_002", defId: "ITEM_SCRAP_PLATE", isNew: false, quantity: 1, }; const newItem = { uid: "ITEM_001", defId: "ITEM_RUSTY_BLADE", isNew: false, quantity: 1, }; mockUnit.loadout.mainHand = existingItem; hubStash.addItem(newItem); const result = manager.equipItem(mockUnit, newItem, "MAIN_HAND"); expect(result).to.be.true; expect(mockUnit.loadout.mainHand).to.deep.equal(newItem); expect(hubStash.findItem("ITEM_002")).to.deep.equal(existingItem); // Old item in stash }); it("should automatically unequip offHand when equipping two-handed weapon", () => { const twoHandedItem = { uid: "ITEM_003", defId: "ITEM_TWO_HANDED_SWORD", isNew: false, quantity: 1, }; const shieldItem = { uid: "ITEM_004", defId: "ITEM_SHIELD", isNew: false, quantity: 1, }; mockUnit.loadout.offHand = shieldItem; hubStash.addItem(twoHandedItem); const result = manager.equipItem(mockUnit, twoHandedItem, "MAIN_HAND"); expect(result).to.be.true; expect(mockUnit.loadout.mainHand).to.deep.equal(twoHandedItem); expect(mockUnit.loadout.offHand).to.be.null; // Off-hand unequipped expect(hubStash.findItem("ITEM_004")).to.deep.equal(shieldItem); // Shield in stash }); it("should return false if item cannot be equipped", () => { const itemInstance = { uid: "ITEM_002", defId: "ITEM_TINKER_GUN", isNew: false, quantity: 1, }; hubStash.addItem(itemInstance); const result = manager.equipItem(mockUnit, itemInstance, "MAIN_HAND"); expect(result).to.be.false; expect(mockUnit.loadout.mainHand).to.be.null; expect(hubStash.findItem("ITEM_002")).to.exist; // Still in stash }); it("should equip item to belt slot", () => { const potion = { uid: "ITEM_005", defId: "ITEM_HEALTH_POTION", isNew: false, quantity: 1, }; hubStash.addItem(potion); const result = manager.equipItem(mockUnit, potion, "BELT", 0); expect(result).to.be.true; expect(mockUnit.loadout.belt[0]).to.deep.equal(potion); }); }); describe("unequipItem", () => { it("should unequip item from slot and move to stash", () => { const itemInstance = { uid: "ITEM_001", defId: "ITEM_RUSTY_BLADE", isNew: false, quantity: 1, }; mockUnit.loadout.mainHand = itemInstance; const result = manager.unequipItem(mockUnit, "MAIN_HAND"); expect(result).to.be.true; expect(mockUnit.loadout.mainHand).to.be.null; expect(hubStash.findItem("ITEM_001")).to.deep.equal(itemInstance); }); it("should return false if slot is empty", () => { const result = manager.unequipItem(mockUnit, "MAIN_HAND"); expect(result).to.be.false; }); it("should unequip from belt slot", () => { const potion = { uid: "ITEM_005", defId: "ITEM_HEALTH_POTION", isNew: false, quantity: 1, }; mockUnit.loadout.belt[0] = potion; const result = manager.unequipItem(mockUnit, "BELT", 0); expect(result).to.be.true; expect(mockUnit.loadout.belt[0]).to.be.null; expect(hubStash.findItem("ITEM_005")).to.deep.equal(potion); }); }); describe("transferToStash", () => { it("should move item from unit loadout to stash", () => { const itemInstance = { uid: "ITEM_001", defId: "ITEM_RUSTY_BLADE", isNew: false, quantity: 1, }; mockUnit.loadout.mainHand = itemInstance; const result = manager.transferToStash(mockUnit, "MAIN_HAND"); expect(result).to.be.true; expect(mockUnit.loadout.mainHand).to.be.null; expect(hubStash.findItem("ITEM_001")).to.deep.equal(itemInstance); }); it("should return false if slot is empty", () => { const result = manager.transferToStash(mockUnit, "MAIN_HAND"); expect(result).to.be.false; }); }); });