import { expect } from "@esm-bundle/chai"; import sinon from "sinon"; // Import to register custom element import "../../src/ui/screens/MissionDebrief.js"; describe("UI: MissionDebrief", () => { let element; let container; beforeEach(async () => { container = document.createElement("div"); document.body.appendChild(container); element = document.createElement("mission-debrief"); container.appendChild(element); // Wait for element to be defined await element.updateComplete; }); afterEach(() => { if (container && container.parentNode) { container.parentNode.removeChild(container); } }); // Helper to wait for LitElement update async function waitForUpdate() { await element.updateComplete; await new Promise((resolve) => setTimeout(resolve, 10)); } // Helper to query shadow DOM function queryShadow(selector) { return element.shadowRoot?.querySelector(selector); } function queryShadowAll(selector) { return element.shadowRoot?.querySelectorAll(selector) || []; } const createMockResult = (outcome = "VICTORY") => ({ outcome, missionTitle: "Test Mission", xpEarned: 500, currency: { shards: 100, cores: 5 }, loot: [ { uid: "ITEM_1", defId: "ITEM_RUSTY_BLADE", name: "Rusty Blade", quantity: 1, }, { uid: "ITEM_2", defId: "ITEM_HEALTH_POTION", name: "Health Potion", quantity: 2, }, ], reputationChanges: [ { factionId: "IRON_LEGION", amount: 15 }, ], squadUpdates: [ { unitId: "unit-1", isDead: false, leveledUp: true, damageTaken: 20, }, { unitId: "unit-2", isDead: false, leveledUp: false, damageTaken: 50, }, ], }); describe("CoA 1: Component accepts result prop", () => { it("should accept and store result prop", async () => { const mockResult = createMockResult(); element.result = mockResult; await waitForUpdate(); expect(element.result).to.deep.equal(mockResult); }); it("should render nothing when result is not provided", async () => { await waitForUpdate(); const modal = queryShadow(".modal-overlay"); expect(modal).to.not.exist; }); }); describe("CoA 2: Visual rendering - Header", () => { it("should display 'MISSION ACCOMPLISHED' in gold for VICTORY", async () => { const mockResult = createMockResult("VICTORY"); element.result = mockResult; await waitForUpdate(); const header = queryShadow(".header"); expect(header).to.exist; expect(header.textContent).to.include("MISSION ACCOMPLISHED"); expect(header.classList.contains("victory")).to.be.true; }); it("should display 'MISSION FAILED' in red for DEFEAT", async () => { const mockResult = createMockResult("DEFEAT"); element.result = mockResult; await waitForUpdate(); const header = queryShadow(".header"); expect(header).to.exist; expect(header.textContent).to.include("MISSION FAILED"); expect(header.classList.contains("defeat")).to.be.true; }); }); describe("CoA 3: Primary Stats", () => { it("should display XP earned with numeric value", async () => { const mockResult = createMockResult(); element.result = mockResult; await waitForUpdate(); const xpDisplay = queryShadow(".xp-display"); expect(xpDisplay).to.exist; expect(xpDisplay.textContent).to.include("500"); }); it("should display turns taken", async () => { const mockResult = createMockResult(); mockResult.turnsTaken = 12; element.result = mockResult; await waitForUpdate(); const turnsDisplay = queryShadow(".turns-display"); expect(turnsDisplay).to.exist; expect(turnsDisplay.textContent).to.include("12"); }); }); describe("CoA 4: Rewards Panel", () => { it("should display currency (shards and cores)", async () => { const mockResult = createMockResult(); element.result = mockResult; await waitForUpdate(); const currencyDisplay = queryShadow(".currency-display"); expect(currencyDisplay).to.exist; expect(currencyDisplay.textContent).to.include("100"); expect(currencyDisplay.textContent).to.include("5"); }); it("should render loot items as item-card components", async () => { const mockResult = createMockResult(); element.result = mockResult; await waitForUpdate(); const itemCards = queryShadowAll(".item-card"); expect(itemCards.length).to.equal(2); }); it("should display reputation changes", async () => { const mockResult = createMockResult(); element.result = mockResult; await waitForUpdate(); const reputationDisplay = queryShadow(".reputation-display"); expect(reputationDisplay).to.exist; expect(reputationDisplay.textContent).to.include("IRON_LEGION"); expect(reputationDisplay.textContent).to.include("+15"); }); }); describe("CoA 5: Roster Status", () => { it("should display squad unit status", async () => { const mockResult = createMockResult(); element.result = mockResult; await waitForUpdate(); const rosterStatus = queryShadow(".roster-status"); expect(rosterStatus).to.exist; }); it("should show level up badge for units that leveled up", async () => { const mockResult = createMockResult(); element.result = mockResult; await waitForUpdate(); const levelUpBadges = queryShadowAll(".level-up-badge"); expect(levelUpBadges.length).to.be.greaterThan(0); }); it("should show dead status for dead units", async () => { const mockResult = createMockResult(); mockResult.squadUpdates[0].isDead = true; element.result = mockResult; await waitForUpdate(); const deadUnits = queryShadowAll(".unit-status.dead"); expect(deadUnits.length).to.be.greaterThan(0); }); }); describe("CoA 6: Typewriter Effect", () => { it("should apply typewriter effect to text elements", async () => { const mockResult = createMockResult(); element.result = mockResult; await waitForUpdate(); // Wait for typewriter to start await new Promise((resolve) => setTimeout(resolve, 100)); const typewriterElements = queryShadowAll(".typewriter"); expect(typewriterElements.length).to.be.greaterThan(0); }); }); describe("CoA 7: Event Dispatch", () => { it("should dispatch 'return-to-hub' event when footer button is clicked", async () => { const mockResult = createMockResult(); element.result = mockResult; await waitForUpdate(); const returnButton = queryShadow(".return-button"); expect(returnButton).to.exist; const dispatchSpy = sinon.spy(element, "dispatchEvent"); returnButton.click(); expect(dispatchSpy.calledOnce).to.be.true; const event = dispatchSpy.firstCall.args[0]; expect(event.type).to.equal("return-to-hub"); expect(event.bubbles).to.be.true; expect(event.composed).to.be.true; }); }); });