import assert from "node:assert/strict"; import test from "node:test"; import { arenaKitForLoadout } from "./arena-character-kit.mjs"; import { ArenaSimulation } from "./arena-simulation.mjs"; import { ARENA_STAGES } from "./arena-stages.mjs"; function fixture() { const kit = arenaKitForLoadout({classId:"priest",talents:{},actions:{"primary:face-left":"priest-flash-heal","primary:face-bottom":"priest-smite"}}); const simulation = new ArenaSimulation({id:"character-kit",stage:{ ...ARENA_STAGES[0], id:"test-floorless", lineOfSight:[] },bracket:"2v2",mode:"practice",ruleset:"wow",startedAt:0, participants:[{actorId:"player",characterId:"saved-priest",name:"My Priest",team:0,role:"healer",isBot:false,characterKit:kit}, {actorId:"ally",team:0,role:"damage",isBot:false},{actorId:"enemy",team:1,role:"damage",isBot:false}]}); for(let i=0;i<200;i++)simulation.step(); const player=simulation.actor("player"), ally=simulation.actor("ally"), enemy=simulation.actor("enemy"); player.position=[0,0,0];ally.position=[1,0,0];enemy.position=[2,0,0]; return {simulation,player,ally,enemy,kit}; } test("all arena spawns have finite character transforms before the first movement",()=>{ for(const stage of ARENA_STAGES) { const simulation=new ArenaSimulation({id:stage.id,stage,bracket:"2v2",mode:"practice",ruleset:"wow",participants:[ {actorId:"left",team:0,role:"healer",isBot:false},{actorId:"right",team:1,role:"damage",isBot:false}]}); for(const actor of simulation.snapshot().actors) { assert.ok(Number.isFinite(actor.facing),stage.id); assert.ok(actor.position.every(Number.isFinite),stage.id); assert.deepEqual(actor.position,stage.teamSpawns[actor.team],stage.id); } } }); test("saved priest identity, spell bindings, and usable mana reach the snapshot",()=>{ const {simulation,kit}=fixture(); const player=simulation.snapshot().actors.find(actor=>actor.id==="player"); assert.equal(player.characterId,"saved-priest");assert.equal(player.classId,"priest"); assert.equal(player.actionBindings["primary:face-left"],"priest-flash-heal"); assert.ok(player.resource>kit.abilities["priest-flash-heal"].cost.amount); assert.equal(simulation.receiveIntent("player",{sequence:1,type:"ability",abilityId:"heal"}).reason,"unknown-ability"); }); test("saved Flash Heal pays mana, has a cast time, heals the chosen ally and reports cooldown",()=>{ const {simulation,player,ally}=fixture();ally.health=200; const resource=player.resource; assert.equal(simulation.receiveIntent("player",{sequence:1,type:"ability",abilityId:"priest-flash-heal",targetActorId:"ally"}).accepted,true); assert.equal(player.resource,resource);assert.equal(ally.health,200); assert.equal(simulation.receiveIntent("player",{sequence:2,type:"ability",abilityId:"priest-flash-heal",targetActorId:"ally"}).reason,"already-casting"); for(let i=0;i<30;i++)simulation.step(); assert.ok(ally.health>200);assert.ok(player.resource{ const {simulation,player,enemy}=fixture(); enemy.position=[1000,0,0]; assert.equal(simulation.receiveIntent("player",{sequence:1,type:"ability",abilityId:"priest-smite",targetActorId:"enemy"}).reason,"out-of-range"); assert.equal(simulation.receiveIntent("player",{sequence:2,type:"ability",abilityId:"priest-flash-heal",targetActorId:"player"}).accepted,true); simulation.receiveIntent("player",{sequence:3,type:"movement",movement:{x:1,z:0}});simulation.step(); assert.equal(player.casting,null); }); test("Shadowfiend uses the character summoning engine",()=>{ const {simulation,player}=fixture(); player.facing=Math.PI/2; assert.equal(simulation.receiveIntent("player",{sequence:1,type:"ability",abilityId:"wow335-priest-shadowfiend",targetActorId:"enemy"}).accepted,true); assert.ok(player.combat.summons.length>0); });