Merge in develop

This commit is contained in:
Blade Barringer
2015-05-24 15:46:57 -05:00
481 changed files with 13559 additions and 9393 deletions
+32
View File
@@ -0,0 +1,32 @@
# API Tests
Our API tests are written in [coffeescript](http://coffeescript.org/) using the [Mocha testing framework](http://mochajs.org/).
There's a variety of ways to run the tests:
```bash
# Individually
mocha test/api/name_of_test.coffee
# The entire collection of api tests
mocha test/api
# As part of the whole test suite
npm test
```
### Modules
Some modules are declared in the [api-helper.coffee](api-helper.coffee) file for use in any of the api tests:
* `moment` - time manipulation
* `async` - run async processes, good for before blocks
* `lodash (_)` - many utilities
* `shared` - generate uuids
* `expect` - making assertions
* `User` - look up a User in the db
### Helper Methods
There are helper methods declared in the [api-helper.coffee](api-helper.coffee) file. Some useful methods contained there:
* `registerNewUser(callback, main)` - Theres a global user variable that gets overwritten with the new user whenever you call `registerNewUser` unless you pass false in as the second argument.
* `registerManyUsers(number, callback)` - Good for testing things that require many users. The callback function returns new users as and array in the second argument.
+76
View File
@@ -0,0 +1,76 @@
##############################
# Global modules
##############################
superagentDefaults = require("superagent-defaults")
global.request = superagentDefaults()
global.mongoose = require("mongoose")
global.moment = require("moment")
global.async = require("async")
global._ = require("lodash")
global.shared = require("../../common")
global.User = require("../../website/src/models/user").model
global.chai = require("chai")
chai.use(require("sinon-chai"))
global.expect = chai.expect
##############################
# Nconf config
##############################
path = require("path")
global.conf = require("nconf")
conf.argv().env().file(file: path.join(__dirname, "../config.json")).defaults()
conf.set "PORT", "1337"
##############################
# Node ENV and global variables
##############################
process.env.NODE_DB_URI = "mongodb://localhost/habitrpg_test"
global.baseURL = "http://localhost:" + conf.get("PORT") + "/api/v2"
global.user = undefined
##############################
# Helper Methods
##############################
global.expectCode = (res, code) ->
expect(res.body.err).to.not.exist if code is 200
expect(res.statusCode).to.equal code
global.registerNewUser = (cb, main) ->
main = true unless main?
randomID = shared.uuid()
username = password = randomID if main
request
.post(baseURL + "/register")
.set("Accept", "application/json")
.set("X-API-User", null)
.set("X-API-Key", null)
.send
username: randomID
password: randomID
confirmPassword: randomID
email: randomID + "@gmail.com"
.end (res) ->
return cb(null, res.body) unless main
_id = res.body._id
apiToken = res.body.apiToken
User.findOne
_id: _id
apiToken: apiToken
, (err, _user) ->
expect(err).to.not.be.ok
global.user = _user
request
.set("Accept", "application/json")
.set("X-API-User", _id)
.set("X-API-Key", apiToken)
cb null, res.body
global.registerManyUsers = (number, callback) ->
async.times number, (n, next) ->
registerNewUser (err, user) ->
next(err, user)
, false
, (err, users) ->
callback(err, users)
+148
View File
@@ -0,0 +1,148 @@
'use strict'
app = require("../../website/src/server")
Group = require("../../website/src/models/group").model
Challenge = require("../../website/src/models/challenge").model
describe "Challenges", ->
challenge = undefined
updateTodo = undefined
group = undefined
before (done) ->
async.waterfall [
(cb) ->
registerNewUser(cb, true)
, (user, cb) ->
request.post(baseURL + "/groups").send(
name: "TestGroup"
type: "party"
).end (res) ->
expectCode res, 200
group = res.body
expect(group.members.length).to.equal 1
expect(group.leader).to.equal user._id
done()
]
it "Creates a challenge", (done) ->
request.post(baseURL + "/challenges").send(
group: group._id
dailys: [
type: "daily"
text: "Challenge Daily"
]
todos: [{
type: "todo"
text: "Challenge Todo 1"
notes: "Challenge Notes"
}, {
type: "todo"
text: "Challenge Todo 2"
notes: "Challenge Notes"
}]
rewards: []
habits: []
official: true
).end (res) ->
expectCode res, 200
async.parallel [
(cb) ->
User.findById user._id, cb
(cb) ->
Challenge.findById res.body._id, cb
], (err, results) ->
_user = results[0]
challenge = results[1]
expect(_user.dailys[_user.dailys.length - 1].text).to.equal "Challenge Daily"
updateTodo = _user.todos[_user.todos.length - 1]
expect(updateTodo.text).to.equal "Challenge Todo 2"
expect(challenge.official).to.equal false
user = _user
done()
it "User updates challenge notes", (done) ->
updateTodo.notes = "User overriden notes"
request.put(baseURL + "/user/tasks/" + updateTodo.id).send(updateTodo).end (res) ->
done() # we'll do the check down below
it "Change challenge daily", (done) ->
challenge.dailys[0].text = "Updated Daily"
challenge.todos[0].notes = "Challenge Updated Todo Notes"
request.post(baseURL + "/challenges/" + challenge._id).send(challenge).end (res) ->
setTimeout (->
User.findById user._id, (err, _user) ->
expectCode res, 200
expect(_user.dailys[_user.dailys.length - 1].text).to.equal "Updated Daily"
expect(res.body.todos[0].notes).to.equal "Challenge Updated Todo Notes"
expect(_user.todos[_user.todos.length - 1].notes).to.equal "User overriden notes"
user = _user
done()
), 500 # we have to wait a while for users' tasks to be updated, called async on server
it "Shows user notes on challenge page", (done) ->
request.get(baseURL + "/challenges/" + challenge._id + "/member/" + user._id).end (res) ->
expect(res.body.todos[res.body.todos.length - 1].notes).to.equal "User overriden notes"
done()
it "Complete To-Dos", (done) ->
User.findById user._id, (err, _user) ->
u = _user
numTasks = (_.size(u.todos))
request.post(baseURL + "/user/tasks/" + u.todos[0].id + "/up").end (res) ->
request.post(baseURL + "/user/tasks/clear-completed").end (res) ->
expect(_.size(res.body)).to.equal numTasks - 1
done()
it "Challenge deleted, breaks task link", (done) ->
itThis = this
request.del(baseURL + "/challenges/" + challenge._id).end (res) ->
User.findById user._id, (err, user) ->
len = user.dailys.length - 1
daily = user.dailys[user.dailys.length - 1]
expect(daily.challenge.broken).to.equal "CHALLENGE_DELETED"
# Now let's handle if challenge was deleted, but didn't get to update all the users (an error)
unset = $unset: {}
unset["$unset"]["dailys." + len + ".challenge.broken"] = 1
User.findByIdAndUpdate user._id, unset, (err, user) ->
expect(err).to.not.exist
expect(user.dailys[len].challenge.broken).to.not.exist
request.post(baseURL + "/user/tasks/" + daily.id + "/up").end (res) ->
setTimeout (->
User.findById user._id, (err, user) ->
expect(user.dailys[len].challenge.broken).to.equal "CHALLENGE_DELETED"
done()
), 100 # we need to wait for challenge to update user, it's a background job for perf reasons
it "Admin creates a challenge", (done) ->
User.findByIdAndUpdate user._id,
$set:
"contributor.admin": true
, (err, _user) ->
expect(err).to.not.exist
async.parallel [
(cb) ->
request.post(baseURL + "/challenges").send(
group: group._id
dailys: []
todos: []
rewards: []
habits: []
official: false
).end (res) ->
expect(res.body.official).to.equal false
cb()
(cb) ->
request.post(baseURL + "/challenges").send(
group: group._id
dailys: []
todos: []
rewards: []
habits: []
official: true
).end (res) ->
expect(res.body.official).to.equal true
cb()
], done
+191
View File
@@ -0,0 +1,191 @@
'use strict'
app = require("../../website/src/server")
Coupon = require("../../website/src/models/coupon").model
makeSudoUser = (usr, cb) ->
registerNewUser ->
sudoUpdate = { "$set" : { "contributor.sudo" : true } }
User.findByIdAndUpdate user._id, sudoUpdate, (err, _user) ->
usr = _user
cb()
, true
describe "Coupons", ->
before (done) ->
async.parallel [
(cb) ->
mongoose.connection.collections['coupons'].drop (err) ->
cb()
(cb) ->
mongoose.connection.collections['users'].drop (err) ->
cb()
], done
coupons = null
describe "POST /api/v2/coupons/generate/:event", ->
context "while sudo user", ->
before (done) ->
makeSudoUser(user, done)
it "generates coupons", (done) ->
queries = '?count=10'
request
.post(baseURL + '/coupons/generate/wondercon' + queries)
.end (res) ->
expectCode res, 200
Coupon.find { event: 'wondercon' }, (err, _coupons) ->
coupons = _coupons
expect(coupons.length).to.equal 10
_(coupons).each (c)->
expect(c.event).to.equal 'wondercon'
done()
context "while regular user", ->
before (done) ->
registerNewUser(done, true)
it "does not generate coupons", (done) ->
queries = '?count=10'
request
.post(baseURL + '/coupons/generate/wondercon' + queries)
.end (res) ->
expectCode res, 401
expect(res.body.err).to.equal 'You don\'t have admin access'
done()
describe "GET /api/v2/coupons", ->
context "while sudo user", ->
before (done) ->
makeSudoUser(user, done)
it "gets coupons", (done) ->
queries = '?_id=' + user._id + '&apiToken=' + user.apiToken
request
.get(baseURL + '/coupons' + queries)
.end (res) ->
expectCode res, 200
codes = res.text
expect(codes).to.contain('code')
# Expect each coupon code _id to exist in response
_(coupons).each (c) -> expect(codes).to.contain(c._id)
done()
it "gets first 5 coupons out of 10 when a limit of 5 is set", (done) ->
queries = '?_id=' + user._id + '&apiToken=' + user.apiToken + '&limit=5'
request
.get(baseURL + '/coupons' + queries)
.end (res) ->
expectCode res, 200
codes = res.text
sortedCoupons = _.sortBy(coupons, 'seq')
firstHalf = sortedCoupons[0..4]
secondHalf = sortedCoupons[5..9]
# First five coupons should be present in codes
_(firstHalf).each (c) -> expect(codes).to.contain(c._id)
# Second five coupons should not be present in codes
_(secondHalf).each (c) -> expect(codes).to.not.contain(c._id)
done()
it "gets last 5 coupons out of 10 when a limit of 5 is set", (done) ->
queries = '?_id=' + user._id + '&apiToken=' + user.apiToken + '&skip=5'
request
.get(baseURL + '/coupons' + queries)
.end (res) ->
expectCode res, 200
codes = res.text
sortedCoupons = _.sortBy(coupons, 'seq')
firstHalf = sortedCoupons[0..4]
secondHalf = sortedCoupons[5..9]
# First five coupons should not be present in codes
_(firstHalf).each (c) -> expect(codes).to.not.contain(c._id)
# Second five coupons should be present in codes
_(secondHalf).each (c) -> expect(codes).to.contain(c._id)
done()
context "while regular user", ->
before (done) ->
registerNewUser(done, true)
it "does not get coupons", (done) ->
queries = '?_id=' + user._id + '&apiToken=' + user.apiToken
request
.get(baseURL + '/coupons' + queries)
.end (res) ->
expectCode res, 401
expect(res.body.err).to.equal 'You don\'t have admin access'
done()
describe "POST /api/v2/user/coupon/:code", ->
specialGear = (gear, has) ->
items = ['body_special_wondercon_gold'
'body_special_wondercon_black'
'body_special_wondercon_red'
'back_special_wondercon_red'
'back_special_wondercon_black'
'back_special_wondercon_red'
'eyewear_special_wondercon_black'
'eyewear_special_wondercon_red']
_(items).each (i) ->
if(has)
expect(gear[i]).to.exist
else
expect(gear[i]).to.not.exist
beforeEach (done) ->
registerNewUser ->
gear = user.items.gear.owned
specialGear(gear, false)
done()
, true
context "unused coupon", ->
it "applies coupon and awards equipment", (done) ->
code = coupons[0]._id
request
.post(baseURL + '/user/coupon/' + code)
.end (res) ->
expectCode res, 200
gear = res.body.items.gear.owned
specialGear(gear, true)
done()
context "already used coupon", ->
it "does not apply coupon and does not award equipment", (done) ->
code = coupons[0]._id
request
.post(baseURL + '/user/coupon/' + code)
.end (res) ->
expectCode res, 400
expect(res.body.err).to.equal "Coupon already used"
User.findById user._id, (err, _user) ->
gear = _user.items.gear.owned
specialGear(gear, false)
done()
context "invalid coupon", ->
it "does not apply coupon and does not award equipment", (done) ->
code = "not-a-real-coupon"
request
.post(baseURL + '/user/coupon/' + code)
.end (res) ->
expectCode res, 400
expect(res.body.err).to.equal "Invalid coupon code"
User.findById user._id, (err, _user) ->
gear = _user.items.gear.owned
specialGear(gear, false)
done()
+564
View File
@@ -0,0 +1,564 @@
'use strict'
diff = require("deep-diff")
Group = require("../../website/src/models/group").model
app = require("../../website/src/server")
describe "Groups", ->
describe "Guilds", ->
before (done) ->
registerNewUser ->
User.findByIdAndUpdate user._id,
$set:
"balance": 4
, (err, _user) ->
done()
, true
describe "Private Guilds", ->
guild = undefined
before (done) ->
request.post(baseURL + "/groups").send(
name: "TestPrivateGroup"
type: "guild"
privacy: "private"
).end (res) ->
expectCode res, 200
guild = res.body
expect(guild.members.length).to.equal 1
expect(guild.leader).to.equal user._id
#Add members to guild
async.waterfall [
(cb) ->
registerManyUsers 15, cb
(_members, cb) ->
members = _members
joinGuild = (member, callback) ->
request.post(baseURL + "/groups/" + guild._id + "/join")
.set("X-API-User", member._id)
.set("X-API-Key", member.apiToken)
.end ->
callback(null, null)
async.map members, joinGuild, (err, results) -> cb()
], done
it "includes user in private group member list when user is a member", (done) ->
request.get(baseURL + "/groups/" + guild._id)
.end (res) ->
g = res.body
userInGroup = _.find g.members, (member) -> return member._id == user._id
expect(userInGroup).to.exist
done()
it "excludes user from viewing private group member list when user is not a member", (done) ->
request.post(baseURL + "/groups/" + guild._id + "/leave")
.end (res) ->
request.get(baseURL + "/groups/" + guild._id)
.end (res) ->
expect res, 404
done()
describe "Public Guilds", ->
guild = undefined
before (done) ->
request.post(baseURL + "/groups").send(
name: "TestPublicGroup"
type: "guild"
privacy: "public"
).end (res) ->
expectCode res, 200
guild = res.body
expect(guild.members.length).to.equal 1
expect(guild.leader).to.equal user._id
#Add members to guild
async.waterfall [
(cb) ->
registerManyUsers 15, cb
(_members, cb) ->
members = _members
joinGuild = (member, callback) ->
request.post(baseURL + "/groups/" + guild._id + "/join")
.set("X-API-User", member._id)
.set("X-API-Key", member.apiToken)
.end ->
callback(null, null)
async.map members, joinGuild, (err, results) -> cb()
], done
context "is a member", ->
before (done) ->
registerNewUser ->
request.post(baseURL + "/groups/" + guild._id + "/join")
.end ->
done()
, true
it "includes user in public group member list", (done) ->
request.get(baseURL + "/groups/" + guild._id)
.end (res) ->
g = res.body
expect(g.members.length).to.equal 15
userInGroup = _.find g.members, (member) -> return member._id == user._id
expect(userInGroup).to.be.ok
done()
context "is not a member", ->
before (done) ->
registerNewUser done, true
it "excludes user in public group member list", (done) ->
request.get(baseURL + "/groups/" + guild._id)
.end (res) ->
g = res.body
expect(g.members.length).to.equal 15
userInGroup = _.find g.members, (member) -> return member._id == user._id
expect(userInGroup).to.not.be.ok
done()
describe "Party", ->
group = undefined
before (done) ->
async.waterfall [
(cb) ->
registerNewUser(cb, true)
, (user, cb) ->
request.post(baseURL + "/groups").send(
name: "TestGroup"
type: "party"
).end (res) ->
expectCode res, 200
group = res.body
expect(group.members.length).to.equal 1
expect(group.leader).to.equal user._id
done()
]
it "can be found by querying for party", (done) ->
request.get(baseURL + "/groups/").send(
type: "party"
).end (res) ->
expectCode res, 200
party = res.body[0]
expect(party._id).to.equal group._id
expect(party.leader).to.equal user._id
expect(party.name).to.equal group.name
expect(party.quest).to.deep.equal { progress: {} }
expect(party.memberCount).to.equal group.memberCount
done()
describe "Chat", ->
chat = undefined
it "Posts a message to party chat", (done) ->
msg = "TestMsg"
request.post(baseURL + "/groups/" + group._id + "/chat?message=" + msg).send(
).end (res) ->
expectCode res, 200
chat = res.body.message
expect(chat.id).to.be.ok
expect(chat.text).to.equal msg
expect(chat.timestamp).to.be.ok
expect(chat.likes).to.be.empty
expect(chat.flags).to.be.empty
expect(chat.flagCount).to.equal 0
expect(chat.uuid).to.be.ok
expect(chat.contributor).to.be.empty
expect(chat.backer).to.be.empty
expect(chat.uuid).to.equal user._id
expect(chat.user).to.equal user.profile.name
done()
it "Does not post an empty message", (done) ->
msg = ""
request.post(baseURL + "/groups/" + group._id + "/chat?message=" + msg).send(
).end (res) ->
expectCode res, 400
expect(res.body.err).to.equal 'You cannot send a blank message'
done()
it "can not like own chat message", (done) ->
request.post(baseURL + "/groups/" + group._id + "/chat/" + chat.id + "/like").send(
).end (res) ->
expectCode res, 401
body = res.body
expect(body.err).to.equal "Can't like your own message. Don't be that person."
done()
it "can not flag own message", (done) ->
request.post(baseURL + "/groups/" + group._id + "/chat/" + chat.id + "/flag").send(
).end (res) ->
expectCode res, 401
body = res.body
expect(body.err).to.equal "Can't report your own message."
done()
it "Gets chat messages from party chat", (done) ->
request.get(baseURL + "/groups/" + group._id + "/chat").send(
).end (res) ->
expectCode res, 200
message = res.body[0]
expect(message.id).to.equal chat.id
expect(message.timestamp).to.equal chat.timestamp
expect(message.likes).to.deep.equal chat.likes
expect(message.flags).to.deep.equal chat.flags
expect(message.flagCount).to.equal chat.flagCount
expect(message.uuid).to.equal chat.uuid
expect(message.contributor).to.deep.equal chat.contributor
expect(message.backer).to.deep.equal chat.backer
expect(message.user).to.equal chat.user
done()
it "Deletes a chat messages from party chat", (done) ->
request.del(baseURL + "/groups/" + group._id + "/chat/" + chat.id).send(
).end (res) ->
expectCode res, 204
expect(res.body).to.be.empty
done()
it "Can not delete already deleted message", (done) ->
request.del(baseURL + "/groups/" + group._id + "/chat/" + chat.id).send(
).end (res) ->
expectCode res, 404
body = res.body
expect(body.err).to.equal "Message not found!"
done()
describe "Quests", ->
party = undefined
participating = []
notParticipating = []
before (done) ->
# Tavern boss, side-by-side
Group.update(
_id: "habitrpg"
,
$set:
quest:
key: "dilatory"
active: true
progress:
hp: shared.content.quests.dilatory.boss.hp
rage: 0
).exec()
# Tally some progress for later. Later we want to test that progress made before the quest began gets
# counted after the quest starts
async.waterfall [
(cb) ->
request.post(baseURL + '/user/tasks').send({
type: 'daily'
text: 'daily one'
}).end (res) ->
cb()
(cb) ->
request.post(baseURL + '/user/tasks').send({
type: 'daily'
text: 'daily two'
}).end (res) ->
cb()
(cb) ->
User.findByIdAndUpdate user._id,
$set:
"stats.lvl": 50
, (err, _user) ->
cb(null, _user)
(_user, cb) ->
user = _user
request.post(baseURL + "/user/batch-update").send([
{
op: "score"
params:
direction: "up"
id: user.dailys[0].id
}
{
op: "score"
params:
direction: "up"
id: user.dailys[0].id
}
{
op: "update"
body:
"stats.lvl": 50
}
]).end (res) ->
user = res.body
expect(user.party.quest.progress.up).to.be.above 0
# Invite some members
async.waterfall [
# Register new users
(cb) ->
registerManyUsers 3, cb
# Send them invitations
(_party, cb) ->
party = _party
inviteURL = baseURL + "/groups/" + group._id + "/invite"
async.parallel [
(cb2) ->
request.post(inviteURL).send(
uuids: [party[0]._id]
).end ->
cb2()
(cb2) ->
request.post(inviteURL).send(
uuids: [party[1]._id]
).end ->
cb2()
(cb2) ->
request.post(inviteURL).send(
uuids: [party[2]._id]
).end (res)->
cb2()
], cb
# Accept / Reject
(results, cb) ->
# series since they'll be modifying the same group record
series = _.reduce(party, (m, v, i) ->
m.push (cb2) ->
request.post(baseURL + "/groups/" + group._id + "/join").set("X-API-User", party[i]._id).set("X-API-Key", party[i].apiToken).end ->
cb2()
m
, [])
async.series series, cb
# Make sure the invites stuck
(whatever, cb) ->
Group.findById group._id, (err, g) ->
group = g
expect(g.members.length).to.equal 4
cb()
], ->
# Start the quest
async.waterfall [
(cb) ->
request.post(baseURL + "/groups/" + group._id + "/questAccept?key=vice3").end (res) ->
expectCode res, 400
User.findByIdAndUpdate user._id,
$set:
"items.quests.vice3": 1
, cb
(_user, cb) ->
request.post(baseURL + "/groups/" + group._id + "/questAccept?key=vice3").end (res) ->
expectCode res, 200
Group.findById group._id, cb
(_group, cb) ->
expect(_group.quest.key).to.equal "vice3"
expect(_group.quest.active).to.equal false
request.post(baseURL + "/groups/" + group._id + "/questAccept").set("X-API-User", party[0]._id).set("X-API-Key", party[0].apiToken).end ->
request.post(baseURL + "/groups/" + group._id + "/questAccept").set("X-API-User", party[1]._id).set("X-API-Key", party[1].apiToken).end (res) ->
request.post(baseURL + "/groups/" + group._id + "/questReject").set("X-API-User", party[2]._id).set("X-API-Key", party[2].apiToken).end (res) ->
group = res.body
expect(group.quest.active).to.equal true
cb()
], done
]
it "Casts a spell", (done) ->
mp = user.stats.mp
request.get(baseURL + "/members/" + party[0]._id).end (res) ->
party[0] = res.body
request.post(baseURL + "/user/class/cast/snowball?targetType=user&targetId=" + party[0]._id).end (res) ->
#expect(res.body.stats.mp).to.be.below(mp);
request.get(baseURL + "/members/" + party[0]._id).end (res) ->
member = res.body
expect(member.achievements.snowball).to.equal 1
expect(member.stats.buffs.snowball).to.exist
difference = diff(member, party[0])
expect(_.size(difference)).to.equal 2
# level up user so str is > 0
request.put(baseURL + "/user").send("stats.lvl": 5).end (res) ->
# Refill mana so user can cast
request.put(baseURL + "/user").send("stats.mp": 100).end (res) ->
request.post(baseURL + "/user/class/cast/valorousPresence?targetType=party").end (res) ->
request.get(baseURL + "/members/" + member._id).end (res) ->
expect(res.body.stats.buffs.str).to.be.above 0
expect(diff(res.body, member).length).to.equal 1
done()
it "Doesn't include people who aren't participating", (done) ->
request.get(baseURL + "/groups/" + group._id).end (res) ->
expect(_.size(res.body.quest.members)).to.equal 3
done()
xit "Hurts the boss", (done) ->
request.post(baseURL + "/user/batch-update").end (res) ->
user = res.body
up = user.party.quest.progress.up
expect(up).to.be.above 0
#{op:'score',params:{direction:'up',id:user.dailys[3].id}}, // leave one daily undone so Trapper hurts party
# set day to yesterday, cron will then be triggered on next action
request.post(baseURL + "/user/batch-update").send([
{
op: "score"
params:
direction: "up"
id: user.dailys[0].id
}
{
op: "update"
body:
lastCron: moment().subtract(1, "days")
}
]).end (res) ->
expect(res.body.party.quest.progress.up).to.be.above up
request.post(baseURL + "/user/batch-update").end ->
request.get(baseURL + "/groups/party").end (res) ->
# Check boss damage
async.waterfall [
(cb) ->
async.parallel [
#tavern boss
(cb2) ->
Group.findById "habitrpg",
quest: 1
, (err, tavern) ->
expect(tavern.quest.progress.hp).to.be.below shared.content.quests.dilatory.boss.hp
expect(tavern.quest.progress.rage).to.be.above 0
cb2()
# party boss
(cb2) ->
expect(res.body.quest.progress.hp).to.be.below shared.content.quests.vice3.boss.hp
_party = res.body.members
expect(_.find(_party,
_id: party[0]._id
).stats.hp).to.be.below 50
expect(_.find(_party,
_id: party[1]._id
).stats.hp).to.be.below 50
expect(_.find(_party,
_id: party[2]._id
).stats.hp).to.be 50
cb2()
], cb
# Kill the boss
(whatever, cb) ->
async.waterfall [
# tavern boss
(cb2) ->
expect(user.items.pets["MantisShrimp-Base"]).to.not.be.ok()
Group.update
_id: "habitrpg"
,
$set:
"quest.progress.hp": 0
, cb2
# party boss
(arg1, arg2, cb2) ->
expect(user.items.gear.owned.weapon_special_2).to.not.be.ok()
Group.findByIdAndUpdate group._id,
$set:
"quest.progress.hp": 0
, cb2
], cb
(_group, cb) ->
# set day to yesterday, cron will then be triggered on next action
request.post(baseURL + "/user/batch-update").send([
{
op: "score"
params:
direction: "up"
id: user.dailys[1].id
}
{
op: "update"
body:
lastCron: moment().subtract(1, "days")
}
]).end ->
cb()
(cb) ->
request.post(baseURL + "/user/batch-update").end (res) ->
cb null, res.body
(_user, cb) ->
# need to load the user again, since tavern boss does update after user's cron
User.findById _user._id, cb
(_user, cb) ->
user = _user
Group.findById group._id, cb
(_group, cb) ->
cummExp = shared.content.quests.vice3.drop.exp + shared.content.quests.dilatory.drop.exp
cummGp = shared.content.quests.vice3.drop.gp + shared.content.quests.dilatory.drop.gp
#//FIXME check that user got exp, but user is leveling up making the exp check difficult
# expect(user.stats.exp).to.be.above(cummExp);
# expect(user.stats.gp).to.be.above(cummGp);
async.parallel [
# Tavern Boss
(cb2) ->
Group.findById "habitrpg", (err, tavern) ->
#use an explicit get because mongoose wraps the null in an object
expect(_.isEmpty(tavern.get("quest"))).to.equal true
expect(user.items.pets["MantisShrimp-Base"]).to.equal 5
expect(user.items.mounts["MantisShrimp-Base"]).to.equal true
expect(user.items.eggs.Dragon).to.equal 2
expect(user.items.hatchingPotions.Shade).to.equal 2
cb2()
# Party Boss
(cb2) ->
#use an explicit get because mongoose wraps the null in an object
expect(_.isEmpty(_group.get("quest"))).to.equal true
expect(user.items.gear.owned.weapon_special_2).to.equal true
expect(user.items.eggs.Dragon).to.equal 2
expect(user.items.hatchingPotions.Shade).to.equal 2
# need to fetch users to get updated data
async.parallel [
(cb3) ->
User.findById party[0].id, (err, mbr) ->
expect(mbr.items.gear.owned.weapon_special_2).to.equal true
cb3()
(cb3) ->
User.findById party[1].id, (err, mbr) ->
expect(mbr.items.gear.owned.weapon_special_2).to.equal true
cb3()
(cb3) ->
User.findById party[2].id, (err, mbr) ->
expect(mbr.items.gear.owned.weapon_special_2).to.not.be.ok()
cb3()
], cb2
], cb
], done
+306
View File
@@ -0,0 +1,306 @@
'use strict'
app = require("../../website/src/server")
rewire = require('rewire')
sinon = require('sinon')
describe "Push-Notifications", ->
before (done) ->
registerNewUser(done, true)
describe "POST /user/pushDevice", ->
it "Registers a DeviceID", (done) ->
request.post(baseURL + "/user/pushDevice").send(
{ regId: "123123", type: "android"}
).end (res) ->
expectCode res, 200
User.findOne
_id: global.user._id
, (err, _user) ->
expect(_user.pushDevices.length).to.equal 1
expect(_user.pushDevices[0].regId).to.equal "123123"
done()
describe "Events that send push notifications", ->
pushSpy = { sendNotify: sinon.spy() }
afterEach (done) ->
pushSpy.sendNotify.reset()
done()
context "Challenges", ->
challenges = rewire("../../website/src/controllers/challenges")
challenges.__set__('pushNotify', pushSpy)
challengeMock = {
findById: (arg, cb) ->
cb(null, {leader: user._id, name: 'challenge-name'})
}
userMock = {
findById: (arg, cb) ->
cb(null, user)
}
challenges.__set__('Challenge', challengeMock)
challenges.__set__('User', userMock)
challenges.__set__('closeChal', -> true)
beforeEach (done) ->
registerNewUser ->
user.preferences.emailNotifications.wonChallenge = false
user.save = (cb) -> cb(null, user)
done()
, true
it "sends a push notification when you win a challenge", (done) ->
req = {
params: { cid: 'challenge-id' }
query: {uid: 'user-id'}
}
res = {
locals: { user: user }
}
challenges.selectWinner req, res
setTimeout -> # Allow selectWinner to finish
expect(pushSpy.sendNotify).to.have.been.calledOnce
expect(pushSpy.sendNotify).to.have.been.calledWith(
user,
'You Won a Challenge',
'challenge-name'
)
done()
, 100
context "Groups", ->
recipient = null
groups = rewire("../../website/src/controllers/groups")
groups.__set__('questStart', -> true)
groups.__set__('pushNotify', pushSpy)
before (done) ->
registerNewUser (err,_user)->
recipient = _user
recipient.invitations.guilds = []
recipient.save = (cb) -> cb(null, recipient)
recipient.preferences.emailNotifications.invitedGuild = false
recipient.preferences.emailNotifications.invitedParty = false
recipient.preferences.emailNotifications.invitedQuest = false
userMock = {
findById: (arg, cb) ->
cb(null, recipient)
find: (arg, arg2, cb) ->
cb(null, [recipient])
}
groups.__set__('User', userMock)
done()
, false
it "sends a push notification when invited to a guild", (done) ->
group = { _id: 'guild-id', name: 'guild-name', type: 'guild', members: [user._id], invites: [] }
group.save = (cb) -> cb(null, group)
req = {
body: { uuids: [recipient._id] }
}
res = {
locals: { group: group, user: user }
json: -> return true
}
groups.invite req, res
setTimeout -> # Allow invite to finish
expect(pushSpy.sendNotify).to.have.been.calledOnce
expect(pushSpy.sendNotify).to.have.been.calledWith(
recipient,
'Invited To Guild',
group.name
)
done()
, 100
it "sends a push notification when invited to a party", (done) ->
group = { _id: 'party-id', name: 'party-name', type: 'party', members: [user._id], invites: [] }
group.save = (cb) -> cb(null, group)
req = {
body: { uuids: [recipient._id] }
}
res = {
locals: { group: group, user: user }
json: -> return true
}
groups.invite req, res
setTimeout -> # Allow invite to finish
expect(pushSpy.sendNotify).to.have.been.calledOnce
expect(pushSpy.sendNotify).to.have.been.calledWith(
recipient,
'Invited To Party',
group.name
)
done()
, 100
it "sends a push notification when invited to a quest", (done) ->
group = { _id: 'party-id', name: 'party-name', type: 'party', members: [user._id, recipient._id], invites: [], quest: {}}
user.items.quests.hedgehog = 5
group.save = (cb) -> cb(null, group)
req = {
body: { uuids: [recipient._id] }
query: { key: 'hedgehog' }
}
res = {
locals: { group: group, user: user }
json: -> return true
}
groups.questAccept req, res
setTimeout -> # Allow questAccept to finish
expect(pushSpy.sendNotify).to.have.been.calledOnce
expect(pushSpy.sendNotify).to.have.been.calledWith(
recipient,
'Quest Invitation',
'Invitation for the Quest The Hedgebeast'
)
done()
, 100
describe "Gifts", ->
recipient = null
before (done) ->
registerNewUser (err, _user) ->
recipient = _user
recipient.preferences.emailNotifications.giftedGems = false
user.balance = 4
user.save = -> return true
recipient.save = -> return true
done()
, false
context "sending gems from balance", ->
members = rewire("../../website/src/controllers/members")
members.sendMessage = -> true
members.__set__('pushNotify', pushSpy)
members.__set__ 'fetchMember', (id) ->
return (cb) -> cb(null, recipient)
it "sends a push notification", (done) ->
req = {
params: { uuid: "uuid" },
body: {
type: 'gems',
gems: { amount: 1 }
}
}
res = { locals: { user: user } }
members.sendGift req, res
setTimeout -> # Allow sendGift to finish
expect(pushSpy.sendNotify).to.have.been.calledOnce
expect(pushSpy.sendNotify).to.have.been.calledWith(
recipient,
'Gifted Gems',
'1 Gems - by ' + user.profile.name
)
done()
, 100
describe "Purchases", ->
payments = rewire("../../website/src/controllers/payments")
payments.__set__('pushNotify', pushSpy)
membersMock = { sendMessage: -> true }
payments.__set__('members', membersMock)
context "buying gems as a purchased gift", ->
it "sends a push notification", (done) ->
data = {
user: user,
gift: {
member: recipient,
gems: { amount: 1 }
}
}
payments.buyGems data
setTimeout -> # Allow buyGems to finish
expect(pushSpy.sendNotify).to.have.been.calledOnce
expect(pushSpy.sendNotify).to.have.been.calledWith(
recipient,
'Gifted Gems',
'1 Gems - by ' + user.profile.name
)
done()
, 100
it "does not send a push notification if buying gems for self", (done) ->
data = {
user: user,
gift: {
member: user
gems: { amount: 1 }
}
}
payments.buyGems data
setTimeout -> # Allow buyGems to finish
expect(pushSpy.sendNotify).to.not.have.been.called
done()
, 100
context "sending a subscription as a purchased gift", ->
it "sends a push notification", (done) ->
data = {
user: user,
gift: {
member: recipient
subscription: { key: 'basic_6mo' }
}
}
payments.createSubscription data
setTimeout -> # Allow createSubscription to finish
expect(pushSpy.sendNotify).to.have.been.calledOnce
expect(pushSpy.sendNotify).to.have.been.calledWith(
recipient,
'Gifted Subscription',
'6 months - by ' + user.profile.name
)
done()
, 100
it "does not send a push notification if buying subscription for self", (done) ->
data = {
user: user,
gift: {
member: user
subscription: { key: 'basic_6mo' }
}
}
payments.createSubscription data
setTimeout -> # Allow buyGems to finish
expect(pushSpy.sendNotify).to.not.have.been.called
done()
, 100
+41
View File
@@ -0,0 +1,41 @@
'use strict'
app = require("../../website/src/server")
describe "Site Status", ->
describe "Without token or user id", ->
it "/api/v2/status", (done) ->
request.get(baseURL + "/status").set("Accept", "application/json").end (res) ->
expect(res.statusCode).to.equal 200
expect(res.body.status).to.equal "up"
done()
it "/api/v2/user", (done) ->
request
.get(baseURL + "/user")
.set("Accept", "application/json")
.set("X-API-User", '')
.set("X-API-Key", '')
.end (res) ->
expect(res.statusCode).to.equal 401
expect(res.body.err).to.equal "You must include a token and uid (user id) in your request"
done()
describe "With token or user id", ->
before (done) ->
registerNewUser(done, true)
it "/api/v2/status", (done) ->
request.get(baseURL + "/status").set("Accept", "application/json").end (res) ->
expect(res.statusCode).to.equal 200
expect(res.body.status).to.equal "up"
done()
it "/api/v2/user", (done) ->
request.get(baseURL + "/user").set("Accept", "application/json").end (res) ->
expect(res.statusCode).to.equal 200
expect(res.body._id).to.equal user._id
done()
+41
View File
@@ -0,0 +1,41 @@
'use strict'
payments = require("../../website/src/controllers/payments")
app = require("../../website/src/server")
describe "Subscriptions", ->
before (done) ->
registerNewUser(done, true)
it "Handles unsubscription", (done) ->
cron = ->
user.lastCron = moment().subtract(1, "d")
user.fns.cron()
expect(user.purchased.plan.customerId).to.not.exist
payments.createSubscription
user: user
customerId: "123"
paymentMethod: "Stripe"
sub: {key: 'basic_6mo'}
expect(user.purchased.plan.customerId).to.exist
shared.wrap user
cron()
expect(user.purchased.plan.customerId).to.exist
payments.cancelSubscription user: user
cron()
expect(user.purchased.plan.customerId).to.exist
expect(user.purchased.plan.dateTerminated).to.exist
user.purchased.plan.dateTerminated = moment().subtract(2, "d")
cron()
expect(user.purchased.plan.customerId).to.not.exist
payments.createSubscription
user: user
customerId: "123"
paymentMethod: "Stripe"
sub: {key: 'basic_6mo'}
expect(user.purchased.plan.dateTerminated).to.not.exist
done()
+165
View File
@@ -0,0 +1,165 @@
'use strict'
require("../../website/src/server")
describe "Todos", ->
before (done) ->
registerNewUser done, true
beforeEach (done) ->
User.findById user._id, (err, _user) ->
user = _user
shared.wrap user
done()
it "Archives old todos", (done) ->
numTasks = _.size(user.todos)
request.post(baseURL + "/user/batch-update?_v=999").send([
{
op: "addTask"
body:
type: "todo"
}
{
op: "addTask"
body:
type: "todo"
}
{
op: "addTask"
body:
type: "todo"
}
]).end (res) ->
expectCode res, 200
# Expect number of todos to be 3 greater than the number the user started with
expect(_.size(res.body.todos)).to.equal numTasks + 3
# Assign new number to numTasks variable
numTasks += 3
request.post(baseURL + "/user/batch-update?_v=998").send([
{
op: "score"
params:
direction: "up"
id: res.body.todos[0].id
}
{
op: "score"
params:
direction: "up"
id: res.body.todos[1].id
}
{
op: "score"
params:
direction: "up"
id: res.body.todos[2].id
}
]).end (res) ->
expectCode res, 200
expect(_.size(res.body.todos)).to.equal numTasks
request.post(baseURL + "/user/batch-update?_v=997").send([
{
op: "updateTask"
params:
id: res.body.todos[0].id
body:
dateCompleted: moment().subtract(4, "days")
}
{
op: "updateTask"
params:
id: res.body.todos[1].id
body:
dateCompleted: moment().subtract(4, "days")
}
]).end (res) ->
# Expect todos to be 2 less than the total count
expect(_.size(res.body.todos)).to.equal numTasks - 2
done()
describe "Creating, Updating, Deleting Todos", ->
todo = undefined
updateTodo = undefined
describe "Creating todos", ->
it "Creates a todo", (done) ->
request.post(baseURL + "/user/tasks").send(
type: "todo"
text: "Sample Todo"
).end (res) ->
expectCode res, 200
todo = res.body
expect(todo.text).to.equal "Sample Todo"
expect(todo.id).to.be.ok
expect(todo.value).to.equal 0
done()
describe "Updating todos", ->
it "Does not update id of todo", (done) ->
request.put(baseURL + "/user/tasks/" + todo.id).send(
id: "a-new-id"
).end (res) ->
expectCode res, 200
updateTodo = res.body
expect(updateTodo.id).to.equal todo.id
done()
it "Does not update type of todo", (done) ->
request.put(baseURL + "/user/tasks/" + todo.id).send(
type: "habit"
).end (res) ->
expectCode res, 200
updateTodo = res.body
expect(updateTodo.type).to.equal todo.type
done()
it "Does update text, attribute, priority, value, notes", (done) ->
request.put(baseURL + "/user/tasks/" + todo.id).send(
text: "Changed Title"
attribute: "int"
priority: 1.5
value: 5
notes: "Some notes"
).end (res) ->
expectCode res, 200
todo = res.body
expect(todo.text).to.equal "Changed Title"
expect(todo.attribute).to.equal "int"
expect(todo.priority).to.equal 1.5
expect(todo.value).to.equal 5
expect(todo.notes).to.equal "Some notes"
done()
describe "Deleting todos", ->
it "Does delete todo", (done) ->
request.del(baseURL + "/user/tasks/" + todo.id).send(
).end (res) ->
expectCode res, 200
body = res.body
expect(body).to.be.empty
done()
it "Does not delete already deleted todo", (done) ->
request.del(baseURL + "/user/tasks/" + todo.id).send(
).end (res) ->
expectCode res, 404
body = res.body
expect(body.err).to.equal "Task not found."
done()
it "Does not update text, attribute, priority, value, notes if task is already deleted", (done) ->
request.put(baseURL + "/user/tasks/" + todo.id).send(
text: "New Title"
attribute: "str"
priority: 1
value: 4
notes: "Other notes"
).end (res) ->
expectCode res, 404
body = res.body
expect(body.err).to.equal "Task not found."
done()
+106 -23
View File
@@ -92,7 +92,7 @@ expectGainedPoints = (before, after, taskType) ->
# daily & todo histories handled on cron
expectNoChange = (before,after) ->
_.each $w('stats items gear dailys todos rewards flags preferences'), (attr)->
_.each $w('stats items gear dailys todos rewards preferences'), (attr)->
expect(after[attr]).to.eql before[attr]
expectClosePoints = (before, after, taskType) ->
@@ -162,12 +162,12 @@ describe 'User', ->
cron()
expect(user.stats.buffs.str).to.be 0
expect(user.achievements.perfect).to.not.be.ok
expect(user.achievements.perfect).to.not.be.ok()
user.dailys[0].completed = true
cron()
expect(user.stats.buffs.str).to.be 0
expect(user.achievements.perfect).to.not.be.ok
expect(user.achievements.perfect).to.not.be.ok()
_.each user.dailys, (d)->d.completed = true
cron()
@@ -182,23 +182,25 @@ describe 'User', ->
expect(user.stats.buffs.str).to.be 1
expect(user.achievements.perfect).to.be 2
describe.skip 'Resting in the Inn', ->
describe 'Resting in the Inn', ->
user = null
cron = null
beforeEach ->
user = newUser()
user.preferences.sleep = true
cron = -> user.lastCron = moment().subtract(1, 'days');user.fns.cron()
user.dailys = []
_.times 2, -> user.dailys.push shared.taskDefaults({type:'daily'})
it 'remains in the inn on cron', ->
cron()
expect(user.preferences.sleep).to.be.ok
expect(user.preferences.sleep).to.be true
it 'resets dailies', ->
user.dailys[0].completed = true
cron()
expect(user.dailys[0].completed).to.not.be.ok
expect(user.dailys[0].completed).to.be false
it 'resets checklist on incomplete dailies', ->
user.dailys[0].checklist = [
@@ -220,7 +222,7 @@ describe 'User', ->
]
cron()
_.each user.dailys[0].checklist, (box)->
expect(box.completed).to.not.be.ok
expect(box.completed).to.be false
it 'resets checklist on complete dailies', ->
user.dailys[0].checklist = [
@@ -243,7 +245,58 @@ describe 'User', ->
user.dailys[0].completed = true
cron()
_.each user.dailys[0].checklist, (box)->
expect(box.completed).to.not.be.ok
expect(box.completed).to.be false
it 'does not reset checklist on grey incomplete dailies', ->
yesterday = moment().subtract(1,'days')
user.dailys[0].repeat[shared.dayMapping[yesterday.day()]] = 0
user.dailys[0].checklist = [
{
"text" : "1",
"id" : "checklist-one",
"completed" : true
},
{
"text" : "2",
"id" : "checklist-two",
"completed" : true
},
{
"text" : "3",
"id" : "checklist-three",
"completed" : true
}
]
cron()
_.each user.dailys[0].checklist, (box)->
expect(box.completed).to.be true
it 'resets checklist on complete grey complete dailies', ->
yesterday = moment().subtract(1,'days')
user.dailys[0].repeat[shared.dayMapping[yesterday.day()]] = 0
user.dailys[0].checklist = [
{
"text" : "1",
"id" : "checklist-one",
"completed" : true
},
{
"text" : "2",
"id" : "checklist-two",
"completed" : true
},
{
"text" : "3",
"id" : "checklist-three",
"completed" : true
}
]
user.dailys[0].completed = true
cron()
_.each user.dailys[0].checklist, (box)->
expect(box.completed).to.be false
it 'does not damage user for incomplete dailies', ->
expect(user).toHaveHP 50
@@ -265,7 +318,7 @@ describe 'User', ->
user.preferences.sleep = false
cron()
expect(user.stats.hp).to.be.lessThan 50
describe 'Death', ->
user = undefined
it 'revives correctly', ->
@@ -338,6 +391,36 @@ describe 'User', ->
expect(user.items.gear.equipped).to.eql { armor: 'armor_base_0', weapon: 'weapon_base_0', head: 'head_base_0', shield: 'shield_base_0' }
expect(user).toHaveGP 1
describe 'Gem purchases', ->
it 'does not purchase items without enough Gems', ->
user = newUser()
user.ops.purchase {params: {type: 'eggs', key: 'Cactus'}}
user.ops.purchase {params: {type: 'gear', key: 'headAccessory_special_foxEars'}}
user.ops.unlock {query: {path: 'items.gear.owned.headAccessory_special_bearEars,items.gear.owned.headAccessory_special_cactusEars,items.gear.owned.headAccessory_special_foxEars,items.gear.owned.headAccessory_special_lionEars,items.gear.owned.headAccessory_special_pandaEars,items.gear.owned.headAccessory_special_pigEars,items.gear.owned.headAccessory_special_tigerEars,items.gear.owned.headAccessory_special_wolfEars'}}
expect(user.items.eggs).to.eql {}
expect(user.items.gear.owned).to.eql { weapon_warrior_0: true }
it 'purchases an egg', ->
user = newUser()
user.balance = 1
user.ops.purchase {params: {type: 'eggs', key: 'Cactus'}}
expect(user.items.eggs).to.eql { Cactus: 1}
expect(user.balance).to.eql 0.25
it 'purchases fox ears', ->
user = newUser()
user.balance = 1
user.ops.purchase {params: {type: 'gear', key: 'headAccessory_special_foxEars'}}
expect(user.items.gear.owned).to.eql { weapon_warrior_0: true, headAccessory_special_foxEars: true }
expect(user.balance).to.eql 0.5
it 'unlocks all the animal ears at once', ->
user = newUser()
user.balance = 2
user.ops.unlock {query: {path: 'items.gear.owned.headAccessory_special_bearEars,items.gear.owned.headAccessory_special_cactusEars,items.gear.owned.headAccessory_special_foxEars,items.gear.owned.headAccessory_special_lionEars,items.gear.owned.headAccessory_special_pandaEars,items.gear.owned.headAccessory_special_pigEars,items.gear.owned.headAccessory_special_tigerEars,items.gear.owned.headAccessory_special_wolfEars'}}
expect(user.items.gear.owned).to.eql { weapon_warrior_0: true, headAccessory_special_bearEars: true, headAccessory_special_cactusEars: true, headAccessory_special_foxEars: true, headAccessory_special_lionEars: true, headAccessory_special_pandaEars: true, headAccessory_special_pigEars: true, headAccessory_special_tigerEars: true, headAccessory_special_wolfEars: true}
expect(user.balance).to.eql 0.75
describe 'spells', ->
_.each shared.content.spells, (spellClass)->
_.each spellClass, (spell)->
@@ -427,67 +510,67 @@ describe 'User', ->
_.each [1..5], (i) ->
user.ops.buy {params:'#{type}_#{klass}_#{i}'}
it 'does not get ultimateGear ' + klass, ->
expect(user.achievements.ultimateGear).to.not.be.ok
expect(user.achievements.ultimateGear).to.not.be.ok()
_.each shared.content.gearTypes, (type) ->
user.ops.buy {params:'#{type}_#{klass}_6'}
it 'gets ultimateGear ' + klass, ->
expect(user.achievements.ultimateGear).to.be.ok
xit 'gets ultimateGear ' + klass, ->
expect(user.achievements.ultimateGear).to.be.ok()
it 'does not get beastMaster if user has less than 90 drop pets', ->
user = newUser()
user.items.pets = {'Wolf-White': 1, 'Wolf-Desert': 1, 'Wolf-Red': 1, 'Wolf-Shade': 1, 'Wolf-Skeleton': 1, 'Wolf-Zombie': 1, 'Wolf-CottonCandyPink': 1, 'Wolf-CottonCandyBlue': 1, 'Wolf-Golden': 1, 'TigerCub-Base': 1, 'TigerCub-White': 1, 'TigerCub-Desert': 1, 'TigerCub-Red': 1, 'TigerCub-Shade': 1, 'TigerCub-Skeleton': 1, 'TigerCub-Zombie': 1, 'TigerCub-CottonCandyPink': 1, 'TigerCub-CottonCandyBlue': 1, 'TigerCub-Golden': 1, 'PandaCub-Base': 1, 'PandaCub-White': 1, 'PandaCub-Desert': 1, 'PandaCub-Red': 1, 'PandaCub-Shade': 1, 'PandaCub-Skeleton': 1, 'PandaCub-Zombie': 1, 'PandaCub-CottonCandyPink': 1, 'PandaCub-CottonCandyBlue': 1, 'PandaCub-Golden': 1, 'LionCub-Base': 1, 'LionCub-White': 1, 'LionCub-Desert': 1, 'LionCub-Red': 1, 'LionCub-Shade': 1, 'LionCub-Skeleton': 1, 'LionCub-Zombie': 1, 'LionCub-CottonCandyPink': 1, 'LionCub-CottonCandyBlue': 1, 'LionCub-Golden': 1, 'Fox-Base': 1, 'Fox-White': 1, 'Fox-Desert': 1, 'Fox-Red': 1, 'Fox-Shade': 1, 'Fox-Skeleton': 1, 'Fox-Zombie': 1, 'Fox-CottonCandyPink': 1, 'Fox-CottonCandyBlue': 1, 'Fox-Golden': 1, 'FlyingPig-Base': 1, 'FlyingPig-White': 1, 'FlyingPig-Desert': 1, 'FlyingPig-Red': 1, 'FlyingPig-Shade': 1, 'FlyingPig-Skeleton': 1, 'FlyingPig-Zombie': 1, 'FlyingPig-CottonCandyPink': 1, 'FlyingPig-CottonCandyBlue': 1, 'FlyingPig-Golden': 1, 'Dragon-Base': 1, 'Dragon-White': 1, 'Dragon-Desert': 1, 'Dragon-Red': 1, 'Dragon-Shade': 1, 'Dragon-Skeleton': 1, 'Dragon-Zombie': 1, 'Dragon-CottonCandyPink': 1, 'Dragon-CottonCandyBlue': 1, 'Dragon-Golden': 1, 'Cactus-Base': 1, 'Cactus-White': 1, 'Cactus-Desert': 1, 'Cactus-Red': 1, 'Cactus-Shade': 1, 'Cactus-Skeleton': 1, 'Cactus-Zombie': 1, 'Cactus-CottonCandyPink': 1, 'Cactus-CottonCandyBlue': 1, 'Cactus-Golden': 1, 'BearCub-Base': 1, 'BearCub-White': 1, 'BearCub-Desert': 1, 'BearCub-Red': 1, 'BearCub-Shade': 1, 'BearCub-Skeleton': 1, 'BearCub-Zombie': 1, 'BearCub-CottonCandyPink': 1, 'BearCub-CottonCandyBlue': 1, 'BearCub-Golden': 1 }
expect(shared.countPets(null,user.items.pets)).to.eql 89
expect(shared.countPets(_.size(user.items.pets), user.items.pets)).to.eql 89
expect(user.achievements.beastMaster).to.not.be.ok
expect(user.achievements.beastMaster).to.not.be.ok()
it 'does not get beastMaster with 89 drop pets + 1 gryphon', ->
user = newUser()
user.items.pets = {'Gryphon-Base': 1, 'Wolf-White': 1, 'Wolf-Desert': 1, 'Wolf-Red': 1, 'Wolf-Shade': 1, 'Wolf-Skeleton': 1, 'Wolf-Zombie': 1, 'Wolf-CottonCandyPink': 1, 'Wolf-CottonCandyBlue': 1, 'Wolf-Golden': 1, 'TigerCub-Base': 1, 'TigerCub-White': 1, 'TigerCub-Desert': 1, 'TigerCub-Red': 1, 'TigerCub-Shade': 1, 'TigerCub-Skeleton': 1, 'TigerCub-Zombie': 1, 'TigerCub-CottonCandyPink': 1, 'TigerCub-CottonCandyBlue': 1, 'TigerCub-Golden': 1, 'PandaCub-Base': 1, 'PandaCub-White': 1, 'PandaCub-Desert': 1, 'PandaCub-Red': 1, 'PandaCub-Shade': 1, 'PandaCub-Skeleton': 1, 'PandaCub-Zombie': 1, 'PandaCub-CottonCandyPink': 1, 'PandaCub-CottonCandyBlue': 1, 'PandaCub-Golden': 1, 'LionCub-Base': 1, 'LionCub-White': 1, 'LionCub-Desert': 1, 'LionCub-Red': 1, 'LionCub-Shade': 1, 'LionCub-Skeleton': 1, 'LionCub-Zombie': 1, 'LionCub-CottonCandyPink': 1, 'LionCub-CottonCandyBlue': 1, 'LionCub-Golden': 1, 'Fox-Base': 1, 'Fox-White': 1, 'Fox-Desert': 1, 'Fox-Red': 1, 'Fox-Shade': 1, 'Fox-Skeleton': 1, 'Fox-Zombie': 1, 'Fox-CottonCandyPink': 1, 'Fox-CottonCandyBlue': 1, 'Fox-Golden': 1, 'FlyingPig-Base': 1, 'FlyingPig-White': 1, 'FlyingPig-Desert': 1, 'FlyingPig-Red': 1, 'FlyingPig-Shade': 1, 'FlyingPig-Skeleton': 1, 'FlyingPig-Zombie': 1, 'FlyingPig-CottonCandyPink': 1, 'FlyingPig-CottonCandyBlue': 1, 'FlyingPig-Golden': 1, 'Dragon-Base': 1, 'Dragon-White': 1, 'Dragon-Desert': 1, 'Dragon-Red': 1, 'Dragon-Shade': 1, 'Dragon-Skeleton': 1, 'Dragon-Zombie': 1, 'Dragon-CottonCandyPink': 1, 'Dragon-CottonCandyBlue': 1, 'Dragon-Golden': 1, 'Cactus-Base': 1, 'Cactus-White': 1, 'Cactus-Desert': 1, 'Cactus-Red': 1, 'Cactus-Shade': 1, 'Cactus-Skeleton': 1, 'Cactus-Zombie': 1, 'Cactus-CottonCandyPink': 1, 'Cactus-CottonCandyBlue': 1, 'Cactus-Golden': 1, 'BearCub-Base': 1, 'BearCub-White': 1, 'BearCub-Desert': 1, 'BearCub-Red': 1, 'BearCub-Shade': 1, 'BearCub-Skeleton': 1, 'BearCub-Zombie': 1, 'BearCub-CottonCandyPink': 1, 'BearCub-CottonCandyBlue': 1, 'BearCub-Golden': 1 }
expect(shared.countPets(null,user.items.pets)).to.eql 89
expect(shared.countPets(_.size(user.items.pets), user.items.pets)).to.eql 89
expect(user.achievements.beastMaster).to.not.be.ok
expect(user.achievements.beastMaster).to.not.be.ok()
it 'does not get beastMaster with 89 pets + 1 hydra', ->
user = newUser()
user.items.pets = {'Dragon-Hydra': 1, 'Wolf-White': 1, 'Wolf-Desert': 1, 'Wolf-Red': 1, 'Wolf-Shade': 1, 'Wolf-Skeleton': 1, 'Wolf-Zombie': 1, 'Wolf-CottonCandyPink': 1, 'Wolf-CottonCandyBlue': 1, 'Wolf-Golden': 1, 'TigerCub-Base': 1, 'TigerCub-White': 1, 'TigerCub-Desert': 1, 'TigerCub-Red': 1, 'TigerCub-Shade': 1, 'TigerCub-Skeleton': 1, 'TigerCub-Zombie': 1, 'TigerCub-CottonCandyPink': 1, 'TigerCub-CottonCandyBlue': 1, 'TigerCub-Golden': 1, 'PandaCub-Base': 1, 'PandaCub-White': 1, 'PandaCub-Desert': 1, 'PandaCub-Red': 1, 'PandaCub-Shade': 1, 'PandaCub-Skeleton': 1, 'PandaCub-Zombie': 1, 'PandaCub-CottonCandyPink': 1, 'PandaCub-CottonCandyBlue': 1, 'PandaCub-Golden': 1, 'LionCub-Base': 1, 'LionCub-White': 1, 'LionCub-Desert': 1, 'LionCub-Red': 1, 'LionCub-Shade': 1, 'LionCub-Skeleton': 1, 'LionCub-Zombie': 1, 'LionCub-CottonCandyPink': 1, 'LionCub-CottonCandyBlue': 1, 'LionCub-Golden': 1, 'Fox-Base': 1, 'Fox-White': 1, 'Fox-Desert': 1, 'Fox-Red': 1, 'Fox-Shade': 1, 'Fox-Skeleton': 1, 'Fox-Zombie': 1, 'Fox-CottonCandyPink': 1, 'Fox-CottonCandyBlue': 1, 'Fox-Golden': 1, 'FlyingPig-Base': 1, 'FlyingPig-White': 1, 'FlyingPig-Desert': 1, 'FlyingPig-Red': 1, 'FlyingPig-Shade': 1, 'FlyingPig-Skeleton': 1, 'FlyingPig-Zombie': 1, 'FlyingPig-CottonCandyPink': 1, 'FlyingPig-CottonCandyBlue': 1, 'FlyingPig-Golden': 1, 'Dragon-Base': 1, 'Dragon-White': 1, 'Dragon-Desert': 1, 'Dragon-Red': 1, 'Dragon-Shade': 1, 'Dragon-Skeleton': 1, 'Dragon-Zombie': 1, 'Dragon-CottonCandyPink': 1, 'Dragon-CottonCandyBlue': 1, 'Dragon-Golden': 1, 'Cactus-Base': 1, 'Cactus-White': 1, 'Cactus-Desert': 1, 'Cactus-Red': 1, 'Cactus-Shade': 1, 'Cactus-Skeleton': 1, 'Cactus-Zombie': 1, 'Cactus-CottonCandyPink': 1, 'Cactus-CottonCandyBlue': 1, 'Cactus-Golden': 1, 'BearCub-Base': 1, 'BearCub-White': 1, 'BearCub-Desert': 1, 'BearCub-Red': 1, 'BearCub-Shade': 1, 'BearCub-Skeleton': 1, 'BearCub-Zombie': 1, 'BearCub-CottonCandyPink': 1, 'BearCub-CottonCandyBlue': 1, 'BearCub-Golden': 1 }
expect(shared.countPets(null,user.items.pets)).to.eql 89
expect(shared.countPets(_.size(user.items.pets), user.items.pets)).to.eql 89
expect(user.achievements.beastMaster).to.not.be.ok
expect(user.achievements.beastMaster).to.not.be.ok()
it 'does get beastMaster', ->
xit 'does get beastMaster', ->
user = newUser()
user.items.pets = {'Wolf-Base': 1, 'Wolf-White': 1, 'Wolf-Desert': 1, 'Wolf-Red': 1, 'Wolf-Shade': 1, 'Wolf-Skeleton': 1, 'Wolf-Zombie': 1, 'Wolf-CottonCandyPink': 1, 'Wolf-CottonCandyBlue': 1, 'Wolf-Golden': 1, 'TigerCub-Base': 1, 'TigerCub-White': 1, 'TigerCub-Desert': 1, 'TigerCub-Red': 1, 'TigerCub-Shade': 1, 'TigerCub-Skeleton': 1, 'TigerCub-Zombie': 1, 'TigerCub-CottonCandyPink': 1, 'TigerCub-CottonCandyBlue': 1, 'TigerCub-Golden': 1, 'PandaCub-Base': 1, 'PandaCub-White': 1, 'PandaCub-Desert': 1, 'PandaCub-Red': 1, 'PandaCub-Shade': 1, 'PandaCub-Skeleton': 1, 'PandaCub-Zombie': 1, 'PandaCub-CottonCandyPink': 1, 'PandaCub-CottonCandyBlue': 1, 'PandaCub-Golden': 1, 'LionCub-Base': 1, 'LionCub-White': 1, 'LionCub-Desert': 1, 'LionCub-Red': 1, 'LionCub-Shade': 1, 'LionCub-Skeleton': 1, 'LionCub-Zombie': 1, 'LionCub-CottonCandyPink': 1, 'LionCub-CottonCandyBlue': 1, 'LionCub-Golden': 1, 'Fox-Base': 1, 'Fox-White': 1, 'Fox-Desert': 1, 'Fox-Red': 1, 'Fox-Shade': 1, 'Fox-Skeleton': 1, 'Fox-Zombie': 1, 'Fox-CottonCandyPink': 1, 'Fox-CottonCandyBlue': 1, 'Fox-Golden': 1, 'FlyingPig-Base': 1, 'FlyingPig-White': 1, 'FlyingPig-Desert': 1, 'FlyingPig-Red': 1, 'FlyingPig-Shade': 1, 'FlyingPig-Skeleton': 1, 'FlyingPig-Zombie': 1, 'FlyingPig-CottonCandyPink': 1, 'FlyingPig-CottonCandyBlue': 1, 'FlyingPig-Golden': 1, 'Dragon-Base': 1, 'Dragon-White': 1, 'Dragon-Desert': 1, 'Dragon-Red': 1, 'Dragon-Shade': 1, 'Dragon-Skeleton': 1, 'Dragon-Zombie': 1, 'Dragon-CottonCandyPink': 1, 'Dragon-CottonCandyBlue': 1, 'Dragon-Golden': 1, 'Cactus-Base': 1, 'Cactus-White': 1, 'Cactus-Desert': 1, 'Cactus-Red': 1, 'Cactus-Shade': 1, 'Cactus-Skeleton': 1, 'Cactus-Zombie': 1, 'Cactus-CottonCandyPink': 1, 'Cactus-CottonCandyBlue': 1, 'Cactus-Golden': 1, 'BearCub-Base': 1, 'BearCub-White': 1, 'BearCub-Desert': 1, 'BearCub-Red': 1, 'BearCub-Shade': 1, 'BearCub-Skeleton': 1, 'BearCub-Zombie': 1, 'BearCub-CottonCandyPink': 1, 'BearCub-CottonCandyBlue': 1, 'BearCub-Golden': 1 }
expect(shared.countPets(null,user.items.pets)).to.eql 90
expect(shared.countPets(_.size(user.items.pets), user.items.pets)).to.eql 90
expect(user.achievements.beastMaster).to.be.ok
expect(user.achievements.beastMaster).to.be.ok()
it 'does not get mountMaster if user has less than 90 drop mounts', ->
user = newUser()
user.items.mounts = {'Wolf-White': true, 'Wolf-Desert': true, 'Wolf-Red': true, 'Wolf-Shade': true, 'Wolf-Skeleton': true, 'Wolf-Zombie': true, 'Wolf-CottonCandyPink': true, 'Wolf-CottonCandyBlue': true, 'Wolf-Golden': true, 'TigerCub-Base': true, 'TigerCub-White': true, 'TigerCub-Desert': true, 'TigerCub-Red': true, 'TigerCub-Shade': true, 'TigerCub-Skeleton': true, 'TigerCub-Zombie': true, 'TigerCub-CottonCandyPink': true, 'TigerCub-CottonCandyBlue': true, 'TigerCub-Golden': true, 'PandaCub-Base': true, 'PandaCub-White': true, 'PandaCub-Desert': true, 'PandaCub-Red': true, 'PandaCub-Shade': true, 'PandaCub-Skeleton': true, 'PandaCub-Zombie': true, 'PandaCub-CottonCandyPink': true, 'PandaCub-CottonCandyBlue': true, 'PandaCub-Golden': true, 'LionCub-Base': true, 'LionCub-White': true, 'LionCub-Desert': true, 'LionCub-Red': true, 'LionCub-Shade': true, 'LionCub-Skeleton': true, 'LionCub-Zombie': true, 'LionCub-CottonCandyPink': true, 'LionCub-CottonCandyBlue': true, 'LionCub-Golden': true, 'Fox-Base': true, 'Fox-White': true, 'Fox-Desert': true, 'Fox-Red': true, 'Fox-Shade': true, 'Fox-Skeleton': true, 'Fox-Zombie': true, 'Fox-CottonCandyPink': true, 'Fox-CottonCandyBlue': true, 'Fox-Golden': true, 'FlyingPig-Base': true, 'FlyingPig-White': true, 'FlyingPig-Desert': true, 'FlyingPig-Red': true, 'FlyingPig-Shade': true, 'FlyingPig-Skeleton': true, 'FlyingPig-Zombie': true, 'FlyingPig-CottonCandyPink': true, 'FlyingPig-CottonCandyBlue': true, 'FlyingPig-Golden': true, 'Dragon-Base': true, 'Dragon-White': true, 'Dragon-Desert': true, 'Dragon-Red': true, 'Dragon-Shade': true, 'Dragon-Skeleton': true, 'Dragon-Zombie': true, 'Dragon-CottonCandyPink': true, 'Dragon-CottonCandyBlue': true, 'Dragon-Golden': true, 'Cactus-Base': true, 'Cactus-White': true, 'Cactus-Desert': true, 'Cactus-Red': true, 'Cactus-Shade': true, 'Cactus-Skeleton': true, 'Cactus-Zombie': true, 'Cactus-CottonCandyPink': true, 'Cactus-CottonCandyBlue': true, 'Cactus-Golden': true, 'BearCub-Base': true, 'BearCub-White': true, 'BearCub-Desert': true, 'BearCub-Red': true, 'BearCub-Shade': true, 'BearCub-Skeleton': true, 'BearCub-Zombie': true, 'BearCub-CottonCandyPink': true, 'BearCub-CottonCandyBlue': true, 'BearCub-Golden': true }
expect(shared.countMounts(null,user.items.mounts)).to.eql 89
expect(shared.countMounts(_.size(user.items.mounts), user.items.mounts)).to.eql 89
expect(user.achievements.mountMaster).to.not.be.ok
expect(user.achievements.mountMaster).to.not.be.ok()
it 'does not get mountMaster with 89 drop pets + 1 gryphon', ->
user = newUser()
user.items.mounts = {'Gryphon-Base': true, 'Wolf-White': true, 'Wolf-Desert': true, 'Wolf-Red': true, 'Wolf-Shade': true, 'Wolf-Skeleton': true, 'Wolf-Zombie': true, 'Wolf-CottonCandyPink': true, 'Wolf-CottonCandyBlue': true, 'Wolf-Golden': true, 'TigerCub-Base': true, 'TigerCub-White': true, 'TigerCub-Desert': true, 'TigerCub-Red': true, 'TigerCub-Shade': true, 'TigerCub-Skeleton': true, 'TigerCub-Zombie': true, 'TigerCub-CottonCandyPink': true, 'TigerCub-CottonCandyBlue': true, 'TigerCub-Golden': true, 'PandaCub-Base': true, 'PandaCub-White': true, 'PandaCub-Desert': true, 'PandaCub-Red': true, 'PandaCub-Shade': true, 'PandaCub-Skeleton': true, 'PandaCub-Zombie': true, 'PandaCub-CottonCandyPink': true, 'PandaCub-CottonCandyBlue': true, 'PandaCub-Golden': true, 'LionCub-Base': true, 'LionCub-White': true, 'LionCub-Desert': true, 'LionCub-Red': true, 'LionCub-Shade': true, 'LionCub-Skeleton': true, 'LionCub-Zombie': true, 'LionCub-CottonCandyPink': true, 'LionCub-CottonCandyBlue': true, 'LionCub-Golden': true, 'Fox-Base': true, 'Fox-White': true, 'Fox-Desert': true, 'Fox-Red': true, 'Fox-Shade': true, 'Fox-Skeleton': true, 'Fox-Zombie': true, 'Fox-CottonCandyPink': true, 'Fox-CottonCandyBlue': true, 'Fox-Golden': true, 'FlyingPig-Base': true, 'FlyingPig-White': true, 'FlyingPig-Desert': true, 'FlyingPig-Red': true, 'FlyingPig-Shade': true, 'FlyingPig-Skeleton': true, 'FlyingPig-Zombie': true, 'FlyingPig-CottonCandyPink': true, 'FlyingPig-CottonCandyBlue': true, 'FlyingPig-Golden': true, 'Dragon-Base': true, 'Dragon-White': true, 'Dragon-Desert': true, 'Dragon-Red': true, 'Dragon-Shade': true, 'Dragon-Skeleton': true, 'Dragon-Zombie': true, 'Dragon-CottonCandyPink': true, 'Dragon-CottonCandyBlue': true, 'Dragon-Golden': true, 'Cactus-Base': true, 'Cactus-White': true, 'Cactus-Desert': true, 'Cactus-Red': true, 'Cactus-Shade': true, 'Cactus-Skeleton': true, 'Cactus-Zombie': true, 'Cactus-CottonCandyPink': true, 'Cactus-CottonCandyBlue': true, 'Cactus-Golden': true, 'BearCub-Base': true, 'BearCub-White': true, 'BearCub-Desert': true, 'BearCub-Red': true, 'BearCub-Shade': true, 'BearCub-Skeleton': true, 'BearCub-Zombie': true, 'BearCub-CottonCandyPink': true, 'BearCub-CottonCandyBlue': true, 'BearCub-Golden': true }
expect(shared.countMounts(null,user.items.mounts)).to.eql 89
expect(shared.countMounts(_.size(user.items.mounts), user.items.mounts)).to.eql 89
expect(user.achievements.mountMaster).to.not.be.ok
expect(user.achievements.mountMaster).to.not.be.ok()
it 'does not get mountMaster with 89 drop pets + 1 mantis shrimp', ->
user = newUser()
user.items.mounts = {'MantisShrimp-Base': true, 'Wolf-White': true, 'Wolf-Desert': true, 'Wolf-Red': true, 'Wolf-Shade': true, 'Wolf-Skeleton': true, 'Wolf-Zombie': true, 'Wolf-CottonCandyPink': true, 'Wolf-CottonCandyBlue': true, 'Wolf-Golden': true, 'TigerCub-Base': true, 'TigerCub-White': true, 'TigerCub-Desert': true, 'TigerCub-Red': true, 'TigerCub-Shade': true, 'TigerCub-Skeleton': true, 'TigerCub-Zombie': true, 'TigerCub-CottonCandyPink': true, 'TigerCub-CottonCandyBlue': true, 'TigerCub-Golden': true, 'PandaCub-Base': true, 'PandaCub-White': true, 'PandaCub-Desert': true, 'PandaCub-Red': true, 'PandaCub-Shade': true, 'PandaCub-Skeleton': true, 'PandaCub-Zombie': true, 'PandaCub-CottonCandyPink': true, 'PandaCub-CottonCandyBlue': true, 'PandaCub-Golden': true, 'LionCub-Base': true, 'LionCub-White': true, 'LionCub-Desert': true, 'LionCub-Red': true, 'LionCub-Shade': true, 'LionCub-Skeleton': true, 'LionCub-Zombie': true, 'LionCub-CottonCandyPink': true, 'LionCub-CottonCandyBlue': true, 'LionCub-Golden': true, 'Fox-Base': true, 'Fox-White': true, 'Fox-Desert': true, 'Fox-Red': true, 'Fox-Shade': true, 'Fox-Skeleton': true, 'Fox-Zombie': true, 'Fox-CottonCandyPink': true, 'Fox-CottonCandyBlue': true, 'Fox-Golden': true, 'FlyingPig-Base': true, 'FlyingPig-White': true, 'FlyingPig-Desert': true, 'FlyingPig-Red': true, 'FlyingPig-Shade': true, 'FlyingPig-Skeleton': true, 'FlyingPig-Zombie': true, 'FlyingPig-CottonCandyPink': true, 'FlyingPig-CottonCandyBlue': true, 'FlyingPig-Golden': true, 'Dragon-Base': true, 'Dragon-White': true, 'Dragon-Desert': true, 'Dragon-Red': true, 'Dragon-Shade': true, 'Dragon-Skeleton': true, 'Dragon-Zombie': true, 'Dragon-CottonCandyPink': true, 'Dragon-CottonCandyBlue': true, 'Dragon-Golden': true, 'Cactus-Base': true, 'Cactus-White': true, 'Cactus-Desert': true, 'Cactus-Red': true, 'Cactus-Shade': true, 'Cactus-Skeleton': true, 'Cactus-Zombie': true, 'Cactus-CottonCandyPink': true, 'Cactus-CottonCandyBlue': true, 'Cactus-Golden': true, 'BearCub-Base': true, 'BearCub-White': true, 'BearCub-Desert': true, 'BearCub-Red': true, 'BearCub-Shade': true, 'BearCub-Skeleton': true, 'BearCub-Zombie': true, 'BearCub-CottonCandyPink': true, 'BearCub-CottonCandyBlue': true, 'BearCub-Golden': true }
expect(shared.countMounts(null,user.items.mounts)).to.eql 89
expect(shared.countMounts(_.size(user.items.mounts), user.items.mounts)).to.eql 89
expect(user.achievements.mountMaster).to.not.be.ok
expect(user.achievements.mountMaster).to.not.be.ok()
it 'does get mountMaster', ->
xit 'does get mountMaster', ->
user = newUser()
user.items.mounts = {'Wolf-Base': true, 'Wolf-White': true, 'Wolf-Desert': true, 'Wolf-Red': true, 'Wolf-Shade': true, 'Wolf-Skeleton': true, 'Wolf-Zombie': true, 'Wolf-CottonCandyPink': true, 'Wolf-CottonCandyBlue': true, 'Wolf-Golden': true, 'TigerCub-Base': true, 'TigerCub-White': true, 'TigerCub-Desert': true, 'TigerCub-Red': true, 'TigerCub-Shade': true, 'TigerCub-Skeleton': true, 'TigerCub-Zombie': true, 'TigerCub-CottonCandyPink': true, 'TigerCub-CottonCandyBlue': true, 'TigerCub-Golden': true, 'PandaCub-Base': true, 'PandaCub-White': true, 'PandaCub-Desert': true, 'PandaCub-Red': true, 'PandaCub-Shade': true, 'PandaCub-Skeleton': true, 'PandaCub-Zombie': true, 'PandaCub-CottonCandyPink': true, 'PandaCub-CottonCandyBlue': true, 'PandaCub-Golden': true, 'LionCub-Base': true, 'LionCub-White': true, 'LionCub-Desert': true, 'LionCub-Red': true, 'LionCub-Shade': true, 'LionCub-Skeleton': true, 'LionCub-Zombie': true, 'LionCub-CottonCandyPink': true, 'LionCub-CottonCandyBlue': true, 'LionCub-Golden': true, 'Fox-Base': true, 'Fox-White': true, 'Fox-Desert': true, 'Fox-Red': true, 'Fox-Shade': true, 'Fox-Skeleton': true, 'Fox-Zombie': true, 'Fox-CottonCandyPink': true, 'Fox-CottonCandyBlue': true, 'Fox-Golden': true, 'FlyingPig-Base': true, 'FlyingPig-White': true, 'FlyingPig-Desert': true, 'FlyingPig-Red': true, 'FlyingPig-Shade': true, 'FlyingPig-Skeleton': true, 'FlyingPig-Zombie': true, 'FlyingPig-CottonCandyPink': true, 'FlyingPig-CottonCandyBlue': true, 'FlyingPig-Golden': true, 'Dragon-Base': true, 'Dragon-White': true, 'Dragon-Desert': true, 'Dragon-Red': true, 'Dragon-Shade': true, 'Dragon-Skeleton': true, 'Dragon-Zombie': true, 'Dragon-CottonCandyPink': true, 'Dragon-CottonCandyBlue': true, 'Dragon-Golden': true, 'Cactus-Base': true, 'Cactus-White': true, 'Cactus-Desert': true, 'Cactus-Red': true, 'Cactus-Shade': true, 'Cactus-Skeleton': true, 'Cactus-Zombie': true, 'Cactus-CottonCandyPink': true, 'Cactus-CottonCandyBlue': true, 'Cactus-Golden': true, 'BearCub-Base': true, 'BearCub-White': true, 'BearCub-Desert': true, 'BearCub-Red': true, 'BearCub-Shade': true, 'BearCub-Skeleton': true, 'BearCub-Zombie': true, 'BearCub-CottonCandyPink': true, 'BearCub-CottonCandyBlue': true, 'BearCub-Golden': true }
expect(shared.countMounts(null,user.items.mounts)).to.eql 90
expect(shared.countMounts(_.size(user.items.mounts), user.items.mounts)).to.eql 90
expect(user.achievements.mountMaster).to.be.ok
expect(user.achievements.mountMaster).to.be.ok()
describe 'Simple Scoring', ->
beforeEach ->
@@ -694,7 +777,7 @@ describe 'Cron', ->
describe 'dailies', ->
describe.skip 'new day', ->
describe 'new day', ->
###
This section runs through a "cron matrix" of all permutations (that I can easily account for). It sets
+1 -1
View File
@@ -41,4 +41,4 @@ module.exports.addCustomMatchers = ->
actual == mp,
-> "expected user to have #{mp} max mp, but got #{actual}",
-> "expected user to not have #{mp} max mp"
)
)
+1
View File
@@ -6,3 +6,4 @@
--debug
--compilers coffee:coffee-script
--globals io
--require test/api/api-helper
+1 -1
View File
@@ -82,7 +82,7 @@ Suite =
runApiSpecs: ->
announce "Running API Specs (Mocha)"
sh.exec("NODE_ENV=testing ./node_modules/mocha/bin/mocha test/api.mocha.coffee").code
sh.exec("NODE_ENV=testing ./node_modules/mocha/bin/mocha test/api").code
runCommonSpecs: ->
announce "Running Common Specs (Mocha)"
+138
View File
@@ -68,6 +68,76 @@ describe('Groups Controller', function() {
});
});
describe("Chat Controller", function() {
var scope, ctrl, user, $rootScope, $controller;
beforeEach(function() {
module(function($provide) {
$provide.value('User', {});
});
inject(function(_$rootScope_, _$controller_){
user = specHelper.newUser();
user._id = "unique-user-id";
$rootScope = _$rootScope_;
scope = _$rootScope_.$new();
$controller = _$controller_;
// Load RootCtrl to ensure shared behaviors are loaded
$controller('RootCtrl', {$scope: scope, User: {user: user}});
ctrl = $controller('ChatCtrl', {$scope: scope});
});
});
describe('copyToDo', function() {
it('when copying a user message it opens modal with information from message', function() {
scope.group = {
name: "Princess Bride"
};
var modalSpy = sinon.spy($rootScope, "openModal");
var message = {
uuid: 'the-dread-pirate-roberts',
user: 'Wesley',
text: 'As you wish'
};
scope.copyToDo(message);
modalSpy.should.have.been.calledOnce;
modalSpy.should.have.been.calledWith('copyChatToDo', sinon.match(function(callArgToMatch){
return callArgToMatch.controller == 'CopyMessageModalCtrl'
&& callArgToMatch.scope.text == message.text
}));
});
it('when copying a system message it opens modal with information from message', function() {
scope.group = {
name: "Princess Bride"
};
var modalSpy = sinon.spy($rootScope, "openModal");
var message = {
uuid: 'system',
text: 'Wesley attacked the ROUS in the Fire Swamp'
};
scope.copyToDo(message);
modalSpy.should.have.been.calledOnce;
modalSpy.should.have.been.calledWith('copyChatToDo', sinon.match(function(callArgToMatch){
return callArgToMatch.controller == 'CopyMessageModalCtrl'
&& callArgToMatch.scope.text == message.text
}));
});
});
});
describe("Autocomplete controller", function() {
var scope, ctrl, user, $rootScope, $controller;
@@ -149,6 +219,20 @@ describe("Autocomplete controller", function() {
});
});
describe("performCompletion", function() {
it('triggers autoComplete', function() {
scope.autoComplete = sinon.spy();
var msg = {user: "boo"}; // scope.autoComplete only cares about user
scope.query = {text: "b"};
scope.performCompletion(msg);
expect(scope.query).to.be.eq(null);
expect(scope.autoComplete.callCount).to.be.eq(1);
expect(scope.autoComplete).to.have.been.calledWith(msg);
});
});
describe("addNewUser", function() {
it('a new message from a new user will modify the usernames', function() {
expect(scope.response).to.be.empty;
@@ -172,3 +256,57 @@ describe("Autocomplete controller", function() {
});
});
});
describe("CopyMessageModal controller", function() {
var scope, ctrl, user, Notification, $rootScope, $controller;
beforeEach(function() {
module(function($provide) {
$provide.value('User', {});
});
inject(function($rootScope, _$controller_, _Notification_){
user = specHelper.newUser();
user._id = "unique-user-id";
user.ops = {
addTask: sinon.spy()
};
scope = $rootScope.$new();
scope.$close = sinon.spy();
$controller = _$controller_;
// Load RootCtrl to ensure shared behaviors are loaded
$controller('RootCtrl', {$scope: scope, User: {user: user}});
ctrl = $controller('CopyMessageModalCtrl', {$scope: scope, User: {user: user}});
Notification = _Notification_;
Notification.text = sinon.spy();
});
});
describe("saveTodo", function() {
it('saves todo', function() {
scope.text = "A Tavern msg";
scope.notes = "Some notes";
var payload = {
body: {
text: scope.text,
type: 'todo',
notes: scope.notes
}
};
scope.saveTodo();
user.ops.addTask.should.have.been.calledOnce;
user.ops.addTask.should.have.been.calledWith(payload);
Notification.text.should.have.been.calledOnce;
Notification.text.should.have.been.calledWith(window.env.t('messageAddedAsToDo'));
scope.$close.should.have.been.calledOnce;
});
});
});