| @@ -1 +1,9 @@ | ||
| angular = require('angular') | ||
| angular.module('h.helpers', ['bootstrap']) | ||
| require('./form-helpers') | ||
| require('./string-helpers') | ||
| require('./time-helpers') | ||
| require('./ui-helpers') | ||
| require('./xsrf-service') |
| @@ -1 +1,5 @@ | ||
| angular = require('angular') | ||
| angular.module('h.session', ['ngResource', 'h.helpers']) | ||
| require('./session-service') |
| @@ -1,73 +1,78 @@ | ||
| {module, inject} = require('angular-mock') | ||
| assert = chai.assert | ||
| describe 'h.directives', -> | ||
| $scope = null | ||
| describe 'h:directives.simple-search', -> | ||
| $compile = null | ||
| $element = null | ||
| $scope = null | ||
| fakeWindow = null | ||
| isolate = null | ||
| before -> | ||
| angular.module('h', []) | ||
| require('../../../h/static/scripts/directives/simple-search') | ||
| beforeEach module('h') | ||
| beforeEach inject (_$compile_, _$rootScope_) -> | ||
| $compile = _$compile_ | ||
| $scope = _$rootScope_.$new() | ||
| describe '.simpleSearch', -> | ||
| $element = null | ||
| beforeEach -> | ||
| $scope.update = sinon.spy() | ||
| $scope.clear = sinon.spy() | ||
| template= ''' | ||
| <div class="simpleSearch" | ||
| query="query" | ||
| on-search="update(query)" | ||
| on-clear="clear()"> | ||
| </div> | ||
| ''' | ||
| $element = $compile(angular.element(template))($scope) | ||
| $scope.$digest() | ||
| isolate = $element.isolateScope() | ||
| it 'updates the search-bar', -> | ||
| $scope.query = "Test query" | ||
| $scope.$digest() | ||
| assert.equal(isolate.searchtext, $scope.query) | ||
| it 'calls the given search function', -> | ||
| isolate.searchtext = "Test query" | ||
| isolate.$digest() | ||
| $element.find('form').triggerHandler('submit') | ||
| sinon.assert.calledWith($scope.update, "Test query") | ||
| it 'calls the given clear function', -> | ||
| $element.find('.simple-search-clear').click() | ||
| assert($scope.clear.called) | ||
| it 'clears the search-bar', -> | ||
| isolate.query = '' | ||
| isolate.$digest() | ||
| isolate.searchtext = "Test query" | ||
| isolate.$digest() | ||
| $element.find('.simple-search-clear').click() | ||
| assert.equal(isolate.searchtext, '') | ||
| it 'invokes callbacks when the input model changes', -> | ||
| $scope.query = "Test query" | ||
| $scope.$digest() | ||
| sinon.assert.calledOnce($scope.update) | ||
| $scope.query = "" | ||
| $scope.$digest() | ||
| sinon.assert.calledOnce($scope.clear) | ||
| it 'adds a class to the form when there is no input value', -> | ||
| $form = $element.find('.simple-search-form') | ||
| assert.include($form.prop('className'), 'simple-search-inactive') | ||
| it 'removes the class from the form when there is an input value', -> | ||
| $scope.query = "Test query" | ||
| $scope.$digest() | ||
| $form = $element.find('.simple-search-form') | ||
| assert.notInclude($form.prop('className'), 'simple-search-inactive') | ||
| $scope.update = sinon.spy() | ||
| $scope.clear = sinon.spy() | ||
| template= ''' | ||
| <div class="simpleSearch" | ||
| query="query" | ||
| on-search="update(query)" | ||
| on-clear="clear()"> | ||
| </div> | ||
| ''' | ||
| $element = $compile(angular.element(template))($scope) | ||
| $scope.$digest() | ||
| isolate = $element.isolateScope() | ||
| it 'updates the search-bar', -> | ||
| $scope.query = "Test query" | ||
| $scope.$digest() | ||
| assert.equal(isolate.searchtext, $scope.query) | ||
| it 'calls the given search function', -> | ||
| isolate.searchtext = "Test query" | ||
| isolate.$digest() | ||
| $element.find('form').triggerHandler('submit') | ||
| sinon.assert.calledWith($scope.update, "Test query") | ||
| it 'calls the given clear function', -> | ||
| $element.find('.simple-search-clear').click() | ||
| assert($scope.clear.called) | ||
| it 'clears the search-bar', -> | ||
| isolate.query = '' | ||
| isolate.$digest() | ||
| isolate.searchtext = "Test query" | ||
| isolate.$digest() | ||
| $element.find('.simple-search-clear').click() | ||
| assert.equal(isolate.searchtext, '') | ||
| it 'invokes callbacks when the input model changes', -> | ||
| $scope.query = "Test query" | ||
| $scope.$digest() | ||
| sinon.assert.calledOnce($scope.update) | ||
| $scope.query = "" | ||
| $scope.$digest() | ||
| sinon.assert.calledOnce($scope.clear) | ||
| it 'adds a class to the form when there is no input value', -> | ||
| $form = $element.find('.simple-search-form') | ||
| assert.include($form.prop('className'), 'simple-search-inactive') | ||
| it 'removes the class from the form when there is an input value', -> | ||
| $scope.query = "Test query" | ||
| $scope.$digest() | ||
| $form = $element.find('.simple-search-form') | ||
| assert.notInclude($form.prop('className'), 'simple-search-inactive') |
| @@ -1,155 +1,167 @@ | ||
| {module, inject} = require('angular-mock') | ||
| assert = chai.assert | ||
| sinon.assert.expose assert, prefix: null | ||
| describe 'h.directives.thread.ThreadController', -> | ||
| $scope = null | ||
| createController = null | ||
| beforeEach module('h') | ||
| beforeEach inject ($controller, $rootScope) -> | ||
| $scope = $rootScope.$new() | ||
| createController = -> | ||
| controller = $controller 'ThreadController' | ||
| controller | ||
| describe '#toggleCollapsed', -> | ||
| it 'sets the collapsed property', -> | ||
| controller = createController() | ||
| before = controller.collapsed | ||
| controller.toggleCollapsed() | ||
| after = controller.collapsed | ||
| assert.equal(before, !after) | ||
| describe '#shouldShowReply', -> | ||
| count = null | ||
| controller = null | ||
| beforeEach -> | ||
| controller = createController() | ||
| count = sinon.stub() | ||
| describe 'when root', -> | ||
| beforeEach -> controller.isRoot = true | ||
| describe 'and when not filtered', -> | ||
| it 'shows the reply if the thread is not collapsed and has children', -> | ||
| count.withArgs('message').returns(1) | ||
| assert.isTrue(controller.shouldShowReply(count, false)) | ||
| it 'does not show the reply if the thread is not collapsed and has no children', -> | ||
| count.withArgs('message').returns(0) | ||
| assert.isFalse(controller.shouldShowReply(count, false)) | ||
| it 'shows the reply if the thread is collapsed and has children', -> | ||
| count.withArgs('message').returns(1) | ||
| controller.collapsed = true | ||
| assert.isTrue(controller.shouldShowReply(count, false)) | ||
| it 'does not show the reply if the thread is collapsed and has no children', -> | ||
| count.withArgs('message').returns(0) | ||
| controller.collapsed = true | ||
| assert.isFalse(controller.shouldShowReply(count, false)) | ||
| describe 'and when filtered with children', -> | ||
| it 'shows the reply if the thread is not collapsed', -> | ||
| count.withArgs('match').returns(1) | ||
| count.withArgs('message').returns(1) | ||
| assert.isTrue(controller.shouldShowReply(count, true)) | ||
| it 'does not show the reply if the thread is not collapsed and the message count does not match the match count', -> | ||
| count.withArgs('match').returns(0) | ||
| count.withArgs('message').returns(1) | ||
| assert.isFalse(controller.shouldShowReply(count, true)) | ||
| describe 'when reply', -> | ||
| beforeEach -> controller.isRoot = false | ||
| describe 'and when not filtered', -> | ||
| it 'shows the reply if the thread is not collapsed and has children', -> | ||
| count.withArgs('message').returns(1) | ||
| assert.isTrue(controller.shouldShowReply(count, false)) | ||
| it 'does not show the reply if the thread is not collapsed and has no children', -> | ||
| count.withArgs('message').returns(0) | ||
| assert.isFalse(controller.shouldShowReply(count, false)) | ||
| it 'does not show the reply if the thread is collapsed and has children', -> | ||
| count.withArgs('message').returns(1) | ||
| controller.collapsed = true | ||
| assert.isFalse(controller.shouldShowReply(count, false)) | ||
| it 'does not show the reply if the thread is collapsed and has no children', -> | ||
| count.withArgs('message').returns(0) | ||
| controller.collapsed = true | ||
| assert.isFalse(controller.shouldShowReply(count, false)) | ||
| describe 'and when filtered with children', -> | ||
| it 'shows the reply if the thread is not collapsed', -> | ||
| count.withArgs('match').returns(1) | ||
| count.withArgs('message').returns(1) | ||
| assert.isTrue(controller.shouldShowReply(count, true)) | ||
| it 'does not show the reply if the thread is not collapsed and the message count does not match the match count', -> | ||
| count.withArgs('match').returns(0) | ||
| count.withArgs('message').returns(1) | ||
| assert.isFalse(controller.shouldShowReply(count, true)) | ||
| describe 'h.directives.thread.thread', -> | ||
| createElement = null | ||
| $element = null | ||
| $isolateScope = null | ||
| fakePulse = null | ||
| describe 'h:directives.thread', -> | ||
| fakeRender = null | ||
| sandbox = null | ||
| before -> | ||
| angular.module('h', []) | ||
| require('../../../h/static/scripts/directives/thread') | ||
| beforeEach module('h') | ||
| beforeEach module ($provide) -> | ||
| sandbox = sinon.sandbox.create() | ||
| fakePulse = sandbox.spy() | ||
| $provide.value 'pulse', fakePulse | ||
| fakeRender = sandbox.spy() | ||
| $provide.value 'render', fakeRender | ||
| return | ||
| beforeEach inject ($compile, $rootScope) -> | ||
| createElement = (html) -> $compile(html or '<div thread></div>')($rootScope.$new()) | ||
| $element = createElement() | ||
| $isolateScope = $element.scope() | ||
| afterEach -> | ||
| sandbox.restore() | ||
| it 'sets the threadRoot on the controller to false', -> | ||
| controller = $element.controller('thread') | ||
| assert.isFalse(controller.isRoot) | ||
| it 'sets the threadRoot on the controller to true when the thread-root attr is set', -> | ||
| $element = createElement('<div thread thread-root="true"></div>') | ||
| controller = $element.controller('thread') | ||
| assert.isTrue(controller.isRoot) | ||
| it 'pulses the current thread on an annotationUpdated event', -> | ||
| $element.scope().$emit('annotationUpdate') | ||
| assert.called(fakePulse) | ||
| it 'does not pulse the thread if it is hidden (parent collapsed)', -> | ||
| fakeParent = { | ||
| controller: -> {collapsed: true} | ||
| } | ||
| sandbox.stub(angular.element.prototype, 'parent').returns(fakeParent) | ||
| $element.scope().$emit('annotationUpdate') | ||
| assert.notCalled(fakePulse) | ||
| it 'does not pulse the thread if it is hidden (grandparent collapsed)', -> | ||
| fakeGrandParent = { | ||
| controller: -> {collapsed: true} | ||
| } | ||
| fakeParent = { | ||
| controller: -> {collapsed: false} | ||
| parent: -> fakeGrandParent | ||
| } | ||
| sandbox.stub(angular.element.prototype, 'parent').returns(fakeParent) | ||
| $element.scope().$emit('annotationUpdate') | ||
| assert.notCalled(fakePulse) | ||
| describe '.ThreadController', -> | ||
| $scope = null | ||
| createController = null | ||
| beforeEach inject ($controller, $rootScope) -> | ||
| $scope = $rootScope.$new() | ||
| createController = -> | ||
| controller = $controller 'ThreadController' | ||
| controller | ||
| describe '#toggleCollapsed', -> | ||
| it 'sets the collapsed property', -> | ||
| controller = createController() | ||
| before = controller.collapsed | ||
| controller.toggleCollapsed() | ||
| after = controller.collapsed | ||
| assert.equal(before, !after) | ||
| describe '#shouldShowReply', -> | ||
| count = null | ||
| controller = null | ||
| beforeEach -> | ||
| controller = createController() | ||
| count = sinon.stub() | ||
| describe 'when root', -> | ||
| beforeEach -> controller.isRoot = true | ||
| describe 'and when not filtered', -> | ||
| it 'shows the reply if the thread is not collapsed and has children', -> | ||
| count.withArgs('message').returns(1) | ||
| assert.isTrue(controller.shouldShowReply(count, false)) | ||
| it 'does not show the reply if the thread is not collapsed and has no children', -> | ||
| count.withArgs('message').returns(0) | ||
| assert.isFalse(controller.shouldShowReply(count, false)) | ||
| it 'shows the reply if the thread is collapsed and has children', -> | ||
| count.withArgs('message').returns(1) | ||
| controller.collapsed = true | ||
| assert.isTrue(controller.shouldShowReply(count, false)) | ||
| it 'does not show the reply if the thread is collapsed and has no children', -> | ||
| count.withArgs('message').returns(0) | ||
| controller.collapsed = true | ||
| assert.isFalse(controller.shouldShowReply(count, false)) | ||
| describe 'and when filtered with children', -> | ||
| it 'shows the reply if the thread is not collapsed', -> | ||
| count.withArgs('match').returns(1) | ||
| count.withArgs('message').returns(1) | ||
| assert.isTrue(controller.shouldShowReply(count, true)) | ||
| it 'does not show the reply if the thread is not collapsed and the message count does not match the match count', -> | ||
| count.withArgs('match').returns(0) | ||
| count.withArgs('message').returns(1) | ||
| assert.isFalse(controller.shouldShowReply(count, true)) | ||
| describe 'when reply', -> | ||
| beforeEach -> controller.isRoot = false | ||
| describe 'and when not filtered', -> | ||
| it 'shows the reply if the thread is not collapsed and has children', -> | ||
| count.withArgs('message').returns(1) | ||
| assert.isTrue(controller.shouldShowReply(count, false)) | ||
| it 'does not show the reply if the thread is not collapsed and has no children', -> | ||
| count.withArgs('message').returns(0) | ||
| assert.isFalse(controller.shouldShowReply(count, false)) | ||
| it 'does not show the reply if the thread is collapsed and has children', -> | ||
| count.withArgs('message').returns(1) | ||
| controller.collapsed = true | ||
| assert.isFalse(controller.shouldShowReply(count, false)) | ||
| it 'does not show the reply if the thread is collapsed and has no children', -> | ||
| count.withArgs('message').returns(0) | ||
| controller.collapsed = true | ||
| assert.isFalse(controller.shouldShowReply(count, false)) | ||
| describe 'and when filtered with children', -> | ||
| it 'shows the reply if the thread is not collapsed', -> | ||
| count.withArgs('match').returns(1) | ||
| count.withArgs('message').returns(1) | ||
| assert.isTrue(controller.shouldShowReply(count, true)) | ||
| it 'does not show the reply if the thread is not collapsed and the message count does not match the match count', -> | ||
| count.withArgs('match').returns(0) | ||
| count.withArgs('message').returns(1) | ||
| assert.isFalse(controller.shouldShowReply(count, true)) | ||
| describe '.thread', -> | ||
| createElement = null | ||
| $element = null | ||
| $isolateScope = null | ||
| fakePulse = null | ||
| beforeEach module ($provide) -> | ||
| fakePulse = sandbox.spy() | ||
| $provide.value 'pulse', fakePulse | ||
| return | ||
| beforeEach inject ($compile, $rootScope) -> | ||
| createElement = (html) -> $compile(html or '<div thread></div>')($rootScope.$new()) | ||
| $element = createElement() | ||
| $isolateScope = $element.scope() | ||
| it 'sets the threadRoot on the controller to false', -> | ||
| controller = $element.controller('thread') | ||
| assert.isFalse(controller.isRoot) | ||
| it 'sets the threadRoot on the controller to true when the thread-root attr is set', -> | ||
| $element = createElement('<div thread thread-root="true"></div>') | ||
| controller = $element.controller('thread') | ||
| assert.isTrue(controller.isRoot) | ||
| it 'pulses the current thread on an annotationUpdated event', -> | ||
| $element.scope().$emit('annotationUpdate') | ||
| assert.called(fakePulse) | ||
| it 'does not pulse the thread if it is hidden (parent collapsed)', -> | ||
| fakeParent = { | ||
| controller: -> {collapsed: true} | ||
| } | ||
| sandbox.stub(angular.element.prototype, 'parent').returns(fakeParent) | ||
| $element.scope().$emit('annotationUpdate') | ||
| assert.notCalled(fakePulse) | ||
| it 'does not pulse the thread if it is hidden (grandparent collapsed)', -> | ||
| fakeGrandParent = { | ||
| controller: -> {collapsed: true} | ||
| } | ||
| fakeParent = { | ||
| controller: -> {collapsed: false} | ||
| parent: -> fakeGrandParent | ||
| } | ||
| sandbox.stub(angular.element.prototype, 'parent').returns(fakeParent) | ||
| $element.scope().$emit('annotationUpdate') | ||
| assert.notCalled(fakePulse) |
| @@ -1,38 +1,46 @@ | ||
| {module, inject} = require('angular-mock') | ||
| assert = chai.assert | ||
| sinon.assert.expose assert, prefix: null | ||
| describe 'persona', -> | ||
| filter = null | ||
| term = 'acct:hacker@example.com' | ||
| describe 'h:filters', -> | ||
| before -> | ||
| angular.module('h', []) | ||
| require('../../h/static/scripts/filters') | ||
| describe 'persona', -> | ||
| filter = null | ||
| term = 'acct:hacker@example.com' | ||
| beforeEach module('h') | ||
| beforeEach inject ($filter) -> | ||
| filter = $filter('persona') | ||
| beforeEach module('h') | ||
| beforeEach inject ($filter) -> | ||
| filter = $filter('persona') | ||
| it 'should return the whole term by request', -> | ||
| result = filter('acct:hacker@example.com', 'term') | ||
| assert.equal result, 'acct:hacker@example.com' | ||
| it 'should return the whole term by request', -> | ||
| result = filter('acct:hacker@example.com', 'term') | ||
| assert.equal result, 'acct:hacker@example.com' | ||
| it 'should return the requested part', -> | ||
| assert.equal filter(term), 'hacker' | ||
| assert.equal filter(term, 'term'), term, | ||
| assert.equal filter(term, 'username'), 'hacker' | ||
| assert.equal filter(term, 'provider'), 'example.com' | ||
| it 'should return the requested part', -> | ||
| assert.equal filter(term), 'hacker' | ||
| assert.equal filter(term, 'term'), term, | ||
| assert.equal filter(term, 'username'), 'hacker' | ||
| assert.equal filter(term, 'provider'), 'example.com' | ||
| it 'should pass through unrecognized terms as username or term', -> | ||
| assert.equal filter('bogus'), 'bogus' | ||
| assert.equal filter('bogus', 'username'), 'bogus' | ||
| it 'should pass through unrecognized terms as username or term', -> | ||
| assert.equal filter('bogus'), 'bogus' | ||
| assert.equal filter('bogus', 'username'), 'bogus' | ||
| it 'should handle error cases', -> | ||
| assert.notOk filter() | ||
| assert.notOk filter('bogus', 'provider') | ||
| it 'should handle error cases', -> | ||
| assert.notOk filter() | ||
| assert.notOk filter('bogus', 'provider') | ||
| describe 'urlencode', -> | ||
| filter = null | ||
| describe 'urlencode', -> | ||
| filter = null | ||
| beforeEach module('h') | ||
| beforeEach inject ($filter) -> | ||
| filter = $filter('urlencode') | ||
| beforeEach module('h') | ||
| beforeEach inject ($filter) -> | ||
| filter = $filter('urlencode') | ||
| it 'encodes reserved characters in the term', -> | ||
| assert.equal(filter('#hello world'), '%23hello%20world') | ||
| it 'encodes reserved characters in the term', -> | ||
| assert.equal(filter('#hello world'), '%23hello%20world') |
| @@ -0,0 +1,156 @@ | ||
| {module, inject} = require('angular-mock') | ||
| assert = chai.assert | ||
| angular = require('angular') | ||
| describe 'h.helpers:form-helpers', -> | ||
| $compile = null | ||
| $scope = null | ||
| formHelpers = null | ||
| before -> | ||
| angular.module('h.helpers', []) | ||
| require('../../../h/static/scripts/helpers/form-helpers') | ||
| beforeEach module('h.helpers') | ||
| beforeEach inject (_$compile_, _$rootScope_, _formHelpers_) -> | ||
| $compile = _$compile_ | ||
| $scope = _$rootScope_.$new() | ||
| formHelpers = _formHelpers_ | ||
| describe '.formValidate', -> | ||
| $element = null | ||
| beforeEach -> | ||
| $scope.model = {username: undefined} | ||
| template = ''' | ||
| <form form-validate name="login" onsubmit="return false"> | ||
| <div class="form-field"> | ||
| <input type="text" class="form-input" name="username" | ||
| ng-model="model.username" name="username" | ||
| required ng-minlength="3" /> | ||
| </div> | ||
| </form> | ||
| ''' | ||
| $element = $compile(angular.element(template))($scope) | ||
| $scope.$digest() | ||
| it 'should remove an error class to an valid field on change', -> | ||
| $field = $element.find('.form-field').addClass('form-field-error') | ||
| $input = $element.find('[name=username]').addClass('form-field-error') | ||
| $input.controller('ngModel').$setViewValue('abc') | ||
| $scope.$digest() | ||
| assert.notInclude($field.prop('className'), 'form-field-error') | ||
| assert.notInclude($input.prop('className'), 'form-field-error') | ||
| it 'should apply an error class to an invalid field on submit', -> | ||
| $field = $element.find('.form-field') | ||
| $element.triggerHandler('submit') | ||
| assert.include($field.prop('className'), 'form-field-error') | ||
| it 'should remove an error class from a valid field on submit', -> | ||
| $field = $element.find('.form-field').addClass('form-field-error') | ||
| $input = $element.find('[name=username]') | ||
| $input.val('abc').triggerHandler('input') | ||
| $element.triggerHandler('submit') | ||
| assert.notInclude($field.prop('className'), 'form-field-error') | ||
| it 'should apply an error class if the form recieves errors after a submit action', -> | ||
| $element.trigger('submit') | ||
| $element.controller('form').username.$setValidity('response', false) | ||
| $field = $element.find('.form-field') | ||
| assert.include $field.prop('className'), 'form-field-error' | ||
| it 'should remove an error class on valid input when the view model changes', -> | ||
| $field = $element.find('.form-field').addClass('form-field-error') | ||
| $input = $element.find('[name=username]') | ||
| $input.val('abc').triggerHandler('input') | ||
| assert.notInclude($field.prop('className'), 'form-field-error') | ||
| it 'should not add an error class on invalid input on when the view changes', -> | ||
| $field = $element.find('.form-field') | ||
| $input = $element.find('[name=username]') | ||
| $input.val('ab').triggerHandler('input') | ||
| assert.notInclude($field.prop('className'), 'form-field-error') | ||
| it 'should reset the "response" error when the view changes', -> | ||
| $field = $element.find('.form-field') | ||
| $input = $element.find('[name=username]') | ||
| controller = $input.controller('ngModel') | ||
| controller.$setViewValue('abc') | ||
| # Submit Event | ||
| $element.triggerHandler('submit') | ||
| controller.$setValidity('response', false) | ||
| controller.responseErrorMessage = 'fail' | ||
| $scope.$digest() | ||
| assert.include($field.prop('className'), 'form-field-error', 'Fail fast check') | ||
| controller.$setViewValue('abc') | ||
| $scope.$digest() | ||
| assert.notInclude($field.prop('className'), 'form-field-error') | ||
| it 'should hide errors if the model is marked as pristine', -> | ||
| $field = $element.find('.form-field').addClass('form-field-error') | ||
| $input = $element.find('[name=username]') | ||
| controller = $input.controller('ngModel') | ||
| # Submit Event | ||
| $element.triggerHandler('submit') | ||
| controller.$setValidity('response', false) | ||
| controller.responseErrorMessage = 'fail' | ||
| $scope.$digest() | ||
| assert.include($field.prop('className'), 'form-field-error', 'Fail fast check') | ||
| # Then clear it out and mark it as pristine | ||
| controller.$setPristine() | ||
| $scope.$digest() | ||
| assert.notInclude($field.prop('className'), 'form-field-error') | ||
| describe '.applyValidationErrors', -> | ||
| form = null | ||
| beforeEach -> | ||
| form = | ||
| $setValidity: sinon.spy() | ||
| username: {$setValidity: sinon.spy()} | ||
| password: {$setValidity: sinon.spy()} | ||
| it 'sets the "response" error key for each field with errors', -> | ||
| formHelpers.applyValidationErrors form, | ||
| username: 'must be at least 3 characters' | ||
| password: 'must be present' | ||
| assert.calledWith(form.username.$setValidity, 'response', false) | ||
| assert.calledWith(form.password.$setValidity, 'response', false) | ||
| it 'adds an error message to each input controller', -> | ||
| formHelpers.applyValidationErrors form, | ||
| username: 'must be at least 3 characters' | ||
| password: 'must be present' | ||
| assert.equal(form.username.responseErrorMessage, 'must be at least 3 characters') | ||
| assert.equal(form.password.responseErrorMessage, 'must be present') | ||
| it 'sets the "response" error key if the form has a failure reason', -> | ||
| formHelpers.applyValidationErrors form, null, 'fail' | ||
| assert.calledWith(form.$setValidity, 'response', false) | ||
| it 'adds an reason message as the response error', -> | ||
| formHelpers.applyValidationErrors form, null, 'fail' | ||
| assert.equal(form.responseErrorMessage, 'fail') |
| @@ -0,0 +1,45 @@ | ||
| #!/usr/bin/env node | ||
| // | ||
| // browserify-pipe | ||
| // | ||
| // A simple browserify commandline that supports CoffeeScript on STDIN. | ||
| // | ||
| // The vanilla browserify commandline tool doesn't deal well with piping input | ||
| // over STDIN: it loses filenames and hence can't deal with non-JavaScript | ||
| // inputs (because it doesn't know the correct file extension). browserify-pipe | ||
| // browserifies a single piped file, using the filename given as a required | ||
| // positional argument. | ||
| // | ||
| var path = require('path'); | ||
| var browserify = require('browserify'); | ||
| var debug = false; | ||
| var args = process.argv.slice(2); | ||
| if (args.indexOf('-d') !== -1) { | ||
| debug = true; | ||
| args.splice(args.indexOf('-d'), 1); | ||
| } | ||
| if (args.length !== 1) { | ||
| console.log('Usage: browserify-pipe [-d] <filename>'); | ||
| process.exit(1); | ||
| } | ||
| var filename = args[0]; | ||
| browserify({ | ||
| debug: debug, | ||
| extensions: ['.coffee'] | ||
| }) | ||
| .require(process.stdin, { | ||
| entry: true, | ||
| basedir: path.dirname(filename), | ||
| file: path.resolve(filename) | ||
| }) | ||
| .bundle() | ||
| .on('error', function (err) { | ||
| console.log(err.stack); | ||
| process.exit(1); | ||
| }) | ||
| .pipe(process.stdout); |