90 lines
2.9 KiB
TypeScript
90 lines
2.9 KiB
TypeScript
// Module 2: The action queue, depth-first. Each test matches a heading in scenarios.md.
|
|
import { expect, test } from "vitest";
|
|
import { newGame, type GameEvent, type Id } from "../src/harness";
|
|
|
|
const fillers = (n: number): string[] => Array(n).fill("Test Filler");
|
|
|
|
/** Sources of the `Triggered` events, in log order. */
|
|
const triggeredSources = (log: GameEvent[]): Id[] =>
|
|
log.flatMap((e) => (e.type === "Triggered" ? [e.source] : []));
|
|
|
|
test("test_02_aoe_damage_then_triggers", () => {
|
|
const g = newGame({ decks: [fillers(5), fillers(5)] });
|
|
const s = g.summon("Armorsmith", 0);
|
|
const a = g.summon("Acolyte of Pain", 0);
|
|
g.clearLog();
|
|
|
|
g.cast("Whirlwind", 0);
|
|
const log = g.log();
|
|
|
|
expect(log.filter((e) => e.type === "Damaged")).toEqual([
|
|
{ type: "Damaged", target: s, amount: 1 },
|
|
{ type: "Damaged", target: a, amount: 1 },
|
|
]);
|
|
const types = log.map((e) => e.type);
|
|
const lastDamaged = types.lastIndexOf("Damaged");
|
|
const firstTriggered = types.indexOf("Triggered");
|
|
expect(firstTriggered).toBeGreaterThanOrEqual(0);
|
|
expect(lastDamaged).toBeLessThan(firstTriggered);
|
|
|
|
const sources = triggeredSources(log);
|
|
expect(sources.filter((id) => id === s)).toHaveLength(2);
|
|
expect(sources.filter((id) => id === a)).toHaveLength(1);
|
|
expect(sources).toHaveLength(3);
|
|
expect(g.armor(0)).toBe(2);
|
|
expect(g.hand(0)).toHaveLength(1);
|
|
});
|
|
|
|
test("test_02_mortally_wounded_still_triggers", () => {
|
|
const g = newGame({ decks: [fillers(5), []] });
|
|
const a = g.summon("Acolyte of Pain", 0);
|
|
g.dealDamage(a, 3);
|
|
const n = g.hand(0).length;
|
|
g.clearLog();
|
|
|
|
g.cast("Whirlwind", 0);
|
|
const log = g.log();
|
|
|
|
expect(log).toContainEqual({ type: "Triggered", source: a, trigger: "damaged" });
|
|
expect(log.some((e) => e.type === "Drew" && e.player === 0)).toBe(true);
|
|
expect(g.hand(0)).toHaveLength(n + 1);
|
|
expect(g.health(a)).toBe(0);
|
|
expect(g.zoneOf(a)).toBe("board");
|
|
});
|
|
|
|
test("test_02_depth_first_nesting", () => {
|
|
const g = newGame();
|
|
const e = g.summon("Test Echo", 0);
|
|
const s = g.summon("Armorsmith", 0);
|
|
const r = g.summon("Test Reactor", 0);
|
|
g.clearLog();
|
|
|
|
g.dealDamage(s, 1);
|
|
const log = g.log();
|
|
|
|
expect(triggeredSources(log)).toEqual([e, r, s]);
|
|
const reactorGrew = log.findIndex((ev) => ev.type === "StatsChanged" && ev.id === r);
|
|
const armorGained = log.findIndex((ev) => ev.type === "ArmorGained");
|
|
expect(reactorGrew).toBeGreaterThanOrEqual(0);
|
|
expect(reactorGrew).toBeLessThan(armorGained);
|
|
expect(g.attack(r)).toBe(2);
|
|
expect(g.armor(0)).toBe(1);
|
|
expect(g.health(g.hero(1))).toBe(29);
|
|
});
|
|
|
|
test("test_02_empty_deck_draw_is_fatigue", () => {
|
|
const g = newGame();
|
|
const a = g.summon("Acolyte of Pain", 0);
|
|
g.clearLog();
|
|
|
|
g.dealDamage(a, 1);
|
|
|
|
expect(g.log()).toEqual([
|
|
{ type: "Damaged", target: a, amount: 1 },
|
|
{ type: "Triggered", source: a, trigger: "damaged" },
|
|
{ type: "Fatigue", player: 0 },
|
|
]);
|
|
expect(g.hand(0)).toEqual([]);
|
|
expect(g.health(g.hero(0))).toBe(30);
|
|
});
|