Mercurial > hg > thermostat-ng > web-client
changeset 167:9726d75909c1
Add basic auth to web-gateway requests when not using Keycloak
Renamed and adapter StubAuth to BasicAuth
Reviewed-by: jkang
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-August/024667.html
author | Andrew Azores <aazores@redhat.com> |
---|---|
date | Wed, 23 Aug 2017 17:21:40 -0400 |
parents | 1c97d42f787f |
children | becd239128c2 |
files | mock-api/mockapi.server.js src/app/auth-interceptor.factory.js src/app/auth-interceptor.factory.spec.js src/app/components/auth/auth.module.js src/app/components/auth/auth.routing.js src/app/components/auth/basic-auth.controller.js src/app/components/auth/basic-auth.controller.spec.js src/app/components/auth/basic-auth.service.js src/app/components/auth/basic-auth.service.spec.js src/app/components/auth/keycloak-auth.service.js src/app/components/auth/keycloak-auth.service.spec.js src/app/components/auth/stub-auth.controller.js src/app/components/auth/stub-auth.controller.spec.js src/app/components/auth/stub-auth.service.js src/app/components/auth/stub-auth.service.spec.js |
diffstat | 15 files changed, 387 insertions(+), 369 deletions(-) [+] |
line wrap: on
line diff
--- a/mock-api/mockapi.server.js Wed Aug 23 10:12:01 2017 -0400 +++ b/mock-api/mockapi.server.js Wed Aug 23 17:21:40 2017 -0400 @@ -26,6 +26,7 @@ console.info('[' + svc + '] requested'); console.info('params: ' + JSON.stringify(req.params)); console.info('query: ' + JSON.stringify(req.query)); + console.info('authorization:' + JSON.stringify(req.headers.authorization)); console.info('~~~~\n'); } };
--- a/src/app/auth-interceptor.factory.js Wed Aug 23 10:12:01 2017 -0400 +++ b/src/app/auth-interceptor.factory.js Wed Aug 23 17:21:40 2017 -0400 @@ -37,11 +37,11 @@ request: config => { var defer = $q.defer(); - if (authService.token) { + if (authService.authHeader) { authService.refresh() .success(() => { config.headers = config.headers || {}; - config.headers.Authorization = 'Bearer ' + authService.token; + config.headers.Authorization = authService.authHeader; defer.resolve(config); }) .error(() => {
--- a/src/app/auth-interceptor.factory.spec.js Wed Aug 23 10:12:01 2017 -0400 +++ b/src/app/auth-interceptor.factory.spec.js Wed Aug 23 17:21:40 2017 -0400 @@ -44,7 +44,7 @@ success: refreshSuccess, error: refreshError }), - token: 'fakeToken' + authHeader: 'Basic foo64' }; $provide.value('authService', authSvc); }); @@ -74,21 +74,21 @@ fn = interceptor.request; }); - it('should refresh authService when token exists', () => { + it('should refresh authService when authHeader exists', () => { authSvc.refresh.should.not.be.called(); fn(); authSvc.refresh.should.be.calledOnce(); }); - it('should append header if token refresh succeeds', () => { + it('should append header if refresh succeeds', () => { let cfg = {}; fn(cfg); authSvc.refreshSuccess.should.be.calledWith(sinon.match.func); authSvc.refreshSuccess.yield(); - cfg.should.deepEqual({ headers: { Authorization: 'Bearer fakeToken'} }); + cfg.should.deepEqual({ headers: { Authorization: 'Basic foo64'} }); }); - it('should do nothing if token refresh fails', () => { + it('should do nothing if refresh fails', () => { let cfg = {}; fn(cfg); authSvc.refreshError.should.be.calledWith(sinon.match.func); @@ -96,8 +96,8 @@ cfg.should.deepEqual({}); }); - it('should do nothing if token does not exist', () => { - delete authSvc.token; + it('should do nothing if authHeader does not exist', () => { + delete authSvc.authHeader; let cfg = {}; fn(cfg); authSvc.refresh.should.not.be.called();
--- a/src/app/components/auth/auth.module.js Wed Aug 23 10:12:01 2017 -0400 +++ b/src/app/components/auth/auth.module.js Wed Aug 23 17:21:40 2017 -0400 @@ -28,9 +28,9 @@ import Keycloak from 'keycloak-js/dist/keycloak.js'; import KeycloakAuthService from './keycloak-auth.service.js'; -import StubAuthService from './stub-auth.service.js'; +import BasicAuthService from './basic-auth.service.js'; import LoginController from './login.controller.js'; -import StubAuthController from './stub-auth.controller.js'; +import BasicAuthController from './basic-auth.controller.js'; let MOD_NAME = 'authModule'; export default MOD_NAME; @@ -52,7 +52,7 @@ mod.constant('AUTH_MODULE', MOD_NAME); mod.controller('LoginController', LoginController); - mod.controller('StubAuthController', StubAuthController); + mod.controller('BasicAuthController', BasicAuthController); if (env === 'production') { let cloak = keycloakProvider(); @@ -63,7 +63,7 @@ .success(done) .error(() => window.location.reload()); } else { - mod.service('authService', StubAuthService); + mod.service('authService', BasicAuthService); done(); } }
--- a/src/app/components/auth/auth.routing.js Wed Aug 23 10:12:01 2017 -0400 +++ b/src/app/components/auth/auth.routing.js Wed Aug 23 17:21:40 2017 -0400 @@ -33,7 +33,7 @@ $stateProvider .state('/', { url:'/', - controller: 'StubAuthController' + controller: 'BasicAuthController' }) .state('login', { url: '/login',
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/app/components/auth/basic-auth.controller.js Wed Aug 23 17:21:40 2017 -0400 @@ -0,0 +1,44 @@ +/** + * Copyright 2012-2017 Red Hat, Inc. + * + * Thermostat is distributed under the GNU General Public License, + * version 2 or any later version (with a special exception described + * below, commonly known as the "Classpath Exception"). + * + * A copy of GNU General Public License (GPL) is included in this + * distribution, in the file COPYING. + * + * Linking Thermostat code with other modules is making a combined work + * based on Thermostat. Thus, the terms and conditions of the GPL + * cover the whole combination. + * + * As a special exception, the copyright holders of Thermostat give you + * permission to link this code with independent modules to produce an + * executable, regardless of the license terms of these independent + * modules, and to copy and distribute the resulting executable under + * terms of your choice, provided that you also meet, for each linked + * independent module, the terms and conditions of the license of that + * module. An independent module is a module which is not derived from + * or based on Thermostat code. If you modify Thermostat, you may + * extend this exception to your version of the software, but you are + * not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +export default class BasicAuthController { + + constructor ($scope, $state, authService) { + 'ngInject'; + + if (authService.status()) { + $state.go('landing'); + } else { + $state.go('login'); + } + + $scope.login = () => { + authService.login($scope.username, $scope.password, () => $state.go('landing'), () => alert('Login failed')); + }; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/app/components/auth/basic-auth.controller.spec.js Wed Aug 23 17:21:40 2017 -0400 @@ -0,0 +1,104 @@ +/** + * Copyright 2012-2017 Red Hat, Inc. + * + * Thermostat is distributed under the GNU General Public License, + * version 2 or any later version (with a special exception described + * below, commonly known as the "Classpath Exception"). + * + * A copy of GNU General Public License (GPL) is included in this + * distribution, in the file COPYING. + * + * Linking Thermostat code with other modules is making a combined work + * based on Thermostat. Thus, the terms and conditions of the GPL + * cover the whole combination. + * + * As a special exception, the copyright holders of Thermostat give you + * permission to link this code with independent modules to produce an + * executable, regardless of the license terms of these independent + * modules, and to copy and distribute the resulting executable under + * terms of your choice, provided that you also meet, for each linked + * independent module, the terms and conditions of the license of that + * module. An independent module is a module which is not derived from + * or based on Thermostat code. If you modify Thermostat, you may + * extend this exception to your version of the software, but you are + * not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +describe('BasicAuthController', () => { + beforeEach(angular.mock.module($provide => { + 'ngInject'; + $provide.value('$transitions', { onBefore: angular.noop }); + })); + + beforeEach(angular.mock.module('appModule')); + + describe('$scope.login()', () => { + let scope, authStatus, authLogin, stateGo, alert; + beforeEach(inject(($controller, $rootScope, authService) => { + 'ngInject'; + scope = $rootScope.$new(); + authStatus = sinon.stub(authService, 'status').returns(false); + authLogin = sinon.stub(authService, 'login'); + stateGo = sinon.spy(); + alert = sinon.spy(window, 'alert'); + + $controller('BasicAuthController', { + $scope: scope, + $state: { go: stateGo }, + authService: authService + }); + })); + + afterEach(() => { + authStatus.restore(); + authLogin.restore(); + alert.restore(); + }); + + it('should perform a login', () => { + authLogin.should.not.be.called(); + stateGo.should.be.calledOnce(); + + scope.login(); + + authLogin.should.be.calledOnce(); + let fn = authLogin.args[0][2]; + should.exist(fn); + fn.should.be.a.Function(); + authLogin.yield(); + stateGo.should.be.calledWith('landing'); + }); + + it('should present an alert on failed login', () => { + authLogin.callsArg(3); + scope.login(); + alert.should.be.calledWith('Login failed'); + }); + }); + + describe('when logged in', () => { + let scope, authStatus, stateGo; + beforeEach(inject(($controller, $rootScope, authService) => { + 'ngInject'; + scope = $rootScope.$new(); + authStatus = sinon.stub(authService, 'status').returns(true); + stateGo = sinon.spy(); + + $controller('BasicAuthController', { + $scope: scope, + $state: { go: stateGo }, + authService: authService + }); + })); + + afterEach(() => { + authStatus.restore(); + }); + + it('should redirect to landing if already logged in', () => { + authStatus.should.be.calledOnce(); + stateGo.should.be.calledWith('landing'); + }); + }); +});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/app/components/auth/basic-auth.service.js Wed Aug 23 17:21:40 2017 -0400 @@ -0,0 +1,78 @@ +/** + * Copyright 2012-2017 Red Hat, Inc. + * + * Thermostat is distributed under the GNU General Public License, + * version 2 or any later version (with a special exception described + * below, commonly known as the "Classpath Exception"). + * + * A copy of GNU General Public License (GPL) is included in this + * distribution, in the file COPYING. + * + * Linking Thermostat code with other modules is making a combined work + * based on Thermostat. Thus, the terms and conditions of the GPL + * cover the whole combination. + * + * As a special exception, the copyright holders of Thermostat give you + * permission to link this code with independent modules to produce an + * executable, regardless of the license terms of these independent + * modules, and to copy and distribute the resulting executable under + * terms of your choice, provided that you also meet, for each linked + * independent module, the terms and conditions of the license of that + * module. An independent module is a module which is not derived from + * or based on Thermostat code. If you modify Thermostat, you may + * extend this exception to your version of the software, but you are + * not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +export default class BasicAuthService { + + constructor ($state) { + 'ngInject'; + this.$state = $state; + this.state = false; + + this._user = null; + this._pass = null; + } + + status () { + return this.state; + } + + login (user, pass, success = angular.noop) { + this._user = user; + this._pass = pass; + this.state = true; + success(); + } + + logout (callback = angular.noop) { + this._user = null; + this._pass = null; + this.state = false; + this.$state.go('login'); + callback(); + } + + refresh () { + return { + success: function (fn) { + fn(); + return this; + }, + error: function () { + return this; + } + }; + } + + get authHeader () { + return 'Basic ' + btoa(this._user + ':' + this._pass); + } + + get username () { + return this._user; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/app/components/auth/basic-auth.service.spec.js Wed Aug 23 17:21:40 2017 -0400 @@ -0,0 +1,139 @@ +/** + * Copyright 2012-2017 Red Hat, Inc. + * + * Thermostat is distributed under the GNU General Public License, + * version 2 or any later version (with a special exception described + * below, commonly known as the "Classpath Exception"). + * + * A copy of GNU General Public License (GPL) is included in this + * distribution, in the file COPYING. + * + * Linking Thermostat code with other modules is making a combined work + * based on Thermostat. Thus, the terms and conditions of the GPL + * cover the whole combination. + * + * As a special exception, the copyright holders of Thermostat give you + * permission to link this code with independent modules to produce an + * executable, regardless of the license terms of these independent + * modules, and to copy and distribute the resulting executable under + * terms of your choice, provided that you also meet, for each linked + * independent module, the terms and conditions of the license of that + * module. An independent module is a module which is not derived from + * or based on Thermostat code. If you modify Thermostat, you may + * extend this exception to your version of the software, but you are + * not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +// AuthServices are set up before Angular is bootstrapped, so we manually import rather than +// using Angular DI +import BasicAuthService from './basic-auth.service.js'; + +describe('BasicAuthService', () => { + let basicAuthService, state; + beforeEach(() => { + state = { go: sinon.spy() }; + basicAuthService = new BasicAuthService(state); + }); + + it('should be initially logged out', () => { + basicAuthService.status().should.equal(false); + }); + + describe('#login()', () => { + it('should set logged in status on successful login', done => { + basicAuthService.login('client', 'client-pwd', () => { + basicAuthService.status().should.equal(true); + done(); + }); + }); + + it('should set username on successful login', done => { + should(basicAuthService.username).be.null(); + basicAuthService.login('client', 'client-pwd', () => { + basicAuthService.username.should.equal('client'); + done(); + }); + }); + }); + + describe('#logout()', () => { + it('should set logged out status', done => { + basicAuthService.login('client', 'client-pwd'); + basicAuthService.status().should.equal(true); + basicAuthService.logout(() => { + basicAuthService.status().should.equal(false); + done(); + }); + }); + + it('should call callback if provided', done => { + basicAuthService.logout(done); + }); + + it('should not require callback', () => { + basicAuthService.logout(); + }); + + it('should redirect to login', done => { + let callCount = state.go.callCount; + basicAuthService.logout(() => { + state.go.callCount.should.equal(callCount + 1); + done(); + }); + }); + }); + + describe('#refresh()', () => { + it('should return an object', () => { + let res = basicAuthService.refresh(); + should.exist(res); + res.should.be.an.Object(); + }); + + it('should return an object with a success callback handler', () => { + let res = basicAuthService.refresh(); + res.should.have.ownProperty('success'); + res.success.should.be.a.Function(); + }); + + it('should return an object with an error callback handler', () => { + let res = basicAuthService.refresh(); + res.should.have.ownProperty('error'); + res.error.should.be.a.Function(); + }); + + it('should call success callbacks', done => { + basicAuthService.refresh().success(done); + }); + + it('should not call error callbacks', done => { + basicAuthService.refresh().error(() => { + done('should not reach here'); + }); + done(); + }); + }); + + describe('#get authHeader()', () => { + it('should return base64-encoded credentials', done => { + basicAuthService.login('foo', 'bar', () => { + basicAuthService.authHeader.should.equal('Basic ' + btoa('foo:bar')); + done(); + }); + }); + }); + + describe('#get username()', () => { + it('should be null before login', () => { + should(basicAuthService.username).be.null(); + }); + + it('should return logged in user', done => { + basicAuthService.login('foo', 'bar', () => { + basicAuthService.username.should.equal('foo'); + done(); + }); + }); + }); +});
--- a/src/app/components/auth/keycloak-auth.service.js Wed Aug 23 10:12:01 2017 -0400 +++ b/src/app/components/auth/keycloak-auth.service.js Wed Aug 23 17:21:40 2017 -0400 @@ -49,8 +49,8 @@ return this.keycloak.updateToken(300); } - get token () { - return this.keycloak.token; + get authHeader () { + return 'Bearer ' + this.keycloak.token; } get username () {
--- a/src/app/components/auth/keycloak-auth.service.spec.js Wed Aug 23 10:12:01 2017 -0400 +++ b/src/app/components/auth/keycloak-auth.service.spec.js Wed Aug 23 17:21:40 2017 -0400 @@ -45,7 +45,7 @@ authenticated: authenticated, token: 'fakeToken', idTokenParsed: { - 'preferred_username': 'fakeUsername' + 'preferred_username': 'client' } }; keycloakAuthService = new KeycloakAuthService(mockCloak); @@ -88,16 +88,15 @@ }); }); - describe('#get token()', () => { - it('should delegate to Keycloak object', () => { - let res = keycloakAuthService.token; - res.should.equal('fakeToken'); + describe('#get authHeader()', () => { + it('should return "Bearer fakeToken"', () => { + keycloakAuthService.authHeader.should.equal('Bearer fakeToken'); }); }); describe('#get username()', () => { it('should delegate to Keycloak object', () => { - keycloakAuthService.username.should.equal('fakeUsername'); + keycloakAuthService.username.should.equal('client'); }); }); });
--- a/src/app/components/auth/stub-auth.controller.js Wed Aug 23 10:12:01 2017 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/** - * Copyright 2012-2017 Red Hat, Inc. - * - * Thermostat is distributed under the GNU General Public License, - * version 2 or any later version (with a special exception described - * below, commonly known as the "Classpath Exception"). - * - * A copy of GNU General Public License (GPL) is included in this - * distribution, in the file COPYING. - * - * Linking Thermostat code with other modules is making a combined work - * based on Thermostat. Thus, the terms and conditions of the GPL - * cover the whole combination. - * - * As a special exception, the copyright holders of Thermostat give you - * permission to link this code with independent modules to produce an - * executable, regardless of the license terms of these independent - * modules, and to copy and distribute the resulting executable under - * terms of your choice, provided that you also meet, for each linked - * independent module, the terms and conditions of the license of that - * module. An independent module is a module which is not derived from - * or based on Thermostat code. If you modify Thermostat, you may - * extend this exception to your version of the software, but you are - * not obligated to do so. If you do not wish to do so, delete this - * exception statement from your version. - */ - -export default class AuthController { - - constructor ($scope, $state, authService) { - 'ngInject'; - - if (authService.status()) { - $state.go('landing'); - } else { - $state.go('login'); - } - - $scope.login = () => { - authService.login($scope.username, $scope.password, () => $state.go('landing'), () => alert('Login failed')); - }; - } - -}
--- a/src/app/components/auth/stub-auth.controller.spec.js Wed Aug 23 10:12:01 2017 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -/** - * Copyright 2012-2017 Red Hat, Inc. - * - * Thermostat is distributed under the GNU General Public License, - * version 2 or any later version (with a special exception described - * below, commonly known as the "Classpath Exception"). - * - * A copy of GNU General Public License (GPL) is included in this - * distribution, in the file COPYING. - * - * Linking Thermostat code with other modules is making a combined work - * based on Thermostat. Thus, the terms and conditions of the GPL - * cover the whole combination. - * - * As a special exception, the copyright holders of Thermostat give you - * permission to link this code with independent modules to produce an - * executable, regardless of the license terms of these independent - * modules, and to copy and distribute the resulting executable under - * terms of your choice, provided that you also meet, for each linked - * independent module, the terms and conditions of the license of that - * module. An independent module is a module which is not derived from - * or based on Thermostat code. If you modify Thermostat, you may - * extend this exception to your version of the software, but you are - * not obligated to do so. If you do not wish to do so, delete this - * exception statement from your version. - */ - -describe('AuthController', () => { - beforeEach(angular.mock.module($provide => { - 'ngInject'; - $provide.value('$transitions', { onBefore: angular.noop }); - })); - - beforeEach(angular.mock.module('appModule')); - - describe('$scope.login()', () => { - let scope, authStatus, authLogin, stateGo, alert; - beforeEach(inject(($controller, $rootScope, authService) => { - 'ngInject'; - scope = $rootScope.$new(); - authStatus = sinon.stub(authService, 'status').returns(false); - authLogin = sinon.stub(authService, 'login'); - stateGo = sinon.spy(); - alert = sinon.spy(window, 'alert'); - - $controller('StubAuthController', { - $scope: scope, - $state: { go: stateGo }, - authService: authService - }); - })); - - afterEach(() => { - authStatus.restore(); - authLogin.restore(); - alert.restore(); - }); - - it('should perform a login', () => { - authLogin.should.not.be.called(); - stateGo.should.be.calledOnce(); - - scope.login(); - - authLogin.should.be.calledOnce(); - let fn = authLogin.args[0][2]; - should.exist(fn); - fn.should.be.a.Function(); - authLogin.yield(); - stateGo.should.be.calledWith('landing'); - }); - - it('should present an alert on failed login', () => { - authLogin.callsArg(3); - scope.login(); - alert.should.be.calledWith('Login failed'); - }); - }); - - describe('when logged in', () => { - let scope, authStatus, stateGo; - beforeEach(inject(($controller, $rootScope, authService) => { - 'ngInject'; - scope = $rootScope.$new(); - authStatus = sinon.stub(authService, 'status').returns(true); - stateGo = sinon.spy(); - - $controller('StubAuthController', { - $scope: scope, - $state: { go: stateGo }, - authService: authService - }); - })); - - it('should redirect to landing if already logged in', () => { - authStatus.should.be.calledOnce(); - stateGo.should.be.calledWith('landing'); - }); - }); -});
--- a/src/app/components/auth/stub-auth.service.js Wed Aug 23 10:12:01 2017 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/** - * Copyright 2012-2017 Red Hat, Inc. - * - * Thermostat is distributed under the GNU General Public License, - * version 2 or any later version (with a special exception described - * below, commonly known as the "Classpath Exception"). - * - * A copy of GNU General Public License (GPL) is included in this - * distribution, in the file COPYING. - * - * Linking Thermostat code with other modules is making a combined work - * based on Thermostat. Thus, the terms and conditions of the GPL - * cover the whole combination. - * - * As a special exception, the copyright holders of Thermostat give you - * permission to link this code with independent modules to produce an - * executable, regardless of the license terms of these independent - * modules, and to copy and distribute the resulting executable under - * terms of your choice, provided that you also meet, for each linked - * independent module, the terms and conditions of the license of that - * module. An independent module is a module which is not derived from - * or based on Thermostat code. If you modify Thermostat, you may - * extend this exception to your version of the software, but you are - * not obligated to do so. If you do not wish to do so, delete this - * exception statement from your version. - */ - -export default class StubAuthService { - - constructor ($state) { - 'ngInject'; - this.$state = $state; - this.state = false; - } - - status () { - return this.state; - } - - login (user, pass, success = angular.noop, failure = angular.noop) { - if (user === 'test-user' && pass === 'test-pass') { - this.state = true; - success(); - } else { - this.logout(failure); - } - } - - logout (callback = angular.noop) { - this.state = false; - this.$state.go('login'); - callback(); - } - - refresh () { - return { - success: function (fn) { - fn(); - return this; - }, - error: function () { - return this; - } - }; - } - - get token () { - return 'stubAuthMockToken'; - } - - get username () { - return 'test-user'; - } - -}
--- a/src/app/components/auth/stub-auth.service.spec.js Wed Aug 23 10:12:01 2017 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -/** - * Copyright 2012-2017 Red Hat, Inc. - * - * Thermostat is distributed under the GNU General Public License, - * version 2 or any later version (with a special exception described - * below, commonly known as the "Classpath Exception"). - * - * A copy of GNU General Public License (GPL) is included in this - * distribution, in the file COPYING. - * - * Linking Thermostat code with other modules is making a combined work - * based on Thermostat. Thus, the terms and conditions of the GPL - * cover the whole combination. - * - * As a special exception, the copyright holders of Thermostat give you - * permission to link this code with independent modules to produce an - * executable, regardless of the license terms of these independent - * modules, and to copy and distribute the resulting executable under - * terms of your choice, provided that you also meet, for each linked - * independent module, the terms and conditions of the license of that - * module. An independent module is a module which is not derived from - * or based on Thermostat code. If you modify Thermostat, you may - * extend this exception to your version of the software, but you are - * not obligated to do so. If you do not wish to do so, delete this - * exception statement from your version. - */ - -// AuthServices are set up before Angular is bootstrapped, so we manually import rather than -// using Angular DI -import StubAuthService from './stub-auth.service.js'; - -describe('StubAuthService', () => { - let stubAuthService, state; - beforeEach(() => { - state = { go: sinon.spy() }; - stubAuthService = new StubAuthService(state); - }); - - it('should be initially logged out', () => { - stubAuthService.status().should.equal(false); - }); - - describe('#login()', () => { - it('should set logged in status on successful login', done => { - stubAuthService.login('test-user', 'test-pass', () => { - stubAuthService.status().should.equal(true); - done(); - }); - }); - - it('should not set logged in status on failed login', done => { - stubAuthService.login('', '', () => done('unexpected login success'), () => { - stubAuthService.status().should.equal(false); - done(); - }); - }); - }); - - describe('#logout()', () => { - it('should set logged out status', done => { - stubAuthService.login('test-user', 'test-pass'); - stubAuthService.status().should.equal(true); - stubAuthService.logout(() => { - stubAuthService.status().should.equal(false); - done(); - }); - }); - - it('should call callback if provided', done => { - stubAuthService.logout(done); - }); - - it('should not require callback', () => { - stubAuthService.logout(); - }); - - it('should redirect to login', done => { - let callCount = state.go.callCount; - stubAuthService.logout(() => { - state.go.callCount.should.equal(callCount + 1); - done(); - }); - }); - }); - - describe('#refresh()', () => { - it('should return an object', () => { - let res = stubAuthService.refresh(); - should.exist(res); - res.should.be.an.Object(); - }); - - it('should return an object with a success callback handler', () => { - let res = stubAuthService.refresh(); - res.should.have.ownProperty('success'); - res.success.should.be.a.Function(); - }); - - it('should return an object with an error callback handler', () => { - let res = stubAuthService.refresh(); - res.should.have.ownProperty('error'); - res.error.should.be.a.Function(); - }); - - it('should call success callbacks', done => { - stubAuthService.refresh().success(done); - }); - - it('should not call error callbacks', done => { - stubAuthService.refresh().error(() => { - done('should not reach here'); - }); - done(); - }); - }); - - describe('#get token()', () => { - it('should return stubAuthMockToken', () => { - stubAuthService.token.should.equal('stubAuthMockToken'); - }); - }); - - describe('#get username()', () => { - it('should return "test-user"', () => { - stubAuthService.username.should.equal('test-user'); - }); - }); -});