// Module 3: Deferred death. Each test matches a heading in scenarios.md. import { expect, test } from "vitest"; import { newGame } from "../src/harness"; const fillers = (n: number): string[] => Array(n).fill("Test Filler"); test("test_03_removed_only_after_sequence", () => { const g = newGame({ decks: [fillers(5), []] }); const h = g.summon("Loot Hoarder", 0); const s = g.summon("Armorsmith", 0); g.clearLog(); g.cast("Whirlwind", 0); const hand = g.hand(0); expect(hand).toHaveLength(1); const c = hand[0]; expect(g.log()).toEqual([ { type: "SpellCast", card: "Whirlwind" }, { type: "Damaged", target: h, amount: 1 }, { type: "Damaged", target: s, amount: 1 }, { type: "Triggered", source: s, trigger: "damaged" }, { type: "ArmorGained", player: 0, amount: 1 }, { type: "Triggered", source: s, trigger: "damaged" }, { type: "ArmorGained", player: 0, amount: 1 }, { type: "Destroyed", id: h }, { type: "DeathPhase", round: 1 }, { type: "Triggered", source: h, trigger: "deathrattle" }, { type: "Drew", player: 0, id: c }, ]); expect(g.zoneOf(h)).toBe("graveyard"); expect(g.board(0)).toEqual([s]); expect(g.armor(0)).toBe(2); }); test("test_03_chained_death_phases", () => { const g = newGame(); const golem = g.summon("Harvest Golem", 0); const ghoul = g.summon("Unstable Ghoul", 0); const r = g.summon("Test Reactor", 0); g.dealDamage(golem, 2); g.clearLog(); g.dealDamage(ghoul, 3); const d = g.board(0)[0]; expect(g.log()).toEqual([ { type: "Damaged", target: ghoul, amount: 3 }, { type: "Destroyed", id: ghoul }, { type: "DeathPhase", round: 1 }, { type: "Triggered", source: ghoul, trigger: "deathrattle" }, { type: "Damaged", target: golem, amount: 1 }, { type: "Damaged", target: r, amount: 1 }, { type: "Destroyed", id: golem }, { type: "DeathPhase", round: 2 }, { type: "Triggered", source: golem, trigger: "deathrattle" }, { type: "Summoned", id: d }, ]); expect(g.nameOf(d)).toBe("Damaged Golem"); expect(g.board(0)).toEqual([d, r]); expect(g.zoneOf(ghoul)).toBe("graveyard"); expect(g.zoneOf(golem)).toBe("graveyard"); expect(g.health(r)).toBe(4); }); test("test_03_simultaneous_removal", () => { const g = newGame({ decks: [fillers(5), []] }); const h1 = g.summon("Loot Hoarder", 0); const h2 = g.summon("Loot Hoarder", 0); g.clearLog(); g.cast("Whirlwind", 0); const hand = g.hand(0); expect(hand).toHaveLength(2); const [c1, c2] = hand; expect(g.log()).toEqual([ { type: "SpellCast", card: "Whirlwind" }, { type: "Damaged", target: h1, amount: 1 }, { type: "Damaged", target: h2, amount: 1 }, { type: "Destroyed", id: h1 }, { type: "Destroyed", id: h2 }, { type: "DeathPhase", round: 1 }, { type: "Triggered", source: h1, trigger: "deathrattle" }, { type: "Drew", player: 0, id: c1 }, { type: "Triggered", source: h2, trigger: "deathrattle" }, { type: "Drew", player: 0, id: c2 }, ]); expect(g.zoneOf(h1)).toBe("graveyard"); expect(g.zoneOf(h2)).toBe("graveyard"); expect(g.board(0)).toEqual([]); }); test("test_03_destroy_marks_pending", () => { const g = newGame(); const golem = g.summon("Harvest Golem", 0); g.clearLog(); g.destroy(golem); const board = g.board(0); expect(board).toHaveLength(1); const d = board[0]; expect(g.log()).toEqual([ { type: "Destroyed", id: golem }, { type: "DeathPhase", round: 1 }, { type: "Triggered", source: golem, trigger: "deathrattle" }, { type: "Summoned", id: d }, ]); expect(g.health(golem)).toBe(3); expect(g.zoneOf(golem)).toBe("graveyard"); expect(g.nameOf(d)).toBe("Damaged Golem"); });