diff --git a/common/locales/en/subscriber.json b/common/locales/en/subscriber.json index c448afe75f..64db64bb2d 100644 --- a/common/locales/en/subscriber.json +++ b/common/locales/en/subscriber.json @@ -61,7 +61,8 @@ "timeTravelersTitle": "Mysterious Time Travelers", "timeTravelersPopoverNoSub": "You'll need a Mystic Hourglass to summon the mysterious Time Travelers! <%= linkStart %>Subscribers<%= linkEnd %> earn one Mystic Hourglass for every three months of consecutive subscribing. Come back when you have a Mystic Hourglass, and the Time Travelers will fetch you a Subscriber Item Set from the past.... or maybe even the future.", "timeTravelersPopover": "We see you have a Mystic Hourglass, so we will happily travel back in time for you! Please choose the Mystery Item Set you would like. You can see a list of the past item sets <%= linkStart %>here<%= linkEnd %>! If those don't satisfy you, perhaps you'd be interested in one of our fashionably futuristic Steampunk Item Sets?", - "mysticHourglassPopover": "Mystic Hourglass allow you to purchase previous months' subscriber sets.", + "timeTravelersAlreadyOwned": "Congratulations! You already own all of the Mystery Items. Thanks for supporting the site!", + "mysticHourglassPopover": "Mystic Hourglass allows you to purchase previous months' subscriber sets.", "subUpdateCard": "Update Card", "subUpdateTitle": "Update", "subUpdateDescription": "Update the card to be charged." diff --git a/test/server_side/controllers/user.test.js b/test/server_side/controllers/user.test.js index ec3b447630..aac7bf69b7 100644 --- a/test/server_side/controllers/user.test.js +++ b/test/server_side/controllers/user.test.js @@ -552,4 +552,66 @@ describe('User Controller', function() { }); }); }); + + describe('#addTenGems', function() { + var req, res, user; + + beforeEach(function() { + user = { + _id: 'user-id', + balance: 5, + save: sinon.stub().yields() + }; + req = { }; + res = { + locals: { user: user }, + send: sinon.spy() + }; + }); + + it('adds 2.5 to user balance', function() { + userController.addTenGems(req, res); + + expect(user.balance).to.eql(7.5); + expect(user.save).to.be.calledOnce; + }); + + it('sends back 204', function() { + userController.addTenGems(req, res); + + expect(res.send).to.be.calledOnce; + expect(res.send).to.be.calledWith(204); + }); + }); + + describe('#addHourglass', function() { + var req, res, user; + + beforeEach(function() { + user = { + _id: 'user-id', + purchased: { plan: { consecutive: { trinkets: 3 } } }, + save: sinon.stub().yields() + }; + req = { }; + res = { + locals: { user: user }, + send: sinon.spy() + }; + }); + + it('adds an hourglass to user', function() { + userController.addHourglass(req, res); + + expect(user.purchased.plan.consecutive.trinkets).to.eql(4); + expect(user.save).to.be.calledOnce; + }); + + it('sends back 204', function() { + userController.addHourglass(req, res); + + expect(res.send).to.be.calledOnce; + expect(res.send).to.be.calledWith(204); + }); + }); }); diff --git a/test/spec/controllers/footerCtrlSpec.js b/test/spec/controllers/footerCtrlSpec.js new file mode 100644 index 0000000000..7b12bc2875 --- /dev/null +++ b/test/spec/controllers/footerCtrlSpec.js @@ -0,0 +1,85 @@ +'use strict'; + +describe('Footer Controller', function() { + var scope, user; + + beforeEach(inject(function($rootScope, $controller) { + console.log(window.env.NODE_ENV); + user = specHelper.newUser(); + var User = {log: sandbox.stub(), set: sandbox.stub(), user: user}; + scope = $rootScope.$new(); + $controller('FooterCtrl', {$scope: scope, User: User}); + })); + + context('Debug mode', function() { + before(function() { + window.env.NODE_ENV = 'test'; + }); + + after(function() { + delete window.env.NODE_ENV; + }); + + describe('#setHealthLow', function(){ + it('sets user health to 1'); + }); + + describe('#addMissedDay', function(){ + beforeEach(function() { + sandbox.stub(confirm).returns(true); + }); + + it('Cancels if confirm box is not confirmed'); + + it('allows multiple days'); + + it('sets users last cron'); + + it('notifies uers'); + }); + + describe('#addTenGems', function() { + it('posts to /user/addTenGems', inject(function($httpBackend) { + $httpBackend.expectPOST('/api/v2/user/addTenGems').respond({}); + + scope.addTenGems(); + + $httpBackend.flush(); + })); + }); + + describe('#addHourglass', function() { + it('posts to /user/addHourglass', inject(function($httpBackend) { + $httpBackend.expectPOST('/api/v2/user/addHourglass').respond({}); + + scope.addHourglass(); + + $httpBackend.flush(); + })); + }); + + describe('#addGold', function() { + it('adds 500 gold to user'); + }); + + describe('#addMana', function() { + it('adds 500 mana to user'); + }); + + describe('#addLevelsAndGold', function() { + it('adds 10000 experience to user'); + + it('adds 10000 gp to user'); + + it('adds 10000 mp to user'); + }); + + describe('#addOneLevel', function() { + it('adds one level to user'); + }); + + describe('#addBossQuestProgressUp', function() { + it('adds 1000 progress to quest.progress.up'); + }); + }); +}); diff --git a/test/spec/controllers/inventoryCtrlSpec.js b/test/spec/controllers/inventoryCtrlSpec.js index f9afeb0449..acdcc86840 100644 --- a/test/spec/controllers/inventoryCtrlSpec.js +++ b/test/spec/controllers/inventoryCtrlSpec.js @@ -12,6 +12,7 @@ describe('Inventory Controller', function() { user = specHelper.newUser({ balance: 4, items: { + gear: { owned: {} }, eggs: { Cactus: 1 }, hatchingPotions: { Base: 1 }, food: { Meat: 1 }, @@ -155,4 +156,16 @@ describe('Inventory Controller', function() { expect(possibleValues).to.contain(cardsModalScope.cardMessage); }); }); + + describe('#hasAllTimeTravelerItems', function() { + it('returns false if there are items left in the time traveler store', function() { + expect(scope.hasAllTimeTravelerItems()).to.eql(false); + }); + + it('returns true if there are no items left to purchase', inject(function(Content) { + sandbox.stub(Content, 'timeTravelerStore').returns({}); + + expect(scope.hasAllTimeTravelerItems()).to.eql(true); + })); + }); }); diff --git a/website/public/js/controllers/footerCtrl.js b/website/public/js/controllers/footerCtrl.js index a12225f8e3..a25972fc81 100644 --- a/website/public/js/controllers/footerCtrl.js +++ b/website/public/js/controllers/footerCtrl.js @@ -69,48 +69,62 @@ function($scope, $rootScope, User, $http, Notification, ApiUrl) { * Debug functions. Note that the server route for gems is only available if process.env.DEBUG=true */ if (_.contains(['development','test'],window.env.NODE_ENV)) { + $scope.setHealthLow = function(){ User.set({ 'stats.hp': 1 }); - } + }; + $scope.addMissedDay = function(numberOfDays){ if (!confirm("Are you sure you want to reset the day by " + numberOfDays + " day(s)?")) return; var dayBefore = moment(User.user.lastCron).subtract(numberOfDays, 'days').toDate(); User.set({'lastCron': dayBefore}); Notification.text('-' + numberOfDays + ' day(s), remember to refresh'); - } + }; + $scope.addTenGems = function(){ $http.post(ApiUrl.get() + '/api/v2/user/addTenGems').success(function(){ User.log({}); }) - } + }; + + $scope.addHourglass = function(){ + $http.post(ApiUrl.get() + '/api/v2/user/addHourglass').success(function(){ + User.log({}); + }) + }; + $scope.addGold = function(){ User.set({ 'stats.gp': User.user.stats.gp + 500, }); - } + }; + $scope.addMana = function(){ User.set({ 'stats.mp': User.user.stats.mp + 500, }); - } + }; + $scope.addLevelsAndGold = function(){ User.set({ 'stats.exp': User.user.stats.exp + 10000, 'stats.gp': User.user.stats.gp + 10000, 'stats.mp': User.user.stats.mp + 10000 }); - } + }; + $scope.addOneLevel = function(){ User.set({ 'stats.exp': User.user.stats.exp + (Math.round(((Math.pow(User.user.stats.lvl, 2) * 0.25) + (10 * User.user.stats.lvl) + 139.75) / 10) * 10) }); - } + }; + $scope.addBossQuestProgressUp = function(){ User.set({ 'party.quest.progress.up': User.user.party.quest.progress.up + 1000 }); - } + }; } }]) diff --git a/website/public/js/controllers/inventoryCtrl.js b/website/public/js/controllers/inventoryCtrl.js index 4edad98680..e140a3798e 100644 --- a/website/public/js/controllers/inventoryCtrl.js +++ b/website/public/js/controllers/inventoryCtrl.js @@ -228,6 +228,13 @@ habitrpg.controller("InventoryCtrl", }); }; + $scope.hasAllTimeTravelerItems = function(items) { + var itemsLeftInTimeTravlerStore = Content.timeTravelerStore(user.items.gear.owned); + var keys = Object.keys(itemsLeftInTimeTravlerStore); + + return keys.length === 0; + }; + function _updateDropAnimalCount(items) { $scope.petCount = Shared.count.beastMasterProgress(items.pets); $scope.mountCount = Shared.count.mountMasterProgress(items.mounts); diff --git a/website/src/controllers/user.js b/website/src/controllers/user.js index f961ee5918..80a8321191 100644 --- a/website/src/controllers/user.js +++ b/website/src/controllers/user.js @@ -412,6 +412,25 @@ api.addTenGems = function(req, res, next) { }) } +/* + ------------------------------------------------------------------------ + Hourglass + ------------------------------------------------------------------------ + */ + +// api.unlock // see Shared.ops + +api.addHourglass = function(req, res, next) { + var user = res.locals.user; + + user.purchased.plan.consecutive.trinkets += 1; + + user.save(function(err){ + if (err) return next(err); + res.send(204); + }) +} + /* ------------------------------------------------------------------------ Tags diff --git a/website/src/routes/apiv2.coffee b/website/src/routes/apiv2.coffee index 396747fcf4..db26ac57a7 100644 --- a/website/src/routes/apiv2.coffee +++ b/website/src/routes/apiv2.coffee @@ -783,6 +783,10 @@ module.exports = (swagger, v2) -> spec: method:'POST' action: user.addTenGems + api["/user/addHourglass"] = + spec: method:'POST' + action: user.addHourglass + _.each api, (route, path) -> ## Spec format is: # spec: diff --git a/website/views/options/inventory/time-travelers.jade b/website/views/options/inventory/time-travelers.jade index 7e7332429a..4b8277038f 100644 --- a/website/views/options/inventory/time-travelers.jade +++ b/website/views/options/inventory/time-travelers.jade @@ -1,23 +1,22 @@ .container-fluid - .stable.row(ng-if='user.purchased.plan.consecutive.trinkets <= 0'): .col-xs-12 - .npc_timetravelers.pull-left-sm.col-centered + .stable.row: .col-xs-12 + - var hasTrinkets = 'user.purchased.plan.consecutive.trinkets > 0' + .pull-left-sm.col-centered(ng-class='#{hasTrinkets} ? "npc_timetravelers_active" : "npc_timetravelers"') .popover.static-popover.fade.right.in.pull-left-sm.col-centered .arrow.hidden-xs - h3.popover-title!=env.t('timeTravelersTitleNoSub', {linkStartTyler: "", linkStartVicky: "", linkEnd: ""}) - .popover-content + h3.popover-title(ng-if='#{hasTrinkets}')=env.t('timeTravelersTitle') + h3.popover-title(ng-if='!(#{hasTrinkets})')!=env.t('timeTravelersTitleNoSub', {linkStartTyler: "", linkStartVicky: "", linkEnd: ""}) + .popover-content(ng-if='!(#{hasTrinkets})') p!=env.t('timeTravelersPopoverNoSub', {linkStart: "", linkEnd: ""}) - - .stable.row(ng-if='user.purchased.plan.consecutive.trinkets > 0'): .col-xs-12 - .npc_timetravelers_active.pull-left-sm.col-centered - .popover.static-popover.fade.right.in.pull-left-sm.col-centered - .arrow.hidden-xs - h3.popover-title=env.t('timeTravelersTitle') - .popover-content + .popover-content(ng-if='#{hasTrinkets}') .pull-right span.inventory_special_trinket.inline-gems b x{{user.purchased.plan.consecutive.trinkets}} p!=env.t('timeTravelersPopover', {linkStart: "", linkEnd: ""}) + .row: .col-md-7 + .alert.alert-info(ng-if='hasAllTimeTravelerItems()')=env.t('timeTravelersAlreadyOwned') + .row: .col-md-12 li.customize-menu.inventory-gear menu.pets-menu(label='{{::set.text}}', ng-repeat='set in Content.timeTravelerStore(user.items.gear.owned)') diff --git a/website/views/shared/footer.jade b/website/views/shared/footer.jade index 2e81898d9c..06bfb26e7c 100644 --- a/website/views/shared/footer.jade +++ b/website/views/shared/footer.jade @@ -80,7 +80,8 @@ footer.footer(ng-controller='FooterCtrl') a.btn.btn-default(ng-click='addMissedDay(1)') +1 Missed Day a.btn.btn-default(ng-click='addMissedDay(2)') +2 Missed Days a.btn.btn-default(ng-click='addTenGems()') +10 Gems - a.btn.btn-default(ng-click='addGold()') +GP + a.btn.btn-default(ng-click='addHourglass()') +1 Mystic Hourglass + a.btn.btn-default(ng-click='addGold()') +500GP a.btn.btn-default(ng-click='addMana()') +MP a.btn.btn-default(ng-click='addLevelsAndGold()') +Exp +GP +MP a.btn.btn-default(ng-click='addOneLevel()') +1 Level