241 lines
7.1 KiB
JavaScript
241 lines
7.1 KiB
JavaScript
|
|
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;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
|