import { expect } from "@esm-bundle/chai"; import { UnitManager } from "../../src/managers/UnitManager.js"; // Note: These tests rely on the existence of src/units/Explorer.js and src/units/Enemy.js // If running in isolation without those files, mocks would be required. describe("Manager: UnitManager", () => { let manager; let mockRegistry; beforeEach(() => { // Setup a mock registry to simulate loading definitions from JSON mockRegistry = { get: (id) => { if (id === "CLASS_VANGUARD") { return { name: "Vanguard", type: "EXPLORER", stats: { health: 100, speed: 10 }, }; } if (id === "ENEMY_GOBLIN") { return { name: "Goblin", type: "ENEMY", stats: { health: 30, attack: 5 }, ai_archetype: "BRUISER", }; } if (id === "STRUCT_WALL") { return { name: "Wall", type: "STRUCTURE", model: "wall.glb", stats: { health: 50 }, }; } return null; }, }; manager = new UnitManager(mockRegistry); }); it("CoA 1: createUnit should instantiate an Explorer for CLASS_ IDs", () => { const unit = manager.createUnit("CLASS_VANGUARD", "PLAYER"); expect(unit).to.exist; // Verify it behaves like an Explorer (has class logic) expect(unit.type).to.equal("EXPLORER"); expect(unit.team).to.equal("PLAYER"); expect(unit.name).to.equal("Vanguard"); // Verify it was added to the active list expect(manager.getUnitById(unit.id)).to.equal(unit); }); it("CoA 2: createUnit should instantiate an Enemy for ENEMY_ IDs", () => { const unit = manager.createUnit("ENEMY_GOBLIN", "ENEMY"); expect(unit).to.exist; expect(unit.type).to.equal("ENEMY"); expect(unit.team).to.equal("ENEMY"); // Enemies should have AI props expect(unit.archetypeId).to.equal("BRUISER"); }); it("CoA 3: createUnit should handle generic structures", () => { const unit = manager.createUnit("STRUCT_WALL", "NEUTRAL"); expect(unit).to.exist; expect(unit.type).to.equal("STRUCTURE"); expect(unit.team).to.equal("NEUTRAL"); }); it("CoA 4: removeUnit should remove the unit from the active map", () => { const unit = manager.createUnit("CLASS_VANGUARD", "PLAYER"); const id = unit.id; expect(manager.getUnitById(id)).to.exist; const removed = manager.removeUnit(id); expect(removed).to.be.true; expect(manager.getUnitById(id)).to.be.undefined; expect(manager.getAllUnits()).to.have.lengthOf(0); }); it("CoA 5: getUnitsInRange should return units within Manhattan distance", () => { const u1 = manager.createUnit("CLASS_VANGUARD", "PLAYER"); // Manually set position since we aren't using the Grid's moveUnit here u1.position = { x: 0, y: 0, z: 0 }; const u2 = manager.createUnit("ENEMY_GOBLIN", "ENEMY"); u2.position = { x: 2, y: 0, z: 0 }; // Distance 2 const u3 = manager.createUnit("ENEMY_GOBLIN", "ENEMY"); u3.position = { x: 5, y: 0, z: 0 }; // Distance 5 // Check range 3 const results = manager.getUnitsInRange({ x: 0, y: 0, z: 0 }, 3); expect(results).to.include(u1); // Distance 0 (Self) expect(results).to.include(u2); // Distance 2 expect(results).to.not.include(u3); // Distance 5 }); it("CoA 6: getUnitsInRange should filter by team if provided", () => { const u1 = manager.createUnit("CLASS_VANGUARD", "PLAYER"); u1.position = { x: 0, y: 0, z: 0 }; const u2 = manager.createUnit("ENEMY_GOBLIN", "ENEMY"); u2.position = { x: 1, y: 0, z: 0 }; // Filter for ENEMY only const results = manager.getUnitsInRange({ x: 0, y: 0, z: 0 }, 5, "ENEMY"); expect(results).to.include(u2); expect(results).to.not.include(u1); }); it("CoA 7: tickAll should trigger cooldown updates on units", () => { const unit = manager.createUnit("CLASS_VANGUARD", "PLAYER"); // Mock the skill manager on the unit instance let ticked = false; unit.skillManager = { tickCooldowns: () => { ticked = true; }, }; manager.tickAll(); expect(ticked).to.be.true; }); });