aether-shards/test/ui/mission-debrief.test.js

241 lines
7.1 KiB
JavaScript
Raw Normal View History

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;
});
});
});