diff --git a/common/locales/en/challenge.json b/common/locales/en/challenge.json index c0b5543caf..d35b168898 100644 --- a/common/locales/en/challenge.json +++ b/common/locales/en/challenge.json @@ -33,7 +33,8 @@ "challengeTagPop": "Challenges appear on tag-lists & task-tooltips. So while you'll want a descriptive title above, you'll also need a 'short name'. Eg, 'Lose 10 pounds in 3 months' might become '-10lb' (Click for more info).", "challengeDescr": "Description", "prize": "Prize", - "prizePop": "If someone can 'win' your challenge, you can optionally award that winner a Gem prize. Max = #gems you own (+ guild.gems, if you created this challenge's guild). Note: This prize can't be changed later and will not be refunded if challenge is cancelled.", + "prizePop": "If someone can 'win' your challenge, you can optionally award that winner a Gem prize. Max = #gems you own (+ guild.gems, if you created this challenge's guild). Note: This prize can't be changed later.", + "prizePopTavern": "If someone can 'win' your challenge, you can optionally award that winner a Gem prize. Max = #gems you own (+ guild.gems, if you created this challenge's guild). Note: This prize can't be changed later and Tavern challenges will not be refunded if the challenge is cancelled.", "publicChallenges": "Minimum 1 Gem for public challenges (helps prevent spam, it really does).", "officialChallenge": "Official HabitRPG Challenge", "by": "by", @@ -43,6 +44,7 @@ "selectGroup": "Please select group", "challengeCreated": "Challenge created", "sureDelCha": "Delete challenge, are you sure?", + "sureDelChaTavern": "Delete challenge, are you sure? Your gems will not be refunded.", "removeTasks": "Remove Tasks", "keepTasks": "Keep Tasks", "closeCha": "Close challenge and...", diff --git a/test/api.mocha.coffee b/test/api.mocha.coffee deleted file mode 100644 index 47e7c23aa6..0000000000 --- a/test/api.mocha.coffee +++ /dev/null @@ -1,862 +0,0 @@ -#jslint node: true - -#global describe, before, beforeEach, it -"use strict" -_ = require("lodash") -expect = require("expect.js") -async = require("async") -diff = require("deep-diff") -superagentDefaults = require("superagent-defaults") -request = superagentDefaults() -path = require("path") -moment = require("moment") -conf = require("nconf") -conf.argv().env().file(file: path.join(__dirname, "../config.json")).defaults() -conf.set "PORT", "1337" - -# Override normal ENV values with nconf ENV values (ENV values are used the same way without nconf) -process.env.BASE_URL = conf.get("BASE_URL") -process.env.FACEBOOK_KEY = conf.get("FACEBOOK_KEY") -process.env.FACEBOOK_SECRET = conf.get("FACEBOOK_SECRET") -process.env.NODE_DB_URI = "mongodb://localhost/habitrpg_test" -User = require("../website/src/models/user").model -Group = require("../website/src/models/group").model -Challenge = require("../website/src/models/challenge").model -app = require("../website/src/server") -shared = require("../common") -payments = require("../website/src/controllers/payments") - -# ###### Helpers & Variables ###### -model = undefined -uuid = undefined -taskPath = undefined -baseURL = "http://localhost:" + conf.get("PORT") + "/api/v2" -expectCode = (res, code) -> - expect(res.body.err).to.be `undefined` if code is 200 - expect(res.statusCode).to.be code - -describe "API", -> - user = undefined - _id = undefined - apiToken = undefined - username = undefined - password = undefined - - 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() - user = _user - request - .set("Accept", "application/json") - .set("X-API-User", _id) - .set("X-API-Key", apiToken) - cb null, res.body - - before (done) -> - require "../website/src/server" # start the server - # then wait for it to do it's thing. TODO make a cb-compatible export of server - setTimeout done, 2000 - - 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.be 200 - expect(res.body.status).to.be "up" - done() - - it "/api/v2/user", (done) -> - request.get(baseURL + "/user").set("Accept", "application/json").end (res) -> - expect(res.statusCode).to.be 401 - expect(res.body.err).to.be "You must include a token and uid (user id) in your request" - done() - - describe "With token and user id", -> - before (done) -> - registerNewUser done, true - - beforeEach (done) -> - User.findById _id, (err, _user) -> - user = _user - shared.wrap user - done() - - describe "Todos", -> - 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.be 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.be 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.be 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.be "Sample Todo" - expect(todo.id).to.be.ok - expect(todo.value).to.be 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.be 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.be 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.be "Changed Title" - expect(todo.attribute).to.be "int" - expect(todo.priority).to.be 1.5 - expect(todo.value).to.be 5 - expect(todo.notes).to.be "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.be "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.be "Task not found." - done() - - ###* - GROUPS - ### - describe "Groups", -> - group = undefined - before (done) -> - request.post(baseURL + "/groups").send( - name: "TestGroup" - type: "party" - ).end (res) -> - expectCode res, 200 - group = res.body - expect(group.members.length).to.be 1 - expect(group.leader).to.be user._id - done() - - describe "Party", -> - 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.be group._id - expect(party.leader).to.be user._id - expect(party.name).to.be group.name - expect(party.quest).to.be.eql { progress: {} } - expect(party.memberCount).to.be 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.be.eql msg - expect(chat.timestamp).to.be.ok - expect(chat.likes).to.be.empty - expect(chat.flags).to.be.empty - expect(chat.flagCount).to.be 0 - expect(chat.uuid).to.be.ok - expect(chat.contributor).to.be.empty - expect(chat.backer).to.be.empty - expect(chat.uuid).to.be user._id - expect(chat.user).to.be 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.be.eql '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.be "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.be "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.be chat.id - expect(message.timestamp).to.be chat.timestamp - expect(message.likes).to.be.eql chat.likes - expect(message.flags).to.be.eql chat.flags - expect(message.flagCount).to.be chat.flagCount - expect(message.uuid).to.be chat.uuid - expect(message.contributor).to.be.eql chat.contributor - expect(message.backer).to.be.eql chat.backer - expect(message.user).to.be 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.be "Message not found!" - done() - - describe "Challenges", -> - challenge = undefined - updateTodo = undefined - 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" - notes: "Challenge Notes" - ] - rewards: [] - habits: [] - official: true - ).end (res) -> - expectCode res, 200 - async.parallel [ - (cb) -> - User.findById _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.be "Challenge Daily" - updateTodo = _user.todos[_user.todos.length - 1] - expect(updateTodo.text).to.be "Challenge Todo" - expect(challenge.official).to.be false - 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 _id, (err, _user) -> - expectCode res, 200 - expect(_user.dailys[_user.dailys.length - 1].text).to.be "Updated Daily" - expect(res.body.todos[0].notes).to.be "Challenge Updated Todo Notes" - expect(_user.todos[_user.todos.length - 1].notes).to.be "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/" + _id).end (res) -> - expect(res.body.todos[res.body.todos.length - 1].notes).to.be "User overriden notes" - done() - - it "Complete To-Dos", (done) -> - u = user - numTasks = (_.size(u.todos)) - request.post(baseURL + "/user/tasks/" + u.todos[0].id + "/up").end (res) -> - request.post(baseURL + "/user/tasks/" + u.todos[1].id + "/up").end (res) -> - request.post(baseURL + "/user/tasks/").send(type: "todo").end (res) -> - request.post(baseURL + "/user/tasks/clear-completed").end (res) -> - # 2 tasks set to be completed, so tasks should equal numTasks - 2 - expect(_.size(res.body)).to.be numTasks - 2 - 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.be "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.be.ok() - expect(user.dailys[len].challenge.broken).to.not.be.ok() - request.post(baseURL + "/user/tasks/" + daily.id + "/up").end (res) -> - setTimeout (-> - User.findById user._id, (err, user) -> - expect(user.dailys[len].challenge.broken).to.be "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 _id, - $set: - "contributor.admin": true - , (err, _user) -> - expect(err).to.not.be.ok() - async.parallel [ - (cb) -> - request.post(baseURL + "/challenges").send( - group: group._id - dailys: [] - todos: [] - rewards: [] - habits: [] - official: false - ).end (res) -> - expect(res.body.official).to.be false - cb() - (cb) -> - request.post(baseURL + "/challenges").send( - group: group._id - dailys: [] - todos: [] - rewards: [] - habits: [] - official: true - ).end (res) -> - expect(res.body.official).to.be true - cb() - ], done - - it "User creates a challenge with prize, deletes it, gets refund", (done) -> - User.findByIdAndUpdate _id, - $set: - "balance": 8 - , (err, user) -> - expect(err).to.not.be.ok() - request.post(baseURL + "/challenges").send( - group: group._id - dailys: [] - todos: [] - rewards: [] - habits: [] - prize: 10 - ).end (res) -> - expect(res.body.prize).to.be 10 - async.parallel [ - (cb) -> - User.findById _id, cb - (cb) -> - Challenge.findById res.body._id, cb - ], (err, results) -> - _user = results[0] - challenge = results[1] - expect(_user.balance).to.be 5.5 - request.del(baseURL + "/challenges/" + challenge._id).end (res) -> - User.findById _id, (err, user) -> - expect(user.balance).to.be 8 - 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 - 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) -> - async.parallel [ - (cb2) -> - registerNewUser cb2, false - (cb2) -> - registerNewUser cb2, false - (cb2) -> - registerNewUser cb2, false - ], 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.be 4 - cb() - - ], -> - - # Start the quest - async.waterfall [ - (cb) -> - request.post(baseURL + "/groups/" + group._id + "/questAccept?key=vice3").end (res) -> - expectCode res, 400 - User.findByIdAndUpdate _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.be "vice3" - expect(_group.quest.active).to.be 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.be 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.be 1 - expect(member.stats.buffs.snowball).to.be true - difference = diff(member, party[0]) - expect(_.size(difference)).to.be 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.be 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.be 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 - console.log tavernBoss: tavern.quest - 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.be true - expect(user.items.pets["MantisShrimp-Base"]).to.be 5 - expect(user.items.mounts["MantisShrimp-Base"]).to.be true - expect(user.items.eggs.Dragon).to.be 2 - expect(user.items.hatchingPotions.Shade).to.be 2 - cb2() - - # Party Boss - (cb2) -> - - #use an explicit get because mongoose wraps the null in an object - expect(_.isEmpty(_group.get("quest"))).to.be true - expect(user.items.gear.owned.weapon_special_2).to.be true - expect(user.items.eggs.Dragon).to.be 2 - expect(user.items.hatchingPotions.Shade).to.be 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.be true - cb3() - (cb3) -> - User.findById party[1].id, (err, mbr) -> - expect(mbr.items.gear.owned.weapon_special_2).to.be 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 - - describe "Subscriptions", -> - user = undefined - before (done) -> - User.findOne - _id: _id - , (err, _user) -> - expect(err).to.not.be.ok() - user = _user - done() - - it "Handles unsubscription", (done) -> - cron = -> - user.lastCron = moment().subtract(1, "d") - user.fns.cron() - - expect(user.purchased.plan.customerId).to.not.be.ok() - payments.createSubscription - user: user - customerId: "123" - paymentMethod: "Stripe" - sub: {key: 'basic_6mo'} - - expect(user.purchased.plan.customerId).to.be.ok() - shared.wrap user - cron() - expect(user.purchased.plan.customerId).to.be.ok() - payments.cancelSubscription user: user - cron() - expect(user.purchased.plan.customerId).to.be.ok() - expect(user.purchased.plan.dateTerminated).to.be.ok() - user.purchased.plan.dateTerminated = moment().subtract(2, "d") - cron() - expect(user.purchased.plan.customerId).to.not.be.ok() - payments.createSubscription - user: user - customerId: "123" - paymentMethod: "Stripe" - sub: {key: 'basic_6mo'} - - expect(user.purchased.plan.dateTerminated).to.not.be.ok() - done() diff --git a/test/api/challenges.coffee b/test/api/challenges.coffee index a94e2bc583..1f47dbc1d8 100644 --- a/test/api/challenges.coffee +++ b/test/api/challenges.coffee @@ -146,3 +146,61 @@ describe "Challenges", -> expect(res.body.official).to.equal true cb() ], done + + it "User creates a non-tavern challenge with prize, deletes it, gets refund", (done) -> + User.findByIdAndUpdate user._id, + $set: + "balance": 8 + , (err, user) -> + expect(err).to.not.be.ok + request.post(baseURL + "/challenges").send( + group: group._id + dailys: [] + todos: [] + rewards: [] + habits: [] + prize: 10 + ).end (res) -> + expect(res.body.prize).to.equal 10 + 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.balance).to.equal 5.5 + request.del(baseURL + "/challenges/" + challenge._id).end (res) -> + User.findById user._id, (err, _user) -> + expect(_user.balance).to.equal 8 + done() + + it "User creates a tavern challenge with prize, deletes it, and does not get refund", (done) -> + User.findByIdAndUpdate user._id, + $set: + "balance": 8 + , (err, user) -> + expect(err).to.not.be.ok + request.post(baseURL + "/challenges").send( + group: 'habitrpg' + dailys: [] + todos: [] + rewards: [] + habits: [] + prize: 10 + ).end (res) -> + expect(res.body.prize).to.equal 10 + 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.balance).to.equal 5.5 + request.del(baseURL + "/challenges/" + challenge._id).end (res) -> + User.findById user._id, (err, _user) -> + expect(_user.balance).to.equal 5.5 + done() diff --git a/website/public/js/controllers/challengesCtrl.js b/website/public/js/controllers/challengesCtrl.js index 6df490571a..5f1f23980a 100644 --- a/website/public/js/controllers/challengesCtrl.js +++ b/website/public/js/controllers/challengesCtrl.js @@ -126,19 +126,27 @@ habitrpg.controller("ChallengesCtrl", ['$rootScope','$scope', 'Shared', 'User', $scope.challenges = Challenges.Challenge.query(); User.log({}); } - $scope.cancelClosing = function() { + $scope.cancelClosing = function(challenge) { $scope.popoverEl.popover('destroy'); $scope.popoverEl = undefined; $scope.closingChal = undefined; + challenge.winner = undefined; } $scope["delete"] = function(challenge) { - if (!confirm(window.env.t('sureDelCha'))) return; + var warningMsg; + if(challenge.group._id == 'habitrpg') { + warningMsg = window.env.t('sureDelChaTavern'); + } else { + warningMsg = window.env.t('sureDelCha'); + } + if (!confirm(warningMsg)) return; challenge.$delete(function(){ $scope.popoverEl.popover('destroy'); backToChallenges(); }); }; $scope.selectWinner = function(challenge) { + if (!challenge.winner) return; if (!confirm(window.env.t('youSure'))) return; challenge.$close({uid:challenge.winner}, function(){ $scope.popoverEl.popover('destroy'); diff --git a/website/src/controllers/challenges.js b/website/src/controllers/challenges.js index 26970b1dfe..8dea70cd1d 100644 --- a/website/src/controllers/challenges.js +++ b/website/src/controllers/challenges.js @@ -300,24 +300,18 @@ function closeChal(cid, broken, cb) { api['delete'] = function(req, res, next){ var user = res.locals.user; var cid = req.params.cid; - var chal + async.waterfall([ function(cb){ Challenge.findById(cid, cb); }, - function(_chal, cb){ - chal = _chal; + function(chal, cb){ if (!chal) return cb('Challenge ' + cid + ' not found'); if (chal.leader != user._id) return cb("You don't have permissions to edit this challenge"); - //Refunds to challenge leader - User.findById(user._id, cb) - }, - function(leader, cb){ - leader.balance += chal.prize/4; - leader.save(cb); + if (chal.group != 'habitrpg') user.balance += chal.prize/4; // Refund gems to user if a non-tavern challenge + user.save(cb); }, function(save, num, cb){ - //Deletes challenge and adds broken link (same as before) add prizeRefundedTo: save.profile.name? closeChal(req.params.cid, {broken: 'CHALLENGE_DELETED'}, cb); } ], function(err){ diff --git a/website/views/options/social/challenges.jade b/website/views/options/social/challenges.jade index c23a184fc8..b2e0d2c1a4 100644 --- a/website/views/options/social/challenges.jade +++ b/website/views/options/social/challenges.jade @@ -1,12 +1,12 @@ script(type='text/ng-template', id='partials/options.social.challenges.detail.close.html') a.btn.btn-sm.btn-danger(ng-click="delete(closingChal)")=env.t('delete') h5= '- ' + env.t('or') + ' -' - select(ui-select2, ng-required=true, ng-model='closingChal.winner', data-placeholder=env.t('selectWinner'), ng-change='selectWinner(closingChal)', ) + select(ui-select2, ng-required=true, ng-model='closingChal.winner', data-placeholder=env.t('selectWinner'), ng-change='selectWinner(closingChal)', style='display:block') option(value='') option(ng-repeat='u in closingChal.members', value='{{u._id}}') {{u.profile.name}} - small.pull-right - a(ng-click='cancelClosing(closingChal)')=env.t('cancel') + .text-right + small.btn-link(ng-click='cancelClosing(closingChal)')=env.t('cancel') script(type='text/ng-template', id='partials/options.social.challenges.detail.member.html') .modal.bs-modal-lg(style='display: block') @@ -115,17 +115,14 @@ script(type='text/ng-template', id='partials/options.social.challenges.html') .form-group textarea.form-control(cols='3', placeholder=env.t('challengeDescr'), ng-model='newChallenge.description') - //- what's going on here? - br - br - .form-group - input.form-control(type='number', min="{{newChallenge.group=='habitrpg' ? 1 : 0}}", max="{{maxPrize}}", ng-model='newChallenge.prize', placeholder=env.t('prize')) - span.input-suffix.Pet_Currency_Gem1x.inline-gems - |  - span.hint.vertical-20(popover=env.t('prizePop'), popover-trigger='mouseenter', popover-placement='right') + .input-group + span.input-group-addon + .Pet_Currency_Gem1x + input.form-control(type='number', min="{{newChallenge.group=='habitrpg' ? 1 : 0}}", max="{{maxPrize}}", ng-model='newChallenge.prize', placeholder=env.t('prize')) + a.hint(popover="{{newChallenge.group=='habitrpg' ? env.t('prizePopTavern') : env.t('prizePop')}}", popover-trigger='mouseenter', popover-placement='right') =env.t('moreInfo') - span(ng-show='newChallenge.group=="habitrpg"') + .pull-right(ng-show='newChallenge.group=="habitrpg"') !=env.t('publicChallenges') .form-group(ng-if='user.contributor.admin')