Files
healer-man/src/game/benchmark/benchmarkScenarios.test.ts
T
2026-08-30 14:16:56 -04:00

73 lines
3.2 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type { PartyRole } from "../partyRoles";
import { BENCHMARK_SCENARIOS, benchmarkScenarioById } from "./benchmarkScenarios";
const EXPECTED_DURATIONS_MS: Readonly<Record<string, number>> = Object.freeze({
"damage-single-burst": 30_000,
"damage-single-sustained": 180_000,
"damage-cleave-three": 90_000,
"damage-aoe-eight": 60_000,
"tank-mixed-boss": 180_000,
"tank-multi-target": 120_000,
"heal-single-target": 90_000,
"heal-spread-party": 180_000,
"heal-stacked-party": 90_000,
"heal-resource-endurance": 600_000,
"mechanic-movement-boss": 180_000,
"mechanic-stack-boss": 180_000,
});
describe("benchmark scenario catalog", () => {
it("uses unique stable ids and positive integer versions", () => {
const ids = BENCHMARK_SCENARIOS.map((scenario) => scenario.id);
expect(ids).toHaveLength(Object.keys(EXPECTED_DURATIONS_MS).length);
expect(new Set(ids).size).toBe(ids.length);
expect([...ids].sort()).toEqual(Object.keys(EXPECTED_DURATIONS_MS).sort());
expect(BENCHMARK_SCENARIOS.every(
(scenario) => Number.isInteger(scenario.version) && scenario.version >= 1,
)).toBe(true);
expect(BENCHMARK_SCENARIOS.every((scenario) => scenario.version === 1)).toBe(true);
for (const scenario of BENCHMARK_SCENARIOS) {
expect(benchmarkScenarioById(scenario.id)).toBe(scenario);
}
expect(benchmarkScenarioById("missing-scenario")).toBeNull();
});
it("covers every combat role and keeps role-specific families scoped", () => {
const expectedRoles: readonly PartyRole[] = ["tank", "healer", "damage"];
const coveredRoles = new Set(BENCHMARK_SCENARIOS.flatMap((scenario) => scenario.roles));
expect([...coveredRoles].sort()).toEqual([...expectedRoles].sort());
expect(BENCHMARK_SCENARIOS.every((scenario) => (
scenario.roles.length > 0
&& scenario.roles.every((role) => expectedRoles.includes(role))
))).toBe(true);
expect(BENCHMARK_SCENARIOS.filter((scenario) => scenario.family === "damage")
.every((scenario) => scenario.roles.length === 1 && scenario.roles[0] === "damage"))
.toBe(true);
expect(BENCHMARK_SCENARIOS.filter((scenario) => scenario.family === "tanking")
.every((scenario) => scenario.roles.length === 1 && scenario.roles[0] === "tank"))
.toBe(true);
expect(BENCHMARK_SCENARIOS.filter((scenario) => (
scenario.family === "healing" || scenario.family === "endurance"
)).every((scenario) => scenario.roles.length === 1 && scenario.roles[0] === "healer"))
.toBe(true);
expect(BENCHMARK_SCENARIOS.filter((scenario) => scenario.family === "mechanics")
.every((scenario) => expectedRoles.every((role) => scenario.roles.includes(role))))
.toBe(true);
});
it("preserves exact durations on an integral fixed-step timeline", () => {
for (const scenario of BENCHMARK_SCENARIOS) {
expect(scenario.durationMs).toBe(EXPECTED_DURATIONS_MS[scenario.id]);
expect(Number.isInteger(scenario.durationMs)).toBe(true);
expect(Number.isInteger(scenario.tickMs)).toBe(true);
expect(scenario.durationMs).toBeGreaterThan(0);
expect(scenario.tickMs).toBeGreaterThan(0);
expect(scenario.durationMs % scenario.tickMs).toBe(0);
}
});
});