Commit 11e809f7 authored by Randall Leeds's avatar Randall Leeds

Eliminate the explicit account module

Angular is smart enough to not instantiate the application until all
pending scripts have been loaded. That means that we can load optional
components by simply appending the script tags. We already load the
account component after the app component. By having the account
component attach its controllers and configuration functions to the
existing 'h' module, rather than defining a new angular module, the
app can avoid having a dependency on 'h.account'. This removes the
requirement that integrators define this module. Instead, they can
just attach a configuration function to the main module if they need
to configure the identity provider.

I have a mild preference for this pattern, since strictly speaking no
account module needs to be present. With a little morke tweaking, the
interface could be made to not have a sign in link and operate in an
anonymous mode by default, assuming that the server requires no
authorization to annotate.
parent 90c39fef
...@@ -87,5 +87,5 @@ class AccountController ...@@ -87,5 +87,5 @@ class AccountController
angular.module('h.account') angular.module('h')
.controller('AccountController', AccountController) .controller('AccountController', AccountController)
imports = [
'ngRoute'
'h.identity'
'h.helpers'
'h.session'
]
AUTH_SESSION_ACTIONS = [ AUTH_SESSION_ACTIONS = [
'login' 'login'
'logout' 'logout'
...@@ -126,6 +119,7 @@ configure = [ ...@@ -126,6 +119,7 @@ configure = [
] ]
angular.module('h.account', imports, configure) angular.module('h')
.config(configure)
.controller('AuthAppController', AuthAppController) .controller('AuthAppController', AuthAppController)
.controller('AuthPageController', AuthPageController) .controller('AuthPageController', AuthPageController)
...@@ -53,5 +53,5 @@ class AuthController ...@@ -53,5 +53,5 @@ class AuthController
, 300000 , 300000
angular.module('h.account') angular.module('h')
.controller('AuthController', AuthController) .controller('AuthController', AuthController)
...@@ -3,7 +3,6 @@ imports = [ ...@@ -3,7 +3,6 @@ imports = [
'ngRoute' 'ngRoute'
'ngSanitize' 'ngSanitize'
'ngTagsInput' 'ngTagsInput'
'h.account'
'h.helpers' 'h.helpers'
'h.identity' 'h.identity'
'h.session' 'h.session'
......
...@@ -2,7 +2,7 @@ assert = chai.assert ...@@ -2,7 +2,7 @@ assert = chai.assert
sinon.assert.expose assert, prefix: null sinon.assert.expose assert, prefix: null
sandbox = sinon.sandbox.create() sandbox = sinon.sandbox.create()
describe 'h.account.AccountController', -> describe 'AccountController', ->
$scope = null $scope = null
fakeFlash = null fakeFlash = null
fakeSession = null fakeSession = null
...@@ -14,7 +14,7 @@ describe 'h.account.AccountController', -> ...@@ -14,7 +14,7 @@ describe 'h.account.AccountController', ->
profilePromise = null profilePromise = null
createController = null createController = null
beforeEach module('h.account') beforeEach module('h')
beforeEach module ($provide, $filterProvider) -> beforeEach module ($provide, $filterProvider) ->
fakeSession = {} fakeSession = {}
......
...@@ -19,8 +19,13 @@ class MockSession ...@@ -19,8 +19,13 @@ class MockSession
mockFlash = sandbox.spy() mockFlash = sandbox.spy()
mockFormHelpers = applyValidationErrors: sandbox.spy() mockFormHelpers = applyValidationErrors: sandbox.spy()
describe 'h.account', -> describe 'AuthController', ->
beforeEach module('h.account') $scope = null
$timeout = null
auth = null
session = null
beforeEach module('h')
beforeEach module('h.templates') beforeEach module('h.templates')
beforeEach module ($provide) -> beforeEach module ($provide) ->
...@@ -30,95 +35,89 @@ describe 'h.account', -> ...@@ -30,95 +35,89 @@ describe 'h.account', ->
$provide.value 'formHelpers', mockFormHelpers $provide.value 'formHelpers', mockFormHelpers
return return
beforeEach inject ($controller, $rootScope, _$timeout_, _session_) ->
$scope = $rootScope.$new()
$timeout = _$timeout_
auth = $controller 'AuthController', {$scope}
session = _session_
sandbox.spy session, 'login'
afterEach -> afterEach ->
sandbox.restore() sandbox.restore()
describe 'AuthController', -> describe '#submit()', ->
$scope = null it 'should call session methods on submit', ->
$timeout = null
auth = null
session = null
beforeEach inject ($controller, $rootScope, _$timeout_, _session_) ->
$scope = $rootScope.$new()
$timeout = _$timeout_
auth = $controller 'AuthController', {$scope}
session = _session_
sandbox.spy session, 'login'
describe '#submit()', ->
it 'should call session methods on submit', ->
auth.submit
$name: 'login'
$valid: true
$setValidity: sandbox.stub()
assert.called session.login
it 'should do nothing when the form is invalid', -> auth.submit
auth.submit $name: 'login'
$name: 'login' $valid: true
$valid: false $setValidity: sandbox.stub()
$setValidity: sandbox.stub()
assert.notCalled session.login
it 'should apply validation errors on submit', -> assert.called session.login
form =
$name: 'register'
$valid: true
$setValidity: sandbox.stub()
username:
$setValidity: sandbox.stub()
email:
$setValidity: sandbox.stub()
auth.submit(form) it 'should do nothing when the form is invalid', ->
auth.submit
$name: 'login'
$valid: false
$setValidity: sandbox.stub()
assert.calledWith mockFormHelpers.applyValidationErrors, form, assert.notCalled session.login
{username: 'taken'},
'registration error'
it 'should emit an auth event once authenticated', -> it 'should apply validation errors on submit', ->
form = form =
$name: 'login' $name: 'register'
$valid: true $valid: true
$setValidity: sandbox.stub()
username:
$setValidity: sandbox.stub()
email:
$setValidity: sandbox.stub() $setValidity: sandbox.stub()
sandbox.spy $scope, '$emit' auth.submit(form)
auth.submit(form) assert.calledWith mockFormHelpers.applyValidationErrors, form,
assert.calledWith $scope.$emit, 'auth', null, userid: 'alice' {username: 'taken'},
'registration error'
it 'should emit an auth event if destroyed before authentication', ->
sandbox.spy $scope, '$emit' it 'should emit an auth event once authenticated', ->
$scope.$destroy() form =
assert.calledWith $scope.$emit, 'auth', 'cancel' $name: 'login'
$valid: true
describe 'timeout', -> $setValidity: sandbox.stub()
it 'should happen after a period of inactivity', ->
sandbox.spy $scope, '$broadcast' sandbox.spy $scope, '$emit'
$scope.form = $setPristine: sandbox.stub()
$scope.model = auth.submit(form)
username: 'test' assert.calledWith $scope.$emit, 'auth', null, userid: 'alice'
email: 'test@example.com'
password: 'secret' it 'should emit an auth event if destroyed before authentication', ->
code: '1234' sandbox.spy $scope, '$emit'
$scope.$destroy()
$scope.$digest() assert.calledWith $scope.$emit, 'auth', 'cancel'
assert.called $timeout
describe 'timeout', ->
$timeout.lastCall.args[0]() it 'should happen after a period of inactivity', ->
assert.called $scope.form.$setPristine, 'the form is pristine' sandbox.spy $scope, '$broadcast'
assert.deepEqual $scope.model, {}, 'the model is erased' $scope.form = $setPristine: sandbox.stub()
assert.called mockFlash, 'a notification is flashed' $scope.model =
username: 'test'
it 'should not happen if the model is empty', -> email: 'test@example.com'
$scope.model = undefined password: 'secret'
$scope.$digest() code: '1234'
assert.notCalled $timeout
$scope.$digest()
$scope.model = {} assert.called $timeout
$scope.$digest()
assert.notCalled $timeout $timeout.lastCall.args[0]()
assert.called $scope.form.$setPristine, 'the form is pristine'
assert.deepEqual $scope.model, {}, 'the model is erased'
assert.called mockFlash, 'a notification is flashed'
it 'should not happen if the model is empty', ->
$scope.model = undefined
$scope.$digest()
assert.notCalled $timeout
$scope.model = {}
$scope.$digest()
assert.notCalled $timeout
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment