forked from phenom/healer-man
88 lines
4.2 KiB
TypeScript
88 lines
4.2 KiB
TypeScript
import { createElement } from "react";
|
|
import { renderToStaticMarkup } from "react-dom/server";
|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { useCombatStore } from "../game/combatStore";
|
|
import { activateDungeonEncounterDefinitions, resetDungeonEncounters } from "../game/dungeonEncounterRuntime";
|
|
import { requireDungeonDefinition } from "../game/dungeonRegistry";
|
|
import { usePartyStore } from "../game/partyStore";
|
|
import { useGameStore } from "../game/store";
|
|
import { PartyFrames } from "./PartyFrames";
|
|
|
|
// Exercise the client HUD against live stores rather than their initial SSR snapshots.
|
|
vi.mock("../game/partyStore", async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import("../game/partyStore")>();
|
|
return { ...actual, usePartyStore: Object.assign(
|
|
(select: (state: ReturnType<typeof actual.usePartyStore.getState>) => unknown) => select(actual.usePartyStore.getState()), actual.usePartyStore,
|
|
) };
|
|
});
|
|
vi.mock("../game/combatStore", async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import("../game/combatStore")>();
|
|
return { ...actual, useCombatStore: Object.assign(
|
|
(select: (state: ReturnType<typeof actual.useCombatStore.getState>) => unknown) => select(actual.useCombatStore.getState()), actual.useCombatStore,
|
|
) };
|
|
});
|
|
vi.mock("../game/store", async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import("../game/store")>();
|
|
return { ...actual, useGameStore: Object.assign(
|
|
(select: (state: ReturnType<typeof actual.useGameStore.getState>) => unknown) => select(actual.useGameStore.getState()), actual.useGameStore,
|
|
) };
|
|
});
|
|
|
|
const dungeon = requireDungeonDefinition("stormwind-stockade");
|
|
const render = () => renderToStaticMarkup(createElement(PartyFrames));
|
|
function killMember() {
|
|
const member = usePartyStore.getState().members[0];
|
|
useCombatStore.getState().commitCompanionActors([{ ...member, health: 0, status: "down" }]);
|
|
}
|
|
|
|
describe("party resurrection UI", () => {
|
|
beforeEach(() => {
|
|
useGameStore.getState().activateDungeon("stormwind-stockade");
|
|
activateDungeonEncounterDefinitions(dungeon.id, dungeon.encounters ?? []);
|
|
resetDungeonEncounters("dungeon", dungeon.id);
|
|
useCombatStore.getState().initializeCharacter({ classId: "priest", level: 16 });
|
|
useCombatStore.setState({ mobs: {} });
|
|
usePartyStore.getState().initializeParty("rez-ui", 16, useCombatStore.getState().health);
|
|
useCombatStore.getState().synchronizeActors();
|
|
});
|
|
|
|
it("hides the control when all NPCs are alive, even if only the player is dead", () => {
|
|
expect(render()).not.toContain("Rez dead members");
|
|
useCombatStore.getState().damagePlayer(useCombatStore.getState().maxHealth * 10);
|
|
expect(render()).not.toContain("Rez dead members");
|
|
});
|
|
|
|
it("places the button and labeled destination selector below every party frame", () => {
|
|
killMember();
|
|
const markup = render();
|
|
expect(markup).toContain("Rez dead members");
|
|
expect(markup).toContain("Resurrect at");
|
|
expect(markup).toContain("Dungeon entrance");
|
|
expect(markup.indexOf("party-resurrection")).toBeGreaterThan(markup.lastIndexOf("party-frame__identity"));
|
|
expect(markup).not.toMatch(/class="party-rez-button" disabled/);
|
|
});
|
|
|
|
it("shows why resurrection is disabled during a living boss encounter", () => {
|
|
killMember();
|
|
useCombatStore.getState().registerMob("boss", { name: "Boss", boss: true, maxHealth: 100 });
|
|
useCombatStore.getState().damageMob("boss", 1, 100);
|
|
expect(render()).toMatch(/class="party-rez-button" disabled=""/);
|
|
expect(render()).toContain("Unavailable during boss combat");
|
|
});
|
|
|
|
it("offers killed boss destinations but not bosses that are still alive", () => {
|
|
killMember();
|
|
const boss = dungeon.bosses[0];
|
|
expect(render()).not.toContain(`value="boss:${boss.id}"`);
|
|
useCombatStore.getState().registerMob(boss.id, { name: boss.name, boss: true, maxHealth: 1 });
|
|
useCombatStore.getState().damageMob(boss.id, 1, 100);
|
|
expect(render()).toContain(`value="boss:${boss.id}"`);
|
|
});
|
|
|
|
it("does not offer free resurrection in Manastorm", () => {
|
|
killMember();
|
|
useGameStore.setState({ gameMode: "manastorm" });
|
|
expect(render()).not.toContain("Rez dead members");
|
|
});
|
|
});
|