diff --git a/common/locales/en/front.json b/common/locales/en/front.json index 0b36eaca97..186ec48753 100644 --- a/common/locales/en/front.json +++ b/common/locales/en/front.json @@ -165,8 +165,12 @@ "teams": "Teams", "terms": "Terms and Conditions", "testimonialHeading": "What people say...", - "tryFirst": "If you are experiencing problems with Habitica, click the button below to clear cookies and local storage for this website (other websites will not be affected). You will need to log in again after doing this, so first be sure that you know your log-in details, which can be found at Settings -> <%= linkStart %>Site<%= linkEnd %>.", - "tryNext": "If the problem persists, please <%= linkStart %>Report a Bug<%= linkEnd %> if you haven't already.", + "localStorageTryFirst": "If you are experiencing problems with Habitica, click the button below to clear cookies and local storage for this website (other websites will not be affected). You will need to log in again after doing this, so first be sure that you know your log-in details, which can be found at Settings -> <%= linkStart %>Site<%= linkEnd %>.", + "localStorageTryNext": "If the problem persists, please <%= linkStart %>Report a Bug<%= linkEnd %> if you haven't already.", + "localStorageClearing": "Clearing Local Storage", + "localStorageClearingExplanation": "Your browser's local storage is being cleared. You will be logged out and redirected to the home page. Please wait.", + "localStorageClear": "Clear Local Storage", + "localStorageClearExplanation": "This button will clear local storage and log you out", "tutorials": "Tutorials", "unlockByline1": "Achieve your goals and level up.", "unlockByline2": "Unlock new motivational tools, such as pet collecting, random rewards, spell-casting, and more!", diff --git a/test/spec/controllers/authCtrlSpec.js b/test/spec/controllers/authCtrlSpec.js index 6ca5c5d11c..86090758a7 100644 --- a/test/spec/controllers/authCtrlSpec.js +++ b/test/spec/controllers/authCtrlSpec.js @@ -1,7 +1,7 @@ 'use strict'; describe('Auth Controller', function() { - var scope, ctrl, user, $httpBackend, $window; + var scope, ctrl, user, $httpBackend, $window, $modal; beforeEach(function(){ module(function($provide) { @@ -9,12 +9,13 @@ describe('Auth Controller', function() { $provide.value('Chat', { seenMessage: function() {} }); }); - inject(function(_$httpBackend_, $rootScope, $controller) { + inject(function(_$httpBackend_, $rootScope, $controller, _$modal_) { $httpBackend = _$httpBackend_; scope = $rootScope.$new(); scope.loginUsername = 'user'; scope.loginPassword = 'pass'; $window = { location: { href: ""}, alert: sandbox.spy() }; + $modal = _$modal_; user = { user: {}, authenticate: sandbox.spy() }; ctrl = $controller('AuthCtrl', {$scope: scope, $window: $window, User: user}); @@ -39,4 +40,82 @@ describe('Auth Controller', function() { expect($window.alert).to.be.calledOnce; }); }); + + describe.only('#clearLocalStorage', function () { + var timer; + + beforeEach(function () { + timer = sandbox.useFakeTimers(); + sandbox.stub($modal, 'open'); + }); + + it('opens modal with message about clearing local storage and logging out', function () { + scope.clearLocalStorage(); + + expect($modal.open).to.be.calledOnce; + expect($modal.open).to.be.calledWith({ + templateUrl: 'modals/message-modal.html', + scope: scope + }); + + expect(scope.messageModal.title).to.eql(window.env.t('localStorageClearing')); + expect(scope.messageModal.body).to.eql(window.env.t('localStorageClearingExplanation')); + }); + + it('does not call $scope.logout before 3 seconds', function () { + sandbox.stub(scope, 'logout'); + + scope.clearLocalStorage(); + + timer.tick(2999); + + expect(scope.logout).to.not.be.called; + }); + + it('calls $scope.logout after 3 seconds', function () { + sandbox.stub(scope, 'logout'); + + scope.clearLocalStorage(); + + timer.tick(3000); + + expect(scope.logout).to.be.calledOnce; + }); + + it('does not clear local storage before 3 seconds', function () { + sandbox.stub(localStorage, 'clear'); + + scope.clearLocalStorage(); + + timer.tick(2999); + + expect(localStorage.clear).to.not.be.called; + }); + + it('clears local storage after 3 seconds', function () { + sandbox.stub(localStorage, 'clear'); + + scope.clearLocalStorage(); + + timer.tick(3000); + + expect(localStorage.clear).to.be.calledOnce; + }); + + it('does not redirect to /logout route before 3 seconds', function () { + scope.clearLocalStorage(); + + timer.tick(2999); + + expect($window.location.href).to.eql(''); + }); + + it('redirects to /logout after 3 seconds', function () { + scope.clearLocalStorage(); + + timer.tick(3000); + + expect($window.location.href).to.eql('/logout'); + }); + }); }); diff --git a/website/public/js/controllers/authCtrl.js b/website/public/js/controllers/authCtrl.js index 7dced7ce00..5b486677f5 100644 --- a/website/public/js/controllers/authCtrl.js +++ b/website/public/js/controllers/authCtrl.js @@ -11,7 +11,7 @@ angular.module('habitrpg') $scope.logout = function() { localStorage.clear(); - window.location.href = '/logout'; + $window.location.href = '/logout'; }; var runAuth = function(id, token) { @@ -105,6 +105,23 @@ angular.module('habitrpg') }, function( e ){ alert("Signin error: " + e.error.message ); }); - } + }; + + $scope.clearLocalStorage = function () { + $scope.messageModal = { + title: window.env.t('localStorageClearing'), + body: window.env.t('localStorageClearingExplanation'), + noFooter: true, + }; + + $modal.open({ + templateUrl: 'modals/message-modal.html', + scope: $scope + }); + + var threeSecondsForUsersToReadClearLocalStorageMessage = 3000; + + setTimeout($scope.logout, threeSecondsForUsersToReadClearLocalStorageMessage); + }; } ]); diff --git a/website/views/static/clear-browser-data.jade b/website/views/static/clear-browser-data.jade index ebc5ec11da..68e7daa434 100644 --- a/website/views/static/clear-browser-data.jade +++ b/website/views/static/clear-browser-data.jade @@ -14,9 +14,11 @@ block content .page-header h1=env.t('clearBrowserData') - p!=env.t('tryFirst', {linkStart: "", linkEnd: ""}) + p!=env.t('localStorageTryFirst', {linkStart: "", linkEnd: ""}) br p.text-center - button.btn.btn-lg.btn-danger(onclick='localStorage.clear()') Clear local storage + button.btn.btn-lg.btn-danger(ng-click='clearLocalStorage()', + popover-trigger='mouseover', popover=env.t('localStorageClearExplanation')) + =env.t('localStorageClear') br - p!=env.t('tryNext', {linkStart: "", linkEnd: ""}) + p!=env.t('localStorageTryNext', {linkStart: "", linkEnd: ""})