mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-28 10:06:08 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
472b05a5e0
13 changed files with 174 additions and 149 deletions
|
@ -342,6 +342,7 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
@ended = true
|
||||
@setPaused true
|
||||
Backbone.Mediator.publish 'surface:playback-ended', {}
|
||||
@updatePaths() # TODO: this is a hack to make sure paths are on the first time the level loads
|
||||
else if @currentFrame < @world.totalFrames and @ended
|
||||
@ended = false
|
||||
@setPaused false
|
||||
|
@ -586,7 +587,6 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
|
||||
updatePaths: ->
|
||||
return unless @options.paths and @heroLank
|
||||
return unless me.isAdmin() # TODO: Fix world thang points, targets, then remove this
|
||||
@hidePaths()
|
||||
return if @world.showPaths is 'never'
|
||||
layerAdapter = @lankBoss.layerAdapters['Path']
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
&.disabled
|
||||
@include opacity(0.8)
|
||||
.ace_cursor, .executing, .ace_active-line, .ace_gutter-active-line
|
||||
@include opacity(0.2)
|
||||
@include opacity(0.1)
|
||||
|
||||
.ace_gutter
|
||||
background-color: transparent
|
||||
|
|
|
@ -45,11 +45,15 @@
|
|||
// color: rgb(197, 6, 11)
|
||||
color: rgb(243, 169, 49)
|
||||
|
||||
|
||||
body:not(.dialogue-view-active)
|
||||
.spell-palette-popover.popover
|
||||
right: 45%
|
||||
min-width: 350px
|
||||
|
||||
.spell-palette-popover.popover
|
||||
// Only those popovers which are our direct children (spell documentation)
|
||||
max-width: 600px
|
||||
right: 45%
|
||||
min-width: 350px
|
||||
|
||||
&.pinned
|
||||
left: auto !important
|
||||
|
|
|
@ -378,11 +378,13 @@ module.exports = class InventoryModal extends ModalView
|
|||
unless itemModel and heroClass in itemModel.classes
|
||||
console.log 'Unequipping', itemModel.get('heroClass'), 'item', itemModel.get('name'), 'from slot due to class restrictions.'
|
||||
@unequipItemFromSlot @$el.find(".item-slot[data-slot='#{slot}']")
|
||||
delete equipment[slot]
|
||||
for slot, item of restrictedGear
|
||||
equipped = equipment[slot]
|
||||
if equipped and equipped is gear[restrictedGear[slot]]
|
||||
console.log 'Unequipping restricted item', restrictedGear[slot], 'for', slot, 'before level', @options.levelID
|
||||
@unequipItemFromSlot @$el.find(".item-slot[data-slot='#{slot}']")
|
||||
delete equipment[slot]
|
||||
if heroClass is 'Warrior'
|
||||
# After they switch to a ranger or wizard, we stop being so finicky about gear.
|
||||
for slot, item of requiredGear
|
||||
|
|
|
@ -40,7 +40,7 @@ module.exports = class WorldMapView extends RootView
|
|||
@levelStatusMap = {}
|
||||
@levelPlayCountMap = {}
|
||||
@sessions = @supermodel.loadCollection(new LevelSessionsCollection(), 'your_sessions', null, 0).model
|
||||
|
||||
|
||||
# Temporary attempt to make sure all earned rewards are accounted for. Figure out a better solution...
|
||||
@earnedAchievements = new CocoCollection([], {url: '/db/earned_achievement', model:EarnedAchievement, project: ['earnedRewards']})
|
||||
@listenToOnce @earnedAchievements, 'sync', ->
|
||||
|
@ -56,7 +56,7 @@ module.exports = class WorldMapView extends RootView
|
|||
earned[group].push(reward)
|
||||
addedSomething = true
|
||||
@supermodel.loadCollection(@earnedAchievements, 'achievements')
|
||||
|
||||
|
||||
@listenToOnce @sessions, 'sync', @onSessionsLoaded
|
||||
@getLevelPlayCounts()
|
||||
$(window).on 'resize', @onWindowResize
|
||||
|
@ -136,7 +136,7 @@ module.exports = class WorldMapView extends RootView
|
|||
if levelID = @$el.find('.level.next').data('level-id')
|
||||
@$levelInfo = @$el.find(".level-info-container[data-level-id=#{levelID}]").show()
|
||||
pos = @$el.find('.level.next').offset()
|
||||
@adjustLevelInfoPosition pageX: pos.left, pageY: pos.top + 250
|
||||
@adjustLevelInfoPosition pageX: pos.left, pageY: pos.top
|
||||
@manuallyPositionedLevelInfoID = levelID
|
||||
|
||||
afterInsert: ->
|
||||
|
@ -203,6 +203,7 @@ module.exports = class WorldMapView extends RootView
|
|||
@$levelInfo = @$el.find(".level-info-container[data-level-id=#{levelID}]").show()
|
||||
@adjustLevelInfoPosition e
|
||||
@endHighlight()
|
||||
@manuallyPositionedLevelInfoID = false
|
||||
|
||||
onMouseLeaveLevel: (e) ->
|
||||
return if application.isIPadApp
|
||||
|
|
|
@ -19,13 +19,10 @@ module.exports = class LevelDialogueView extends CocoView
|
|||
onClick: (e) ->
|
||||
Backbone.Mediator.publish 'tome:focus-editor', {}
|
||||
|
||||
onFrameChanged: (e) ->
|
||||
@timeProgress = e.progress
|
||||
@update()
|
||||
|
||||
onSpriteDialogue: (e) ->
|
||||
return unless e.message
|
||||
@$el.addClass 'active speaking'
|
||||
$('body').addClass('dialogue-view-active')
|
||||
@setMessage e.message, e.mood, e.responses
|
||||
|
||||
window.tracker?.trackEvent 'Heard Sprite', {message: e.message, label: e.message}, ['Google Analytics']
|
||||
|
@ -35,6 +32,7 @@ module.exports = class LevelDialogueView extends CocoView
|
|||
|
||||
onSpriteClearDialogue: ->
|
||||
@$el.removeClass 'active speaking'
|
||||
$('body').removeClass('dialogue-view-active')
|
||||
|
||||
setMessage: (message, mood, responses) ->
|
||||
message = marked message
|
||||
|
|
|
@ -56,6 +56,7 @@ module.exports = class LevelHUDView extends CocoView
|
|||
setThang: (thang, thangType) ->
|
||||
if not thang? and not @thang? then return
|
||||
if thang? and @thang? and thang.id is @thang.id then return
|
||||
if thang? and @hidesHUD and thang.id isnt 'Hero Placeholder' then return # Don't let them find the names of their opponents this way
|
||||
@thang = thang
|
||||
@thangType = thangType
|
||||
return unless @thang
|
||||
|
|
|
@ -37,10 +37,11 @@ module.exports = class SpellPaletteEntryView extends CocoView
|
|||
afterRender: ->
|
||||
super()
|
||||
@$el.addClass(@doc.type)
|
||||
placement = -> if $('body').hasClass('dialogue-view-active') then 'top' else 'left'
|
||||
@$el.popover(
|
||||
animation: false
|
||||
html: true
|
||||
placement: 'left'
|
||||
placement: placement
|
||||
trigger: 'manual' # Hover, until they click, which will then pin it until unclick.
|
||||
content: @docFormatter.formatPopover()
|
||||
container: 'body'
|
||||
|
|
|
@ -131,13 +131,12 @@ module.exports = class SpellView extends CocoView
|
|||
addCommand
|
||||
name: 'toggle-playing'
|
||||
bindKey: {win: 'Ctrl-P', mac: 'Command-P|Ctrl-P'}
|
||||
readOnly: true
|
||||
exec: -> Backbone.Mediator.publish 'level:toggle-playing', {}
|
||||
addCommand
|
||||
name: 'end-current-script'
|
||||
bindKey: {win: 'Shift-Space', mac: 'Shift-Space'}
|
||||
# passEvent: true # https://github.com/ajaxorg/ace/blob/master/lib/ace/keyboard/keybinding.js#L114
|
||||
# No easy way to selectively cancel shift+space, since we don't get access to the event.
|
||||
# Maybe we could temporarily set ourselves to read-only if we somehow know that a script is active?
|
||||
readOnly: true
|
||||
exec: =>
|
||||
if @scriptRunning
|
||||
Backbone.Mediator.publish 'level:shift-space-pressed', {}
|
||||
|
@ -147,34 +146,44 @@ module.exports = class SpellView extends CocoView
|
|||
addCommand
|
||||
name: 'end-all-scripts'
|
||||
bindKey: {win: 'Escape', mac: 'Escape'}
|
||||
exec: -> Backbone.Mediator.publish 'level:escape-pressed', {}
|
||||
readOnly: true
|
||||
exec: ->
|
||||
console.log 'esc pressed'
|
||||
Backbone.Mediator.publish 'level:escape-pressed', {}
|
||||
addCommand
|
||||
name: 'toggle-grid'
|
||||
bindKey: {win: 'Ctrl-G', mac: 'Command-G|Ctrl-G'}
|
||||
readOnly: true
|
||||
exec: -> Backbone.Mediator.publish 'level:toggle-grid', {}
|
||||
addCommand
|
||||
name: 'toggle-debug'
|
||||
bindKey: {win: 'Ctrl-\\', mac: 'Command-\\|Ctrl-\\'}
|
||||
readOnly: true
|
||||
exec: -> Backbone.Mediator.publish 'level:toggle-debug', {}
|
||||
addCommand
|
||||
name: 'toggle-pathfinding'
|
||||
bindKey: {win: 'Ctrl-O', mac: 'Command-O|Ctrl-O'}
|
||||
readOnly: true
|
||||
exec: -> Backbone.Mediator.publish 'level:toggle-pathfinding', {}
|
||||
addCommand
|
||||
name: 'level-scrub-forward'
|
||||
bindKey: {win: 'Ctrl-]', mac: 'Command-]|Ctrl-]'}
|
||||
readOnly: true
|
||||
exec: -> Backbone.Mediator.publish 'level:scrub-forward', {}
|
||||
addCommand
|
||||
name: 'level-scrub-back'
|
||||
bindKey: {win: 'Ctrl-[', mac: 'Command-[|Ctrl-]'}
|
||||
readOnly: true
|
||||
exec: -> Backbone.Mediator.publish 'level:scrub-back', {}
|
||||
addCommand
|
||||
name: 'spell-step-forward'
|
||||
bindKey: {win: 'Ctrl-Alt-]', mac: 'Command-Alt-]|Ctrl-Alt-]'}
|
||||
readOnly: true
|
||||
exec: -> Backbone.Mediator.publish 'tome:spell-step-forward', {}
|
||||
addCommand
|
||||
name: 'spell-step-backward'
|
||||
bindKey: {win: 'Ctrl-Alt-[', mac: 'Command-Alt-[|Ctrl-Alt-]'}
|
||||
readOnly: true
|
||||
exec: -> Backbone.Mediator.publish 'tome:spell-step-backward', {}
|
||||
addCommand
|
||||
name: 'spell-beautify'
|
||||
|
@ -815,10 +824,11 @@ module.exports = class SpellView extends CocoView
|
|||
return if enabled is @controlsEnabled
|
||||
@controlsEnabled = enabled and @writable
|
||||
disabled = not enabled
|
||||
$('body').focus() if disabled and $(document.activeElement).is('.ace_text-input')
|
||||
wasFocused = @ace.isFocused()
|
||||
@ace.setReadOnly disabled
|
||||
@ace[if disabled then 'setStyle' else 'unsetStyle'] 'disabled'
|
||||
@toggleBackground()
|
||||
$('body').focus() if disabled and wasFocused
|
||||
|
||||
toggleBackground: =>
|
||||
# TODO: make the background an actual background and do the CSS trick
|
||||
|
|
|
@ -67,7 +67,7 @@ class EarnedAchievementHandler extends Handler
|
|||
if achievement.get('proportionalTo')
|
||||
return @sendBadInputError(res, 'Cannot currently do this to repeatable docs...')
|
||||
EarnedAchievement.createForAchievement(achievement, trigger, null, (earnedAchievementDoc) =>
|
||||
@sendSuccess(res, earnedAchievementDoc.toObject())
|
||||
@sendCreated(res, earnedAchievementDoc.toObject())
|
||||
)
|
||||
|
||||
)
|
||||
|
|
|
@ -88,10 +88,13 @@ PaymentHandler = class PaymentHandler extends Handler
|
|||
|
||||
#- Check existence
|
||||
transactionID = transaction.transaction_id
|
||||
criteria = { recipient: req.user._id, 'ios.transactionID': transactionID }
|
||||
criteria = { 'ios.transactionID': transactionID }
|
||||
Payment.findOne(criteria).exec((err, payment) =>
|
||||
|
||||
if payment
|
||||
unless payment.get('recipient').equals(req.user._id)
|
||||
return @sendForbiddenError(res)
|
||||
|
||||
@recalculateGemsFor(req.user, (err) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
@sendSuccess(res, @formatEntity(req, payment))
|
||||
|
|
|
@ -122,134 +122,133 @@ describe 'Achievement', ->
|
|||
|
||||
# TODO: Took level achievements out of this auto achievement business, so fix these tests
|
||||
|
||||
#describe 'Achieving Achievements', ->
|
||||
# it 'wait for achievements to be loaded', (done) ->
|
||||
# Achievement.loadAchievements (achievements) ->
|
||||
# expect(Object.keys(achievements).length).toBe(1)
|
||||
#
|
||||
# loadedAchievements = Achievement.getLoadedAchievements()
|
||||
# expect(Object.keys(loadedAchievements).length).toBe(1)
|
||||
# done()
|
||||
#
|
||||
# it 'saving an object that should trigger an unlockable achievement', (done) ->
|
||||
# unittest.getNormalJoe (joe) ->
|
||||
# session = new LevelSession
|
||||
# permissions: simplePermissions
|
||||
# creator: joe._id
|
||||
# level: original: 'dungeon-arena'
|
||||
# session.save (err, doc) ->
|
||||
# expect(err).toBeNull()
|
||||
# expect(doc).toBeDefined()
|
||||
# expect(doc.creator).toBe(session.creator)
|
||||
# done()
|
||||
#
|
||||
# it 'verify that an unlockable achievement has been earned', (done) ->
|
||||
# unittest.getNormalJoe (joe) ->
|
||||
# EarnedAchievement.find {}, (err, docs) ->
|
||||
# expect(err).toBeNull()
|
||||
# expect(docs.length).toBe(1)
|
||||
# achievement = docs[0]
|
||||
# expect(achievement).toBeDefined()
|
||||
#
|
||||
# expect(achievement.get 'achievement').toBe unlockable._id
|
||||
# expect(achievement.get 'user').toBe joe._id.toHexString()
|
||||
# expect(achievement.get 'notified').toBeFalsy()
|
||||
# expect(achievement.get 'earnedPoints').toBe unlockable.worth
|
||||
# expect(achievement.get 'achievedAmount').toBeUndefined()
|
||||
# expect(achievement.get 'previouslyAchievedAmount').toBeUndefined()
|
||||
# done()
|
||||
#
|
||||
# it 'saving an object that should trigger a repeatable achievement', (done) ->
|
||||
# unittest.getNormalJoe (joe) ->
|
||||
# expect(joe.get 'simulatedBy').toBeFalsy()
|
||||
# joe.set('simulatedBy', 2)
|
||||
# joe.save (err, doc) ->
|
||||
# expect(err).toBeNull()
|
||||
# done()
|
||||
#
|
||||
# it 'verify that a repeatable achievement has been earned', (done) ->
|
||||
# unittest.getNormalJoe (joe) ->
|
||||
# EarnedAchievement.find {achievementName: repeatable.name}, (err, docs) ->
|
||||
# expect(err).toBeNull()
|
||||
# expect(docs.length).toBe(1)
|
||||
# achievement = docs[0]
|
||||
#
|
||||
# expect(achievement.get 'achievement').toBe repeatable._id
|
||||
# expect(achievement.get 'user').toBe joe._id.toHexString()
|
||||
# expect(achievement.get 'notified').toBeFalsy()
|
||||
# expect(achievement.get 'earnedPoints').toBe 2 * repeatable.worth
|
||||
# expect(achievement.get 'achievedAmount').toBe 2
|
||||
# expect(achievement.get 'previouslyAchievedAmount').toBeFalsy()
|
||||
# done()
|
||||
#
|
||||
#
|
||||
# it 'verify that the repeatable achievement with complex exp has been earned', (done) ->
|
||||
# unittest.getNormalJoe (joe) ->
|
||||
# EarnedAchievement.find {achievementName: diminishing.name}, (err, docs) ->
|
||||
# expect(err).toBeNull()
|
||||
# expect(docs.length).toBe 1
|
||||
# achievement = docs[0]
|
||||
#
|
||||
# expect(achievement.get 'achievedAmount').toBe 2
|
||||
# expect(achievement.get 'earnedPoints').toBe (Math.log(.5 * (2 + .5)) + 1) * diminishing.worth
|
||||
#
|
||||
# done()
|
||||
describe 'Level Session Achievement', ->
|
||||
it 'does not generate earned achievements automatically, they need to be created manually', (done) ->
|
||||
unittest.getNormalJoe (joe) ->
|
||||
session = new LevelSession
|
||||
permissions: simplePermissions
|
||||
creator: joe._id
|
||||
level: original: 'dungeon-arena'
|
||||
session.save (err, session) ->
|
||||
expect(err).toBeNull()
|
||||
expect(session).toBeDefined()
|
||||
expect(session.creator).toBe(session.creator)
|
||||
|
||||
EarnedAchievement.find {}, (err, earnedAchievements) ->
|
||||
expect(err).toBeNull()
|
||||
expect(earnedAchievements.length).toBe(0)
|
||||
|
||||
json = {achievement: unlockable._id, triggeredBy: session._id, collection: 'level.sessions'}
|
||||
request.post {uri: getURL('/db/earned_achievement'), json: json}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(201)
|
||||
expect(body.achievement).toBe unlockable._id+''
|
||||
expect(body.user).toBe joe._id.toHexString()
|
||||
expect(body.notified).toBeFalsy()
|
||||
expect(body.earnedPoints).toBe unlockable.worth
|
||||
expect(body.achievedAmount).toBeUndefined()
|
||||
expect(body.previouslyAchievedAmount).toBeUndefined()
|
||||
done()
|
||||
|
||||
#describe 'Recalculate Achievements', ->
|
||||
# EarnedAchievementHandler = require '../../../server/achievements/earned_achievement_handler'
|
||||
#
|
||||
# it 'remove earned achievements', (done) ->
|
||||
# clearModels [EarnedAchievement], (err) ->
|
||||
# expect(err).toBeNull()
|
||||
# EarnedAchievement.find {}, (err, earned) ->
|
||||
# expect(earned.length).toBe 0
|
||||
#
|
||||
# User.update {}, {$set: {points: 0}}, {multi:true}, (err) ->
|
||||
# expect(err).toBeNull()
|
||||
# done()
|
||||
#
|
||||
# it 'can not be accessed by regular users', (done) ->
|
||||
# loginJoe -> request.post {uri:getURL '/admin/earned_achievement/recalculate'}, (err, res, body) ->
|
||||
# expect(res.statusCode).toBe 403
|
||||
# done()
|
||||
#
|
||||
# it 'can recalculate a selection of achievements', (done) ->
|
||||
# loginAdmin ->
|
||||
# EarnedAchievementHandler.constructor.recalculate ['dungeon-arena-started'], ->
|
||||
# EarnedAchievement.find {}, (err, earnedAchievements) ->
|
||||
# expect(earnedAchievements.length).toBe 1
|
||||
#
|
||||
# # Recalculate again, doesn't change a thing
|
||||
# EarnedAchievementHandler.constructor.recalculate ['dungeon-arena-started'], ->
|
||||
# EarnedAchievement.find {}, (err, earnedAchievements) ->
|
||||
# expect(earnedAchievements.length).toBe 1
|
||||
#
|
||||
# unittest.getNormalJoe (joe) ->
|
||||
# User.findById joe.get('id'), (err, guy) ->
|
||||
# expect(err).toBeNull()
|
||||
# expect(guy.get 'points').toBe unlockable.worth
|
||||
# done()
|
||||
#
|
||||
# it 'can recalculate all achievements', (done) ->
|
||||
# loginAdmin ->
|
||||
# Achievement.count {}, (err, count) ->
|
||||
# expect(count).toBe 3
|
||||
# EarnedAchievementHandler.constructor.recalculate ->
|
||||
# EarnedAchievement.find {}, (err, earnedAchievements) ->
|
||||
# expect(earnedAchievements.length).toBe 3
|
||||
# unittest.getNormalJoe (joe) ->
|
||||
# User.findById joe.get('id'), (err, guy) ->
|
||||
# expect(err).toBeNull()
|
||||
# expect(guy.get 'points').toBe unlockable.worth + 2 * repeatable.worth + (Math.log(.5 * (2 + .5)) + 1) * diminishing.worth
|
||||
# done()
|
||||
#
|
||||
# it 'cleaning up test: deleting all Achievements and related', (done) ->
|
||||
# clearModels [Achievement, EarnedAchievement, LevelSession], (err) ->
|
||||
# expect(err).toBeNull()
|
||||
#
|
||||
# # reset achievements in memory as well
|
||||
# Achievement.resetAchievements()
|
||||
# loadedAchievements = Achievement.getLoadedAchievements()
|
||||
# expect(Object.keys(loadedAchievements).length).toBe(0)
|
||||
#
|
||||
# done()
|
||||
|
||||
describe 'Achieving Achievements', ->
|
||||
it 'wait for achievements to be loaded', (done) ->
|
||||
Achievement.loadAchievements (achievements) ->
|
||||
expect(Object.keys(achievements).length).toBe(1)
|
||||
|
||||
loadedAchievements = Achievement.getLoadedAchievements()
|
||||
expect(Object.keys(loadedAchievements).length).toBe(1)
|
||||
done()
|
||||
|
||||
it 'saving an object that should trigger a repeatable achievement', (done) ->
|
||||
unittest.getNormalJoe (joe) ->
|
||||
expect(joe.get 'simulatedBy').toBeFalsy()
|
||||
joe.set('simulatedBy', 2)
|
||||
joe.save (err, doc) ->
|
||||
expect(err).toBeNull()
|
||||
done()
|
||||
|
||||
it 'verify that a repeatable achievement has been earned', (done) ->
|
||||
unittest.getNormalJoe (joe) ->
|
||||
EarnedAchievement.find {achievementName: repeatable.name}, (err, docs) ->
|
||||
expect(err).toBeNull()
|
||||
expect(docs.length).toBe(1)
|
||||
achievement = docs[0]
|
||||
|
||||
expect(achievement.get 'achievement').toBe repeatable._id
|
||||
expect(achievement.get 'user').toBe joe._id.toHexString()
|
||||
expect(achievement.get 'notified').toBeFalsy()
|
||||
expect(achievement.get 'earnedPoints').toBe 2 * repeatable.worth
|
||||
expect(achievement.get 'achievedAmount').toBe 2
|
||||
expect(achievement.get 'previouslyAchievedAmount').toBeFalsy()
|
||||
done()
|
||||
|
||||
it 'verify that the repeatable achievement with complex exp has been earned', (done) ->
|
||||
unittest.getNormalJoe (joe) ->
|
||||
EarnedAchievement.find {achievementName: diminishing.name}, (err, docs) ->
|
||||
expect(err).toBeNull()
|
||||
expect(docs.length).toBe 1
|
||||
achievement = docs[0]
|
||||
|
||||
expect(achievement.get 'achievedAmount').toBe 2
|
||||
expect(achievement.get 'earnedPoints').toBe (Math.log(.5 * (2 + .5)) + 1) * diminishing.worth
|
||||
|
||||
done()
|
||||
|
||||
describe 'Recalculate Achievements', ->
|
||||
EarnedAchievementHandler = require '../../../server/achievements/earned_achievement_handler'
|
||||
|
||||
it 'remove earned achievements', (done) ->
|
||||
clearModels [EarnedAchievement], (err) ->
|
||||
expect(err).toBeNull()
|
||||
EarnedAchievement.find {}, (err, earned) ->
|
||||
expect(earned.length).toBe 0
|
||||
|
||||
User.update {}, {$set: {points: 0}}, {multi:true}, (err) ->
|
||||
expect(err).toBeNull()
|
||||
done()
|
||||
|
||||
it 'can not be accessed by regular users', (done) ->
|
||||
loginJoe -> request.post {uri:getURL '/admin/earned_achievement/recalculate'}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe 403
|
||||
done()
|
||||
|
||||
it 'can recalculate a selection of achievements', (done) ->
|
||||
loginAdmin ->
|
||||
EarnedAchievementHandler.constructor.recalculate ['dungeon-arena-started'], ->
|
||||
EarnedAchievement.find {}, (err, earnedAchievements) ->
|
||||
expect(earnedAchievements.length).toBe 1
|
||||
|
||||
# Recalculate again, doesn't change a thing
|
||||
EarnedAchievementHandler.constructor.recalculate ['dungeon-arena-started'], ->
|
||||
EarnedAchievement.find {}, (err, earnedAchievements) ->
|
||||
expect(earnedAchievements.length).toBe 1
|
||||
|
||||
unittest.getNormalJoe (joe) ->
|
||||
User.findById joe.get('id'), (err, guy) ->
|
||||
expect(err).toBeNull()
|
||||
expect(guy.get 'points').toBe unlockable.worth
|
||||
done()
|
||||
|
||||
it 'can recalculate all achievements', (done) ->
|
||||
loginAdmin ->
|
||||
Achievement.count {}, (err, count) ->
|
||||
expect(count).toBe 3
|
||||
EarnedAchievementHandler.constructor.recalculate ->
|
||||
EarnedAchievement.find {}, (err, earnedAchievements) ->
|
||||
expect(earnedAchievements.length).toBe 3
|
||||
unittest.getNormalJoe (joe) ->
|
||||
User.findById joe.get('id'), (err, guy) ->
|
||||
expect(err).toBeNull()
|
||||
expect(guy.get 'points').toBe unlockable.worth + 2 * repeatable.worth + (Math.log(.5 * (2 + .5)) + 1) * diminishing.worth
|
||||
done()
|
||||
|
||||
it 'cleaning up test: deleting all Achievements and related', (done) ->
|
||||
clearModels [Achievement, EarnedAchievement, LevelSession], (err) ->
|
||||
expect(err).toBeNull()
|
||||
|
||||
# reset achievements in memory as well
|
||||
Achievement.resetAchievements()
|
||||
loadedAchievements = Achievement.getLoadedAchievements()
|
||||
expect(Object.keys(loadedAchievements).length).toBe(0)
|
||||
|
||||
done()
|
||||
|
|
|
@ -52,6 +52,12 @@ describe '/db/payment', ->
|
|||
done()
|
||||
)
|
||||
|
||||
it 'prevents other users from reusing payment receipts', (done) ->
|
||||
loginSam ->
|
||||
request.post {uri: paymentURL, json: firstApplePayment}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe 403
|
||||
done()
|
||||
|
||||
it 'processes only the transactionID that is given', (done) ->
|
||||
loginJoe ->
|
||||
request.post {uri: paymentURL, json: secondApplePayment}, (err, res, body) ->
|
||||
|
|
Loading…
Reference in a new issue