forked from phenom/healer-man
Release Healer Man 0.1.37
This commit is contained in:
1 parent
03a4e3f51c
commit
361734bc41
41 files changed
+1714
-110
No files matched your search
@@ -0,0 +1,64 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { PLAYER_AGGRO_ID } from "./aggro";
|
||||
import { useCombatStore } from "./combatStore";
|
||||
import { appendCombatEvent } from "./combatEvents";
|
||||
import { connectDpsMeter, currentDpsMeterSnapshot, useDpsMeterStore } from "./dpsMeterStore";
|
||||
import { useGameStore } from "./store";
|
||||
import { useUiLayoutStore } from "./uiLayoutStore";
|
||||
import { currentCompanionSnapshot, executeCompanionCommand } from "../platform/dualScreenSync";
|
||||
|
||||
describe("live DPS tracking and companion editor", () => {
|
||||
let disconnect: () => void;
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers(); vi.setSystemTime(1_000);
|
||||
useGameStore.setState({ overlay: null, paused: false, companionOpen: false });
|
||||
useCombatStore.getState().initializeCharacter({ classId: "mage", level: 5 });
|
||||
useCombatStore.getState().registerMob("dps-target", { name: "Target", maxHealth: 1_000_000 });
|
||||
disconnect = connectDpsMeter();
|
||||
});
|
||||
afterEach(() => { disconnect(); useUiLayoutStore.getState().finish(false); vi.useRealTimers(); });
|
||||
|
||||
it("tracks real damage while hidden, caps overkill, freezes on defeat, and clears on reset", () => {
|
||||
useUiLayoutStore.getState().begin();
|
||||
useUiLayoutStore.getState().updateDraft((layout) => ({ ...layout, elements: { ...layout.elements, dps: { ...layout.elements.dps, visible: false } } }));
|
||||
useCombatStore.getState().damageMob("dps-target", 100, Date.now());
|
||||
vi.advanceTimersByTime(2_000);
|
||||
expect(currentDpsMeterSnapshot()).toMatchObject({ totalDamage: 100, totalDps: 50 });
|
||||
const remaining = useCombatStore.getState().mobs["dps-target"].health;
|
||||
useCombatStore.getState().damageMob("dps-target", 2_000_000, Date.now());
|
||||
expect(currentDpsMeterSnapshot()).toMatchObject({ active: false, totalDamage: 100 + remaining });
|
||||
vi.advanceTimersByTime(10_000);
|
||||
expect(currentDpsMeterSnapshot().durationSeconds).toBe(2);
|
||||
useCombatStore.getState().resetEncounter();
|
||||
expect(useDpsMeterStore.getState().startedAt).toBeNull();
|
||||
});
|
||||
it("merges summon damage into its owner and excludes hostile and friendly-target damage", () => {
|
||||
const actors = useCombatStore.getState().actors;
|
||||
useCombatStore.setState({ actors: { ...actors, "meter-pet": { ...actors[PLAYER_AGGRO_ID], id: "meter-pet", kind: "pet", ownerId: PLAYER_AGGRO_ID } } });
|
||||
for (const [id, sourceActorId, targetActorId] of [[1, "meter-pet", "dps-target"], [2, "dps-target", PLAYER_AGGRO_ID], [3, PLAYER_AGGRO_ID, PLAYER_AGGRO_ID]] as const) {
|
||||
appendCombatEvent([], { occurredAt: Date.now(), kind: "damage", sourceActorId, targetActorId,
|
||||
rawAmount: 100, effectiveAmount: 80, overheal: 0, absorbed: 20, critical: false }, id);
|
||||
}
|
||||
expect(currentDpsMeterSnapshot().totalDamage).toBe(80);
|
||||
expect(currentDpsMeterSnapshot().rows.find((row) => row.total > 0)?.id).toBe(PLAYER_AGGRO_ID);
|
||||
});
|
||||
it("does not dilute DPS while a local game menu pauses combat", () => {
|
||||
useCombatStore.getState().damageMob("dps-target", 100, Date.now());
|
||||
vi.advanceTimersByTime(1_000);
|
||||
useGameStore.setState({ paused: true, overlay: "ui-layout" });
|
||||
vi.advanceTimersByTime(10_000);
|
||||
expect(currentDpsMeterSnapshot()).toMatchObject({ durationSeconds: 1, totalDps: 100 });
|
||||
useGameStore.setState({ paused: false, overlay: null });
|
||||
vi.advanceTimersByTime(1_000);
|
||||
expect(currentDpsMeterSnapshot()).toMatchObject({ durationSeconds: 2, totalDps: 50 });
|
||||
});
|
||||
it("publishes draft visibility and accepts lower-screen movement only while editing", () => {
|
||||
useUiLayoutStore.getState().begin();
|
||||
const command = { name: "editDpsMeter", update: { position: { x: .7, y: .8 }, width: 300 } } as const;
|
||||
executeCompanionCommand(command);
|
||||
expect(useUiLayoutStore.getState().draft?.elements.dps.position).toBeNull();
|
||||
useGameStore.setState({ overlay: "ui-layout" });
|
||||
executeCompanionCommand(command);
|
||||
expect(currentCompanionSnapshot().game.dpsMeter).toMatchObject({ editing: true, layout: { position: { x: .7, y: .8 }, width: 300 } });
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user