'use strict'; const assert = require('assert').strict; global.Ladders = require('../../dist/server/ladders').Ladders; const { makeUser } = require('../users-utils'); describe('Matchmaker', () => { const FORMATID = 'gen7ou'; const addSearch = (player, rating = 1000, formatid = FORMATID) => { const search = new Ladders.BattleReady(player.id, formatid, player.battleSettings, rating); Ladders(formatid).addSearch(search, player); return search; }; const destroyPlayer = player => { player.resetName(); player.disconnectAll(); player.destroy(); return null; }; before(() => { clearInterval(Ladders.periodicMatchInterval); Ladders.periodicMatchInterval = null; }); beforeEach(function () { this.p1 = makeUser('Morfent', '192.168.0.1'); this.p1.battleSettings.team = 'Gengar||||lick||252,252,4,,,|||||'; Users.users.set(this.p1.id, this.p1); this.p2 = makeUser('Mrofnet', '192.168.0.2'); this.p2.battleSettings.team = 'Gengar||||lick||252,252,4,,,|||||'; Users.users.set(this.p2.id, this.p2); }); afterEach(function () { this.p1 = destroyPlayer(this.p1); this.p2 = destroyPlayer(this.p2); }); it('should add a search', function () { const s1 = addSearch(this.p1); assert(Ladders.searches.has(FORMATID)); const formatSearches = Ladders.searches.get(FORMATID).searches; assert(formatSearches instanceof Map); assert.equal(formatSearches.size, 1); assert.equal(s1.userid, this.p1.id); assert.equal(s1.settings.team, this.p1.battleSettings.team); assert.equal(s1.rating, 1000); }); it('should matchmake users when appropriate', function () { addSearch(this.p1); addSearch(this.p2); assert.equal(Ladders.searches.get(FORMATID).searches.size, 0); const [roomid] = [...this.p1.games]; Rooms.get(roomid).destroy(); }); it('should matchmake users within a reasonable rating range', function () { addSearch(this.p1); addSearch(this.p2, 2000); assert.equal(Ladders.searches.get(FORMATID).searches.size, 2); }); it('should cancel searches', function () { addSearch(this.p1); Ladders(FORMATID).cancelSearch(this.p1); Ladders.cancelSearches(this.p2); assert.equal(Ladders.searches.get(FORMATID).searches.size, 0); }); it('should periodically matchmake users when appropriate', function () { addSearch(this.p1); const s2 = addSearch(this.p2, 2000); assert.equal(Ladders.searches.get(FORMATID).searches.size, 2); s2.rating = 1000; Ladders.Ladder.periodicMatch(); assert.equal(Ladders.searches.get(FORMATID).searches.size, 0); const [roomid] = [...this.p1.games]; Rooms.get(roomid).destroy(); }); it('should create a new battle room after matchmaking', function () { assert.equal(this.p1.games.size, 0); addSearch(this.p1); addSearch(this.p2); assert.equal(this.p1.games.size, 1); for (const roomid of this.p1.games) { assert(Rooms.get(roomid).battle); } }); it('should cancel search on disconnect', function () { addSearch(this.p1); this.p1.onDisconnect(this.p1.connections[0]); assert.equal(Ladders.searches.get(FORMATID).searches.size, 0); }); it('should cancel search on merge', function () { addSearch(this.p1); this.p2.merge(this.p1); assert.equal(Ladders.searches.get(FORMATID).searches.size, 0); }); describe('#startBattle', () => { beforeEach(function () { this.s1 = addSearch(this.p1); this.s2 = addSearch(this.p2); }); afterEach(function () { this.s1 = null; this.s2 = null; }); it('should prevent battles from starting if both players are identical', function () { Object.assign(this.s2, this.s1); let room; try { room = Rooms.createBattle({ format: FORMATID, players: [ { user: this.p1, team: this.s1.team }, { user: this.p1, team: this.s2.team }, ], rated: 1000, }); } catch {} assert.equal(room, undefined); }); before(function () { this.lockdown = Rooms.global.lockdown; Rooms.global.lockdown = true; }); after(function () { Rooms.global.lockdown = this.lockdown; this.lockdown = null; }); it('should prevent battles from starting if the server is in lockdown', function () { const room = Rooms.createBattle({ format: FORMATID, players: [{ user: this.p1, team: this.s1.team }, { user: this.p2, team: this.s2.team }], rated: 1000, }); assert.equal(room, null); }); }); });