import { expect } from "@esm-bundle/chai"; import { GameViewport } from "../../src/ui/game-viewport.js"; import { gameStateManager } from "../../src/core/GameStateManager.js"; describe("UI: GameViewport", () => { let element; let container; beforeEach(() => { container = document.createElement("div"); document.body.appendChild(container); element = document.createElement("game-viewport"); container.appendChild(element); }); afterEach(() => { // Clean up event listeners and reset state if (container.parentNode) { container.parentNode.removeChild(container); } // Reset gameStateManager.activeRunData if (gameStateManager) { gameStateManager.activeRunData = null; } }); // Helper to wait for LitElement update async function waitForUpdate() { await element.updateComplete; // Give a small delay for DOM updates await new Promise((resolve) => setTimeout(resolve, 10)); } // Helper to query shadow DOM function queryShadow(selector) { return element.shadowRoot?.querySelector(selector); } describe("Squad Updates", () => { it("should update squad from run-data-updated event", async () => { await waitForUpdate(); const testSquad = [ { id: "u1", name: "Valerius", classId: "CLASS_VANGUARD" }, { id: "u2", name: "Aria", classId: "CLASS_AETHER_WEAVER" }, ]; // Dispatch run-data-updated event window.dispatchEvent( new CustomEvent("run-data-updated", { detail: { runData: { squad: testSquad, }, }, }) ); await waitForUpdate(); expect(element.squad).to.deep.equal(testSquad); }); it("should update squad from activeRunData when gamestate-changed fires", async () => { await waitForUpdate(); const testSquad = [ { id: "u1", name: "Valerius", classId: "CLASS_VANGUARD" }, { id: "u2", name: "Aria", classId: "CLASS_AETHER_WEAVER" }, ]; // Set activeRunData gameStateManager.activeRunData = { squad: testSquad, }; // Dispatch gamestate-changed event window.dispatchEvent( new CustomEvent("gamestate-changed", { detail: { newState: "STATE_DEPLOYMENT" }, }) ); await waitForUpdate(); expect(element.squad).to.deep.equal(testSquad); }); it("should update squad from activeRunData in constructor", async () => { const testSquad = [ { id: "u1", name: "Valerius", classId: "CLASS_VANGUARD" }, ]; // Set activeRunData before element is created gameStateManager.activeRunData = { squad: testSquad, }; // Create new element (constructor will call #setupCombatStateUpdates) const newElement = document.createElement("game-viewport"); container.appendChild(newElement); await newElement.updateComplete; await new Promise((resolve) => setTimeout(resolve, 10)); expect(newElement.squad).to.deep.equal(testSquad); newElement.remove(); }); it("should pass squad to deployment-hud", async () => { await waitForUpdate(); const testSquad = [ { id: "u1", name: "Valerius", classId: "CLASS_VANGUARD" }, { id: "u2", name: "Aria", classId: "CLASS_AETHER_WEAVER" }, ]; element.squad = testSquad; await waitForUpdate(); const deploymentHud = queryShadow("deployment-hud"); expect(deploymentHud).to.exist; expect(deploymentHud.squad).to.deep.equal(testSquad); }); it("should handle empty squad gracefully", async () => { await waitForUpdate(); expect(element.squad).to.be.an("array"); expect(element.squad.length).to.equal(0); const deploymentHud = queryShadow("deployment-hud"); expect(deploymentHud).to.exist; expect(deploymentHud.squad).to.be.an("array"); }); it("should create new array reference when updating squad", async () => { await waitForUpdate(); const testSquad = [ { id: "u1", name: "Valerius", classId: "CLASS_VANGUARD" }, ]; window.dispatchEvent( new CustomEvent("run-data-updated", { detail: { runData: { squad: testSquad, }, }, }) ); await waitForUpdate(); // Verify it's a new array reference (not the same object) expect(element.squad).to.not.equal(testSquad); expect(element.squad).to.deep.equal(testSquad); }); }); });