import assert from "node:assert/strict"; import test from "node:test"; import { createArenaService } from "./arena-service.mjs"; function fakeDatabase() { return { onlineGroupState: () => ({ group: null, invitations: [] }), arenaLoadoutForQueue: (_accountId, characterId) => ({ slot: 1, name: "Disc", characterId, classId: "priest", specializationId: "priest:discipline", role: "healer", ruleset: "wow", level: 80, talents: {}, actions: {}, version: 1, selected: true, updatedAt: 1, }), selectedArenaLoadoutForQueue: (_accountId, characterId) => ({ slot: 2, name: "Selected", characterId, classId: "warrior", specializationId: "warrior:arms", role: "damage", ruleset: "wow", level: 80, talents: {}, actions: {}, version: 1, selected: true, updatedAt: 1, }), getArenaRating: () => ({ rating: 1200, title: "Challenger" }), getArenaState: () => ({ characterId: "priest", loadouts: [], ratings: {} }), createArenaMatch: () => {}, settleArenaMatch: () => ({ ratingUpdates: [] }), voidArenaMatch: () => {}, }; } test("Rated AI fills immediately and requires the 15 second ready check", () => { let clock = 1000; const service = createArenaService({ database: fakeDatabase(), now: () => clock, random: () => 0, autoPump: false }); const account = { id: "account", username: "ArenaPlayer" }; const queued = service.enqueue(account, { characterId: "priest", loadoutSlot: 1, bracket: "2v2", mode: "rated-ai", ruleset: "wow" }); assert.equal(queued.status, "ready-check"); assert.equal(queued.readyDeadline, clock + 15_000); service.ready(account.id); const match = [...service.inspect().matches.values()][0]; assert.equal(match.participants.length, 4); assert.equal(match.participants.filter((participant) => participant.team === 0 && participant.role === "healer").length, 1); match.simulation.stop(); service.close(); }); test("group leaders queue partial teams with each member's selected loadout", () => { const database = fakeDatabase(); database.onlineGroupState = () => ({ invitations: [], group: { leaderAccountId: "leader", members: [ { accountId: "leader", username: "Leader", character: { id: "priest" } }, { accountId: "member", username: "Member", character: { id: "warrior" } }, ], }, }); const service = createArenaService({ database, now: () => 1000, random: () => 0, autoPump: false }); const queued = service.enqueue({ id: "leader", username: "Leader" }, { characterId: "priest", loadoutSlot: 1, bracket: "3v3", mode: "rated-ai", ruleset: "wow", }); assert.equal(queued.status, "ready-check"); service.ready("leader"); assert.equal(service.inspect().matches.size, 0); service.ready("member"); const match = [...service.inspect().matches.values()][0]; assert.equal(match.participants.filter((participant) => participant.accountId).length, 2); assert.equal(match.participants.filter((participant) => participant.team === 0 && participant.isBot).length, 1); match.simulation.stop(); service.close(); }); test("expired ready checks return tickets to matchmaking", () => { let clock = 1000; const service = createArenaService({ database: fakeDatabase(), now: () => clock, random: () => 0, autoPump: false }); const account = { id: "account", username: "ArenaPlayer" }; service.enqueue(account, { characterId: "priest", loadoutSlot: 1, bracket: "2v2", mode: "rated-ai", ruleset: "wow" }); clock += 15_001; service.pump(); assert.equal(service.queueState(account.id).status, "queued"); assert.equal(service.inspect().matches.size, 0); service.close(); }); test("Ranked PvP permanently fills every open slot after thirty seconds", () => { let clock = 1000; const service = createArenaService({ database: fakeDatabase(), now: () => clock, random: () => 0, autoPump: false }); const account = { id: "account", username: "ArenaPlayer" }; assert.equal(service.enqueue(account, { characterId: "priest", loadoutSlot: 1, bracket: "3v3", mode: "ranked-pvp", ruleset: "wow" }).status, "queued"); clock += 30_000; service.pump(); const lobby = [...service.inspect().lobbies.values()][0]; assert.equal(lobby.participants.length, 6); assert.equal(lobby.participants.filter((participant) => participant.isBot).length, 5); service.close(); });