import { expect } from "@esm-bundle/chai"; import sinon from "sinon"; import { GameLoop } from "../../../src/core/GameLoop.js"; import { createGameLoopSetup, cleanupGameLoop, createRunData, createMockGameStateManagerForCombat, setupCombatUnits, cleanupTurnSystem, } from "./helpers.js"; describe("Core: GameLoop - Combat Deployment Integration", function () { this.timeout(30000); let gameLoop; let container; let mockGameStateManager; let playerUnit; let enemyUnit; beforeEach(async () => { const setup = createGameLoopSetup(); gameLoop = setup.gameLoop; container = setup.container; gameLoop.stop(); if ( gameLoop.turnSystem && typeof gameLoop.turnSystem.reset === "function" ) { gameLoop.turnSystem.reset(); } gameLoop.init(container); mockGameStateManager = createMockGameStateManagerForCombat(); // Ensure rosterManager exists if (!mockGameStateManager.rosterManager) { mockGameStateManager.rosterManager = { roster: [] }; } gameLoop.gameStateManager = mockGameStateManager; const runData = createRunData({ squad: [{ id: "u1", classId: "CLASS_VANGUARD" }], }); await gameLoop.startLevel(runData, { startAnimation: false }); const units = setupCombatUnits(gameLoop); playerUnit = units.playerUnit; enemyUnit = units.enemyUnit; }); afterEach(() => { gameLoop.clearMovementHighlights(); gameLoop.clearSpawnZoneHighlights(); cleanupTurnSystem(gameLoop); cleanupGameLoop(gameLoop, container); }); it("CoA 14: should clear spawn zone highlights when deployment finishes", async () => { mockGameStateManager.currentState = "STATE_DEPLOYMENT"; const runData = createRunData(); await gameLoop.startLevel(runData, { startAnimation: false }); expect(gameLoop.spawnZoneHighlights.size).to.be.greaterThan(0); await gameLoop.finalizeDeployment(); expect(gameLoop.spawnZoneHighlights.size).to.equal(0); }); it("CoA 14b: should update combat state immediately when deployment finishes", async () => { mockGameStateManager.currentState = "STATE_DEPLOYMENT"; const runData = createRunData({ squad: [{ id: "u1", classId: "CLASS_VANGUARD" }], }); await gameLoop.startLevel(runData, { startAnimation: false }); const unitDef = runData.squad[0]; const validTile = gameLoop.playerSpawnZone[0]; gameLoop.deployUnit(unitDef, validTile); const updateCombatStateSpy = sinon.spy(gameLoop, "updateCombatState"); await gameLoop.finalizeDeployment(); // Wait a bit for updateCombatState to complete await new Promise((resolve) => setTimeout(resolve, 10)); expect(updateCombatStateSpy.calledOnce).to.be.true; expect(mockGameStateManager.setCombatState.called).to.be.true; const combatStateCall = mockGameStateManager.setCombatState.getCall(-1); expect(combatStateCall).to.exist; const combatState = combatStateCall.args[0]; expect(combatState).to.exist; expect(combatState.isActive).to.be.true; expect(combatState.turnQueue).to.be.an("array"); updateCombatStateSpy.restore(); }); it("CoA 15: should clear movement highlights when starting new level", async () => { mockGameStateManager.getCombatState.returns({ activeUnit: { id: playerUnit.id, name: playerUnit.name, }, turnQueue: [], }); gameLoop.updateMovementHighlights(playerUnit); expect(gameLoop.movementHighlights.size).to.be.greaterThan(0); const runData = createRunData({ seed: 99999 }); await gameLoop.startLevel(runData, { startAnimation: false }); expect(gameLoop.movementHighlights.size).to.equal(0); }); });