BattleSim/test/server_spec.coffee

825 lines
32 KiB
CoffeeScript

require './helpers'
{BattleServer} = require('../server/server')
{Conditions, DEFAULT_FORMAT} = require '../shared/conditions'
{Protocol} = require '../shared/protocol'
{Factory} = require './factory'
alts = require('../server/alts')
should = require('should')
generateTeam = ->
[ Factory("Magikarp")
Factory("Gyarados")
Factory('Hitmonchan')
Factory("Celebi")
Factory("Blissey")
Factory("Alakazam") ]
describe 'BattleServer', ->
it 'can create a new battle', ->
server = new BattleServer()
battleId = server.createBattle()
server.battles.should.have.ownProperty battleId
it "sends the 'spectateBattle' event for each matched player", (done) ->
server = new BattleServer()
players = []
players.push server.findOrCreateUser(id: 1, name: 'abc', @stubSpark())
players.push server.findOrCreateUser(id: 2, name: 'def', @stubSpark())
spies = []
for player in players
spy = @sandbox.spy(player.sparks[0], 'send')
spies.push(spy)
for player in players
server.queuePlayer(player.name, generateTeam()).should.be.empty
server.beginBattles (err, ids) ->
throw new Error(err.message) if err
return if ids.length == 0
for spy in spies
spy.calledWith('spectateBattle').should.be.true
done()
describe "#queuePlayer", ->
it "queues players", ->
server = new BattleServer()
derp = server.findOrCreateUser(id: 1, name: 'derp', @stubSpark())
server.queuePlayer(derp.name, generateTeam()).should.be.empty
server.queues[DEFAULT_FORMAT].size().should.equal(1)
it "does not queue players already queued", ->
server = new BattleServer()
derp = server.findOrCreateUser(id: 1, name: 'derp', @stubSpark())
server.queuePlayer(derp.name, generateTeam()).should.be.empty
server.queuePlayer(derp.name, generateTeam()).should.be.empty
server.queues[DEFAULT_FORMAT].size().should.equal(1)
describe "#getOngoingBattles", ->
it "returns one object for each queued battle", (done) ->
server = new BattleServer()
nBattles = 3
for i in [1..nBattles]
first = 2 * i
second = (2 * i) + 1
server.findOrCreateUser(id: first, name: String(first), @stubSpark())
server.findOrCreateUser(id: second, name: String(second), @stubSpark())
server.queuePlayer(String(first), generateTeam()).should.be.empty
server.queuePlayer(String(second), generateTeam()).should.be.empty
server.beginBattles ->
server.getOngoingBattles().should.have.length(nBattles)
done()
describe "#registerChallenge", ->
it "registers a challenge to a player", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
team = generateTeam()
format = 'xy1000'
conditions = []
server.registerChallenge(user, other.name, format, team, conditions)
server.challenges.should.have.property(user.name)
server.challenges[user.name].should.have.property(other.name)
challenge = server.challenges[user.name][other.name]
challenge.should.have.property("team")
challenge.should.have.property("format")
challenge.should.have.property("conditions")
challenge.team.should.equal(team)
challenge.format.should.equal(format)
challenge.conditions.should.equal(conditions)
it "does not override old challenges", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
team = generateTeam()
format = 'xy1000'
diffFormat = 'xy500'
diffTeam = generateTeam()
diffTeam[0] = Factory("Celebi")
server.registerChallenge(user, other.name, format, team)
server.registerChallenge(user, other.name, diffFormat, diffTeam)
challenge = server.challenges[user.name][other.name]
challenge.format.should.equal(format)
challenge.team.should.equal(team)
it "returns an error if the team is invalid", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
format = 'xy1000'
mock = @sandbox.mock(user).expects('error').once()
team = []
server.registerChallenge(user, other.name, format, team)
mock.verify()
it "returns an error if the team is over 1000 PBV with 1000 PBV clause", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
format = 'xy1000'
team = generateTeam()
team[0] = Factory("Arceus", moves: [ "Recover" ])
conditions = [ Conditions.PBV_1000 ]
mock = @sandbox.mock(user).expects('error').once()
server.registerChallenge(user, other.name, format, team, conditions)
mock.verify()
it "returns an error on a rated challenge", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
format = 'xy1000'
team = generateTeam()
conditions = [ Conditions.RATED_BATTLE ]
mock = @sandbox.mock(user).expects('error').once()
server.registerChallenge(user, other.name, format, team, conditions)
mock.verify()
it "returns an error if the format is invalid", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
team = generateTeam()
format = "UNRELEASED INFERNO RED AND WEIRD YELLOWISH GREEN"
conditions = []
mock = @sandbox.mock(user).expects('error').once()
server.registerChallenge(user, other.name, format, team, conditions)
mock.verify()
it "returns an error if the challengee is offline", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
team = generateTeam()
format = 'xy1000'
conditions = []
mock = @sandbox.mock(user).expects('error').once()
server.registerChallenge(user, "husk", format, team, conditions)
mock.verify()
it "returns an error if you challenge yourself", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
team = generateTeam()
format = 'xy1000'
conditions = []
mock = @sandbox.mock(user).expects('error').once()
server.registerChallenge(user, user.name, format, team, conditions)
mock.verify()
it "sends an error if a challenge already exists for that pair", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
team = generateTeam()
format = 'xy1000'
conditions = []
server.registerChallenge(user, other.name, format, team, conditions)
mock = @sandbox.mock(other).expects('error').once()
server.registerChallenge(other, user.name, format, team, conditions)
mock.verify()
it "sends a 'challenge' event to the challengee", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
team = generateTeam()
format = 'xy1000'
conditions = []
otherSpy = @sandbox.spy(other, 'send')
otherSpy.withArgs('challenge', user.name, format, conditions)
server.registerChallenge(user, other.name, format, team, conditions)
otherSpy.withArgs('challenge', user.name, format, conditions)
.calledOnce.should.be.true
it "returns an error if the server is locked down", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
format = 'xy1000'
team = generateTeam()
conditions = [ Conditions.PBV_1000 ]
mock = @sandbox.mock(user).expects('error').once()
server.lockdown()
server.registerChallenge(user, other.name, format, team, conditions)
mock.verify()
describe "#cancelChallenge", ->
it "sends a 'cancelChallenge' to both the challengee and challenger", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
team = generateTeam()
format = 'xy1000'
conditions = []
userSpy = @sandbox.spy(user, 'send')
userSpy.withArgs('cancelChallenge', other.name)
otherSpy = @sandbox.spy(other, 'send')
otherSpy.withArgs('cancelChallenge', user.name)
server.registerChallenge(user, other.name, format, team, conditions)
server.cancelChallenge(user, other.name)
userSpy.withArgs('cancelChallenge', other.name).calledOnce.should.be.true
otherSpy.withArgs('cancelChallenge', user.name).calledOnce.should.be.true
it "removes the challenge from the internal hash", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
team = generateTeam()
format = 'xy1000'
conditions = []
server.registerChallenge(user, other.name, format, team, conditions)
should.exist server.challenges[user.name][other.name]
server.cancelChallenge(user, other.name)
should.not.exist server.challenges[user.name][other.name]
describe "#rejectChallenge", ->
it "sends a 'rejectChallenge' to the challengee and challenger", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
team = generateTeam()
format = 'xy1000'
conditions = []
server.registerChallenge(user, other.name, format, team, conditions)
userSpy = @sandbox.spy(user, 'send')
userSpy.withArgs('rejectChallenge', other.name)
otherSpy = @sandbox.spy(other, 'send')
otherSpy.withArgs('rejectChallenge', user.name)
server.rejectChallenge(other, user.name)
userSpy.withArgs('rejectChallenge', other.name).calledOnce.should.be.true
otherSpy.withArgs('rejectChallenge', user.name).calledOnce.should.be.true
it "removes the challenge from the internal hash", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
team = generateTeam()
format = 'xy1000'
conditions = []
server.registerChallenge(user, other.name, format, team, conditions)
should.exist server.challenges[user.name][other.name]
server.rejectChallenge(other, user.name)
should.not.exist server.challenges[user.name][other.name]
it "returns an error if no such challenge exists", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
team = generateTeam()
format = 'xy1000'
conditions = []
server.registerChallenge(user, other.name, format, team, conditions)
mock = @sandbox.mock(other).expects('error').once()
server.rejectChallenge(other, "bogus dude")
mock.verify()
describe "#acceptChallenge", ->
initServer = ->
@server = new BattleServer()
@user = @server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
@other = @server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
it "creates a battle with the teams given by both players", ->
initServer.call(this)
team = generateTeam()
format = 'xy1000'
conditions = []
@server.registerChallenge(@user, @other.name, format, team, conditions)
mock = @sandbox.mock(@server).expects('createBattle').once()
@server.acceptChallenge(@other, @user.name, team)
mock.verify()
it "returns an error to a player if their team is invalid", ->
initServer.call(this)
team = generateTeam()
format = 'xy1000'
conditions = []
@server.registerChallenge(@user, @other.name, format, team, conditions)
mock = @sandbox.mock(@other).expects('error').once()
@server.acceptChallenge(@other, @user.name, [])
mock.verify()
it "returns an error to a player if their team violates clauses", ->
initServer.call(this)
team = generateTeam()
acceptTeam = generateTeam()
acceptTeam[0] = Factory("Mewtwo", moves: [ "Psychic" ])
format = 'xy1000'
conditions = [ Conditions.PBV_1000 ]
@server.registerChallenge(@user, @other.name, format, team, conditions)
mock = @sandbox.mock(@other).expects('error').once()
@server.acceptChallenge(@other, @user.name, acceptTeam)
mock.verify()
it "removes the challenge from the internal hash", ->
initServer.call(this)
team = generateTeam()
format = 'xy1000'
conditions = []
@server.registerChallenge(@user, @other.name, format, team, conditions)
should.exist @server.challenges[@user.name][@other.name]
@server.acceptChallenge(@other, @user.name, team)
should.not.exist @server.challenges[@user.name][@other.name]
it "sends a 'challengeSuccess' event to both players", ->
initServer.call(this)
team = generateTeam()
format = 'xy1000'
conditions = []
userSpy = @sandbox.spy(@user, 'send')
userSpy.withArgs('challengeSuccess', @other.name)
otherSpy = @sandbox.spy(@other, 'send')
otherSpy.withArgs('challengeSuccess', @user.name)
@server.registerChallenge(@user, @other.name, format, team, conditions)
@server.acceptChallenge(@other, @user.name, team)
userSpy.withArgs('challengeSuccess', @other.name).calledOnce.should.be.true
otherSpy.withArgs('challengeSuccess', @user.name).calledOnce.should.be.true
it "returns an error if no such challenge exists", ->
initServer.call(this)
team = generateTeam()
format = 'xy1000'
conditions = []
@server.registerChallenge(@user, @other.name, format, team, conditions)
mock = @sandbox.mock(@other).expects('error').once()
@server.acceptChallenge(@other, "bogus dude", team)
mock.verify()
it "overrides the user's name with the alt name in battle", ->
initServer.call(this)
team = generateTeam()
format = 'xy1000'
conditions = []
@server.registerChallenge(@user, @other.name, format, team, conditions, "Bruce Wayne")
battleId = @server.acceptChallenge(@other, @user.name, team, "Jason Todd")
battle = @server.findBattle(battleId)
battle.battle.playerNames.should.eql ["Bruce Wayne", "Jason Todd"]
it "sets the rating key to be the unique alt id if there is an alt", ->
initServer.call(this)
team = generateTeam()
format = 'xy1000'
conditions = []
@server.registerChallenge(@user, @other.name, format, team, conditions, "Bruce Wayne")
battleId = @server.acceptChallenge(@other, @user.name, team, "Jason Todd")
battle = @server.findBattle(battleId)
battle.battle.getPlayer("Batman").ratingKey.should.equal alts.uniqueId(@user.name, "Bruce Wayne")
battle.battle.getPlayer("Robin").ratingKey.should.equal alts.uniqueId(@other.name, "Jason Todd")
describe "#leave", ->
it "removes challenges by that player", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", spark = @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
team = generateTeam()
format = 'xy1000'
conditions = []
server.registerChallenge(user, other.name, format, team, conditions)
should.exist server.challenges[user.name]
should.exist server.challenges[user.name][other.name]
server.leave(spark)
should.not.exist server.challenges[user.name]
it "removes challenges to that player", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", spark = @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
team = generateTeam()
format = 'xy1000'
conditions = []
server.registerChallenge(other, user.name, format, team, conditions)
should.exist server.challenges[other.name]
should.exist server.challenges[other.name][user.name]
server.leave(spark)
should.exist server.challenges[other.name]
should.not.exist server.challenges[other.name][user.name]
describe "#lockdown", ->
it "cancels all challenges", ->
server = new BattleServer()
user = server.findOrCreateUser(id: 1, name: "Batman", @stubSpark())
other = server.findOrCreateUser(id: 2, name: "Robin", @stubSpark())
team = generateTeam()
format = 'xy1000'
conditions = []
server.registerChallenge(other, user.name, format, team, conditions)
should.exist server.challenges[other.name]
should.exist server.challenges[other.name][user.name]
server.lockdown()
should.not.exist server.challenges[other.name]
describe "#validateTeam", ->
it "returns non-empty if given anything that's not an array", ->
server = new BattleServer()
server.validateTeam().should.not.be.empty
it "returns empty if given a non-empty array containing Pokemon", ->
server = new BattleServer()
server.validateTeam(generateTeam()).should.be.empty
it "returns non-empty if given an empty array", ->
server = new BattleServer()
server.validateTeam([]).should.not.be.empty
it "returns non-empty if a team member is not a valid Pokemon", ->
server = new BattleServer()
invalidPokemon = {}
server.validateTeam([ invalidPokemon ]).should.not.be.empty
it "returns non-empty if a team member has a fake species name", ->
server = new BattleServer()
team = generateTeam()
team[0] = {species: "NOTREALMON"}
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a team member has no moveset", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Hitmonchan", moves: null)
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a team member has an empty moveset", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Hitmonchan", moves: [])
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a team member has a bogus moveset", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Hitmonchan", moves: true)
server.validateTeam(team).should.not.be.empty
team[0] = Factory("Hitmonchan", moves: ["Super Powerful Punch"])
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a team member has an illegal moveset", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Raichu", moves: [ "Volt Tackle", "Encore" ])
server.validateTeam(team, 'bw').should.not.be.empty
# TODO: 4 is a magic constant
it "returns non-empty if a pokemon has more than 4 moves", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory "Hitmonchan",
moves: [
"Ice Punch"
"Fire Punch"
"Close Combat"
"Mach Punch"
"Rapid Spin"
]
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon has a move it can't learn", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Magikarp", moves: [ "Fissure" ])
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon has a fake move", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Magikarp", moves: [ "Splash", "Armageddon" ])
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon has an ability it can't have", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Magikarp", ability: "Wonder Guard")
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon has a bogus ability", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Magikarp", ability: "Being Batman")
server.validateTeam(team).should.not.be.empty
it "returns empty if a pokemon has a hidden ability", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Cloyster", ability: "Overcoat")
server.validateTeam(team).should.be.empty
it "returns non-empty if a pokemon has a level below 1", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Magikarp", level: 0)
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon has a bogus level", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Magikarp", level: "hi")
server.validateTeam(team).should.not.be.empty
# TODO: 100 is a magic constant
it "returns non-empty if a pokemon has a level over 100", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Magikarp", level: 101)
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon has an iv below 0", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Magikarp", ivs: { hp: -1 })
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon has an iv above 31", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Magikarp", ivs: { hp: 32 })
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon has bogus ivs", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Magikarp", ivs: true)
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon has an ev below 0", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Magikarp", evs: { hp: -1 })
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon has an ev above 255", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Magikarp", evs: { hp: 256 })
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon has an ev total above 510", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Magikarp", evs: { hp: 255, defense: 255, speed: 255 })
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon has bogus evs", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Magikarp", evs: true)
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon has an invalid gender", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Metagross", gender: "Alien")
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon has a gender it can't have", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Metagross", gender: "F")
server.validateTeam(team).should.not.be.empty
team = generateTeam()
team[0] = Factory("Blissey", gender: "M")
server.validateTeam(team).should.not.be.empty
team = generateTeam()
team[0] = Factory("Gallade", gender: "F")
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon has a bogus forme", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Blissey", forme: "Super Ultra Mega Blissey")
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon has a battle-only forme", ->
server = new BattleServer()
team = generateTeam()
team[0] = Factory("Meloetta", forme: "pirouette", moves: ["Relic Song"])
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon cannot have its forme"
it "returns non-empty if the format is fake", ->
server = new BattleServer()
server.validateTeam(generateTeam(), 'bogusformat').should.not.be.empty
it "returns non-empty if a pokemon's nickname matches another species", ->
server = new BattleServer()
team = generateTeam()
team[0].name = "Latios"
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon's nickname is blank", ->
server = new BattleServer()
team = generateTeam()
team[0].name = ""
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon's nickname contains illegal chars", ->
server = new BattleServer()
team = generateTeam()
team[0].name = "some chars \uFE20 are illegal"
server.validateTeam(team).should.not.be.empty
it "returns non-empty if a pokemon's nickname is past a certain length", ->
server = new BattleServer()
team = generateTeam()
team[0].name = ("A" for x in [0...50]).join('')
server.validateTeam(team).should.not.be.empty
describe "#beginBattles", ->
it "creates a battle per pair", (done) ->
server = new BattleServer()
for i in [1..4]
server.findOrCreateUser(id: i, name: "user#{i}", @stubSpark())
server.queuePlayer("user#{i}", generateTeam())
server.beginBattles (err, battleIds) ->
battleIds.length.should.equal(2)
done()
describe "users", ->
it "are recorded to be playing in which battles", (done) ->
server = new BattleServer()
[ user1, user2, user3 ] = [ "a", "b", "c" ]
for name, i in [ user1, user2, user3 ]
server.findOrCreateUser(id: i, name: name, @stubSpark())
server.queuePlayer(user1, generateTeam()).should.be.empty
server.queuePlayer(user2, generateTeam()).should.be.empty
server.queuePlayer(user3, generateTeam()).should.be.empty
server.beginBattles (err, battleIds) ->
server.getUserBattles(user1).should.eql(battleIds)
server.getUserBattles(user2).should.eql(battleIds)
server.getUserBattles(user3).should.be.empty
done()
it "no longer records battles once they end", (done) ->
server = new BattleServer()
[ user1, user2, user3 ] = [ "a", "b", "c" ]
for name, i in [ user1, user2, user3 ]
server.findOrCreateUser(id: i, name: name, @stubSpark())
server.queuePlayer(user1, generateTeam()).should.be.empty
server.queuePlayer(user2, generateTeam()).should.be.empty
server.queuePlayer(user3, generateTeam()).should.be.empty
server.beginBattles (err, battleIds) ->
for battleId in battleIds
battle = server.findBattle(battleId)
battle.endBattle()
server.getUserBattles(user1).should.be.empty
server.getUserBattles(user2).should.be.empty
server.getUserBattles(user3).should.be.empty
done()
it "can join multiple times", ->
server = new BattleServer()
server.findOrCreateUser(id: 1, name: "hey", spark1 = @stubSpark())
server.join(spark1)
(=>
server.findOrCreateUser(id: 1, name: "hey", spark2 = @stubSpark())
server.join(spark2)
).should.not.throw()
it "records battles they're under an alt in", (done) ->
server = new BattleServer()
[ user1, user2 ] = [ "a", "b" ]
for name, i in [ user1, user2 ]
server.findOrCreateUser(id: i, name: name, @stubSpark())
server.queuePlayer(user1, generateTeam(), null, 'alt1').should.be.empty
server.queuePlayer(user2, generateTeam(), null, 'alt2').should.be.empty
server.beginBattles (err, battleIds) ->
server.getUserBattles(user1).should.not.be.empty
server.getUserBattles(user2).should.not.be.empty
done()
it "auto-rejoin battles they're under an alt in", (done) ->
server = new BattleServer()
[ user1, user2 ] = [ "a", "b" ]
server.findOrCreateUser(id: 1, name: user1, spark1 = @stubSpark())
server.findOrCreateUser(id: 2, name: user2, spark2 = @stubSpark())
server.queuePlayer(user1, generateTeam(), null, 'alt1').should.be.empty
server.queuePlayer(user2, generateTeam(), null, 'alt2').should.be.empty
server.beginBattles (err, battleIds) =>
[battleId] = battleIds
battle = server.findBattle(battleId).battle
# test spark1
spy = @sandbox.spy(battle, 'tellPlayer').withArgs(user1, Protocol.RECEIVE_TEAM)
server.join(spark1)
spy.calledOnce.should.be.true
battle.tellPlayer.restore()
# test spark2
spy = @sandbox.spy(battle, 'tellPlayer').withArgs(user2, Protocol.RECEIVE_TEAM)
server.join(spark2)
spy.calledOnce.should.be.true
battle.tellPlayer.restore()
done()
it "automatically leaves a battle when leaving the server", (done) ->
server = new BattleServer()
[ user1, user2 ] = [ "a", "b" ]
server.findOrCreateUser(id: 1, name: user1, spark1 = @stubSpark())
server.findOrCreateUser(id: 2, name: user2, spark2 = @stubSpark())
server.join(spark1)
server.join(spark2)
server.queuePlayer(user1, generateTeam(), null, 'alt1').should.be.empty
server.queuePlayer(user2, generateTeam(), null, 'alt2').should.be.empty
server.beginBattles (err, battleIds) =>
[battleId] = battleIds
battle = server.findBattle(battleId).battle
# test spark1
spy = @sandbox.spy(battle, 'remove').withArgs(spark1)
broadcastSpy = @sandbox.spy(battle, 'send')
broadcastSpy = broadcastSpy.withArgs('leaveChatroom', battle.id, 'alt1')
server.leave(spark1)
spark1.end()
spy.calledOnce.should.be.true
broadcastSpy.calledOnce.should.be.true
battle.remove.restore()
battle.send.restore()
# test spark2
spy = @sandbox.spy(battle, 'remove').withArgs(spark2)
broadcastSpy = @sandbox.spy(battle, 'send')
broadcastSpy = broadcastSpy.withArgs('leaveChatroom', battle.id, 'alt2')
server.leave(spark2)
spark2.end()
spy.calledOnce.should.be.true
broadcastSpy.calledOnce.should.be.true
battle.remove.restore()
battle.send.restore()
done()
describe "a battle", ->
beforeEach (done) ->
@server = new BattleServer()
[ @user1, @user2, @user3 ] = [ "a", "b", "c" ]
for name, i in [ @user1, @user2, @user3 ]
@server.findOrCreateUser(id: i, name: name, @stubSpark())
@server.queuePlayer(@user1, generateTeam()).should.be.empty
@server.queuePlayer(@user2, generateTeam()).should.be.empty
@server.queuePlayer(@user3, generateTeam()).should.be.empty
@server.queuedPlayers().should.have.length(3)
@server.beginBattles (err, battleIds) =>
@battleIds = battleIds
@relevantUser = @server.findBattle(@battleIds[0]).battle.playerIds[0]
done()
it "removes from user battles if ended", ->
@server.getUserBattles(@relevantUser).should.not.be.empty
battle = @server.findBattle(@battleIds[0])
battle.endBattle()
@server.getUserBattles(@user1).should.be.empty
@server.getUserBattles(@user2).should.be.empty
@server.getUserBattles(@user3).should.be.empty
it "removes from user battles if forfeited", ->
@server.getUserBattles(@relevantUser).should.not.be.empty
battle = @server.findBattle(@battleIds[0])
battle.forfeit(@relevantUser)
@server.getUserBattles(@user1).should.be.empty
@server.getUserBattles(@user2).should.be.empty
@server.getUserBattles(@user3).should.be.empty