Add unit tests

This commit is contained in:
Nicolas Le Goff
2013-02-27 18:39:06 +01:00
committed by Romain Neutron
parent e6418df60e
commit 700324be09
8 changed files with 307 additions and 143 deletions

View File

@@ -71,6 +71,7 @@
<script src="/skins/login/js/bootstrap-switch.js"></script> <script src="/skins/login/js/bootstrap-switch.js"></script>
<script src="/assets/underscore/underscore.js"></script> <script src="/assets/underscore/underscore.js"></script>
<script src="/skins/login/js/main.js"></script> <script src="/skins/login/js/main.js"></script>
<script src="/skins/login/js/angular/app/app.js"></script>
{% endblock header_javascript %} {% endblock header_javascript %}
{% endblock header %} {% endblock header %}
</head> </head>

144
www/skins/login/js/angular/app/app.js vendored Normal file
View File

@@ -0,0 +1,144 @@
// controllers
function LoginFormController($scope) {
$scope.$watch('loginForm', function() {
$scope.loginForm.email.errors = {'filled' : true, 'valid' : true};
$scope.loginForm.password.errors = {'filled' : true, 'valid' : true};
});
$scope.submit = function() {
$scope.$broadcast('event:force-model-update');
if (true === $scope.loginForm.$valid) {
$scope.loginForm.email.errors = {'filled' : true, 'valid' : true};
$scope.loginForm.password.errors = {'filled' : true,'valid' : true};
// submit
return true;
}
$scope.loginForm.email.errors.valid = $scope.loginForm.email.$valid;
$scope.loginForm.email.errors.filled = !$scope.loginForm.email.$error.required;
$scope.loginForm.password.errors.filled = !$scope.loginForm.password.$error.required;
return false;
};
$scope.getInputClass = function(name) {
return _.every($scope.loginForm[name].errors, function(value) {
return value === true;
}) ? '' : 'input-table-error';
};
}
function forgottenPasswordFormCtrl($scope) {
$scope.$watch('forgottenPasswordForm', function() {
$scope.forgottenPasswordForm.email.errors = {'filled' : true, 'valid' : true};
});
$scope.submit = function() {
$scope.$broadcast('event:force-model-update');
if (true === $scope.forgottenPasswordForm.$valid) {
$scope.forgottenPasswordForm.email.errors = {'filled' : true, 'valid' : true};
// submit
return true;
}
$scope.forgottenPasswordForm.email.errors.valid = $scope.forgottenPasswordForm.email.$valid;
$scope.forgottenPasswordForm.email.errors.filled = !$scope.forgottenPasswordForm.email.$error.required;
return false;
};
$scope.getInputClass = function(name) {
return _.every($scope.forgottenPasswordForm[name].errors, function(value) {
return value === true;
}) ? '' : 'input-table-error';
};
}
function passwordChangeFormCtrl($scope) {
$scope.$watch('passwordChangeForm', function() {
$scope.passwordChangeForm.password.errors = {'filled' : true, 'valid' : true};
$scope.passwordChangeForm.passwordConfirm.errors = {'filled' : true, 'valid' : true};
});
$scope.submit = function() {
$scope.$broadcast('event:force-model-update');
if (true === $scope.passwordChangeForm.$valid) {
$scope.passwordChangeForm.password.errors = {'filled' : true, 'valid' : true};
$scope.passwordChangeForm.passwordConfirm.errors = {'filled' : true, 'valid' : true};
// submit
return true;
}
$scope.passwordChangeForm.password.errors.filled = !$scope.passwordChangeForm.password.$error.required;
$scope.passwordChangeForm.passwordConfirm.errors.filled = !$scope.passwordChangeForm.passwordConfirm.$error.required;
return false;
};
$scope.getInputClass = function(name) {
return _.every($scope.passwordChangeForm[name].errors, function(value) {
return value === true;
}) ? '' : 'input-table-error';
};
}
// bootstrap angular
angular.element(document).ready(function() {
angular.bootstrap(document, ['phraseanetAuthentication']);
});
// angular app
angular.module('phraseanetAuthentication', ['ui'])
// force model update for autofill inputs. Yuck.
.directive('forceModelUpdate', function($compile) {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
scope.$on('event:force-model-update', function() {
ctrl.$setViewValue(element.val());
});
}
}
}).directive('alert', function () {
return {
restrict:'EA',
template: [
'<div class="alert" ng-class=\'type && "alert-" + type || "warning"\'>',
'<table><tr>',
'<td class="alert-block-logo"><i class="icon-2x icon-white" ng-class=\'icon || "icon-exclamation-sign"\'></i></td>',
'<td class="alert-block-content" ng-transclude></td>',
'<td class="alert-block-close"><a href="#"><b>&times;</b></a></td>',
'</tr></table>',
'</div>'
].join(''),
transclude:true,
replace:true,
scope:{
type: '@'
},
compile: function (element, attrs, transclude) {
return function (scope, element, attr) {
if (true === 'type' in attrs) {
switch (attrs.type) {
case 'error' :
scope.icon = 'icon-warning-sign';
break;
case 'success' :
scope.icon = 'icon-ok-sign';
break;
case 'info' :
scope.icon = 'icon-info-sign';
break;
}
}
}
}
};
});

View File

@@ -0,0 +1,16 @@
basePath = '../../../../../';
files = [
JASMINE,
JASMINE_ADAPTER,
'assets/angular/angular.js',
'assets/angular-ui/build/angular-ui.js',
'assets/underscore/underscore.js',
'assets/angular-mocks/angular-mocks.js',
'skins/login/js/angular/app/*.js',
'skins/login/js/angular/tests/unit/*.js'
];
autoWatch = true;
browsers = ['firefox'];

View File

@@ -0,0 +1,11 @@
@echo off
REM Windows script for running unit tests
REM You have to run server and capture some browser first
REM
REM Requirements:
REM - NodeJS (http://nodejs.org/)
REM - Testacular (npm install -g testacular)
set BASE_DIR=%~dp0
testacular start "%BASE_DIR%\..\config\testacular.conf.js" %*

View File

@@ -0,0 +1,9 @@
#!/bin/bash
BASE_DIR=`dirname $0`
echo ""
echo "Starting Testacular Server (http://vojtajina.github.com/testacular)"
echo "-------------------------------------------------------------------"
testacular start $BASE_DIR/../config/testacular.conf.js $*

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env watchr
# config file for watchr http://github.com/mynyml/watchr
# install: gem install watchr
# run: watch watchr.rb
# note: make sure that you have jstd server running (server.sh) and a browser captured
log_file = File.expand_path(File.dirname(__FILE__) + '/../logs/jstd.log')
`cd ..`
`touch #{log_file}`
puts "String watchr... log file: #{log_file}"
watch( '(app/js|test/unit)' ) do
`echo "\n\ntest run started @ \`date\`" > #{log_file}`
`scripts/test.sh &> #{log_file}`
end

View File

@@ -0,0 +1,107 @@
'use strict';
describe('LoginFormController', function(){
var scope;
beforeEach(inject(function($rootScope) {
scope = $rootScope.$new();
scope.loginForm = {
email : {
errors:{},
$valid : true,
$error : {
required : false
}
},
password : {
errors:{},
$valid : true,
$error : {
required : false
}
}
};
}));
it('should create model errors with 2 validation for each input', inject(function($controller) {
$controller(LoginFormController, {
$scope: scope
});
scope.$digest();
expect(Object.keys(scope.loginForm.email.errors).length).toEqual(2);
expect(Object.keys(scope.loginForm.password.errors).length).toEqual(2);
}));
it('should return input-table-error class when input is not valid', inject(function($controller) {
scope.loginForm.email.errors.valid = false;
scope.loginForm.password.errors.valid = true;
$controller(LoginFormController, {
$scope: scope
});
expect(scope.getInputClass('password')).toBe('');
expect(scope.getInputClass('email')).toEqual('input-table-error');
}));
it('The valid email input validation should be equal to input form validation if form is submited and not valid', inject(function($controller) {
scope.loginForm.$valid = false;
$controller(LoginFormController, {
$scope: scope
});
scope.$digest();
expect(scope.loginForm.email.errors.valid).toBe(scope.loginForm.email.$valid);
}));
it('The filled password and email input validation should be true if input is not required and form is submited and not valid', inject(function($controller) {
scope.loginForm.$valid = false;
$controller(LoginFormController, {
$scope: scope
});
scope.$digest();
expect(scope.loginForm.email.errors.filled).not.toBe(scope.loginForm.email.$error.required);
expect(scope.loginForm.password.errors.filled).not.toBe(scope.loginForm.password.$error.required);
}));
it('Should reset input validation errors when form is submited and valid', inject(function($controller) {
$controller(LoginFormController, {
$scope: scope
});
scope.$digest();
var startEmailState = _.clone(scope.loginForm.email.errors);
var startPasswordState = _.clone(scope.loginForm.password.errors);
scope.loginForm.$valid = true;
scope.loginForm.email.errors.valid = false;
scope.loginForm.password.errors.valid = false;
scope.submit();
expect(scope.loginForm.email.errors).toEqual(startEmailState);
expect(scope.loginForm.password.errors).toEqual(startPasswordState);
}));
it('should not submit form if it is not valid', inject(function($controller) {
scope.loginForm.$valid = false;
$controller(LoginFormController, {
$scope: scope
});
scope.$digest();
expect(scope.submit()).toBe(false);
}));
});

View File

@@ -6,146 +6,3 @@ $(document).ready(function() {
return false; return false;
}); });
}); });
// angular app
angular.module('phraseanetAuthentication', ['ui'])
// force model update for autofill inputs. Yuck.
.directive('forceModelUpdate', function($compile) {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
scope.$on('event:force-model-update', function() {
ctrl.$setViewValue(element.val());
});
}
}
}).directive('alert', function () {
return {
restrict:'EA',
template: [
'<div class="alert" ng-class=\'type && "alert-" + type || "warning"\'>',
'<table><tr>',
'<td class="alert-block-logo"><i class="icon-2x icon-white" ng-class=\'icon || "icon-exclamation-sign"\'></i></td>',
'<td class="alert-block-content" ng-transclude></td>',
'<td class="alert-block-close"><a href="#"><b>&times;</b></a></td>',
'</tr></table>',
'</div>'
].join(''),
transclude:true,
replace:true,
scope:{
type: '@'
},
compile: function (element, attrs, transclude) {
return function (scope, element, attr) {
if (true === 'type' in attrs) {
switch (attrs.type) {
case 'error' :
scope.icon = 'icon-warning-sign';
break;
case 'success' :
scope.icon = 'icon-ok-sign';
break;
case 'info' :
scope.icon = 'icon-info-sign';
break;
}
}
}
}
};
});
// controllers
function LoginFormController($scope) {
$scope.$watch('loginForm', function() {
$scope.loginForm.email.errors = {'filled' : true, 'valid' : true};
$scope.loginForm.password.errors = {'filled' : true, 'valid' : true};
});
$scope.submit = function() {
$scope.$broadcast('event:force-model-update');
if (true === $scope.loginForm.$valid) {
$scope.loginForm.email.errors = {'filled' : true, 'valid' : true};
$scope.loginForm.password.errors = {'filled' : true,'valid' : true};
// submit
return;
}
$scope.loginForm.email.errors.valid = $scope.loginForm.email.$valid;
$scope.loginForm.email.errors.filled = !$scope.loginForm.email.$error.required;
$scope.loginForm.password.errors.filled = !$scope.loginForm.password.$error.required;
return;
};
$scope.getInputClass = function(name) {
return _.every($scope.loginForm[name].errors, function(value) {
return value === true;
}) ? '' : 'input-table-error';
};
}
function forgottenPasswordFormCtrl($scope) {
$scope.$watch('forgottenPasswordForm', function() {
$scope.forgottenPasswordForm.email.errors = {'filled' : true, 'valid' : true};
});
$scope.submit = function() {
$scope.$broadcast('event:force-model-update');
if (true === $scope.forgottenPasswordForm.$valid) {
$scope.forgottenPasswordForm.email.errors = {'filled' : true, 'valid' : true};
// submit
return;
}
$scope.forgottenPasswordForm.email.errors.valid = $scope.forgottenPasswordForm.email.$valid;
$scope.forgottenPasswordForm.email.errors.filled = !$scope.forgottenPasswordForm.email.$error.required;
return;
};
$scope.getInputClass = function(name) {
return _.every($scope.forgottenPasswordForm[name].errors, function(value) {
return value === true;
}) ? '' : 'input-table-error';
};
}
function passwordChangeFormCtrl($scope) {
$scope.$watch('passwordChangeForm', function() {
$scope.passwordChangeForm.password.errors = {'filled' : true, 'valid' : true};
$scope.passwordChangeForm.passwordConfirm.errors = {'filled' : true, 'valid' : true};
});
$scope.submit = function() {
$scope.$broadcast('event:force-model-update');
if (true === $scope.passwordChangeForm.$valid) {
$scope.passwordChangeForm.password.errors = {'filled' : true, 'valid' : true};
$scope.passwordChangeForm.passwordConfirm.errors = {'filled' : true, 'valid' : true};
// submit
return;
}
$scope.passwordChangeForm.password.errors.filled = !$scope.passwordChangeForm.password.$error.required;
$scope.passwordChangeForm.passwordConfirm.errors.filled = !$scope.passwordChangeForm.passwordConfirm.$error.required;
return;
};
$scope.getInputClass = function(name) {
return _.every($scope.passwordChangeForm[name].errors, function(value) {
return value === true;
}) ? '' : 'input-table-error';
};
}
// bootstrap angular
angular.element(document).ready(function() {
angular.bootstrap(document, ['phraseanetAuthentication']);
});