To check the custom angularjs validation directive

This custom validation directive is an example provided on the official angular website. http://docs.angularjs.org/guide/forms It checks whether text input is in numeric format or not.

var INTEGER_REGEXP = /^\-?\d*$/; app.directive('integer', function() { return { require: 'ngModel', link: function(scope, elm, attrs, ctrl) { ctrl.$parsers.unshift(function(viewValue) { if (INTEGER_REGEXP.test(viewValue)) { // it is valid ctrl.$setValidity('integer', true); return viewValue; } else { // it is invalid, return undefined (no model update) ctrl.$setValidity('integer', false); return undefined; } }); } }; }); 

In unit test this code, I wrote the following:

 describe('directives', function() { beforeEach(module('exampleDirective')); describe('integer', function() { it('should validate an integer', function() { inject(function($compile, $rootScope) { var element = angular.element( '<form name="form">' + '<input ng-model="someNum" name="someNum" integer>' + '</form>' ); $compile(element)($rootScope); $rootScope.$digest(); element.find('input').val(5); expect($rootScope.someNum).toEqual(5); }); }); }); }); 

Then I get this error:

 Expected undefined to equal 5. Error: Expected undefined to equal 5. 

I print print statements everywhere to see what happens, and it looks like the directive is never called. What is the correct way to test a simple directive like this?

+74
angularjs unit-testing angularjs-directive
Mar 05 '13 at 9:07
source share
3 answers

Other response tests should be written as:

 describe('directives', function() { var $scope, form; beforeEach(module('exampleDirective')); beforeEach(inject(function($compile, $rootScope) { $scope = $rootScope; var element = angular.element( '<form name="form">' + '<input ng-model="model.somenum" name="somenum" integer />' + '</form>' ); $scope.model = { somenum: null } $compile(element)($scope); form = $scope.form; })); describe('integer', function() { it('should pass with integer', function() { form.somenum.$setViewValue('3'); $scope.$digest(); expect($scope.model.somenum).toEqual('3'); expect(form.somenum.$valid).toBe(true); }); it('should not pass with string', function() { form.somenum.$setViewValue('a'); $scope.$digest(); expect($scope.model.somenum).toBeUndefined(); expect(form.somenum.$valid).toBe(false); }); }); }); 

Note that $scope.$digest() now called after $setViewValue . This sets the form to a โ€œdirtyโ€ state, otherwise it will remain โ€œuntouchedโ€, which is probably not what you want.

+79
Mar 31 '14 at 21:26
source share

I figured it out by reading angular -app code https://github.com/angular-app/angular-app This video also helps http://youtu.be/ZhfUv0spHCY?t=31m17s

Two mistakes I made:

  • Do not snap directly to scope when you do ng-model
  • Use the form controller to directly control the transfer of directives.

Here is the updated version. The directive is the same, only the tests that I changed.

 describe('directives', function() { var $scope, form; beforeEach(module('exampleDirective')); beforeEach(inject(function($compile, $rootScope) { $scope = $rootScope; var element = angular.element( '<form name="form">' + '<input ng-model="model.somenum" name="somenum" integer />' + '</form>' ); $scope.model = { somenum: null } $compile(element)($scope); $scope.$digest(); form = $scope.form; })); describe('integer', function() { it('should pass with integer', function() { form.somenum.$setViewValue('3'); expect($scope.model.somenum).toEqual('3'); expect(form.somenum.$valid).toBe(true); }); it('should not pass with string', function() { form.somenum.$setViewValue('a'); expect($scope.model.somenum).toBeUndefined(); expect(form.somenum.$valid).toBe(false); }); }); }); 
+67
Jul 6 '13 at 7:52
source share

I am testing my custom directives by looking for the name of the user check in the $ error object. Example:

  'use strict'; describe('Directive: validadorCorreo', function () { // load the directive module beforeEach(module('sistemaRegistroProCivilApp')); var inputCorreo, formulario, elementoFormulario, scope, $compile; beforeEach(inject(function ($rootScope, _$compile_) { scope = $rootScope.$new(); $compile = _$compile_; elementoFormulario = angular.element('<form name="formulario">' + '<input type="text" name="correo" data-ng-model="correo" required data-validador-correo/>' + '</form'); scope.correo = ''; elementoFormulario = $compile(elementoFormulario)(scope); scope.$digest(); inputCorreo = elementoFormulario.find('input'); formulario = scope.formulario; console.log(formulario.correo.$error); })); it('Deberia Validar si un correo ingresado en el input es correcto e incorrecto', inject(function ($compile) { inputCorreo.val('eric+@eric.com').triggerHandler('input'); expect(formulario.correo.$error.email).toBe(true); //Here, the name of the custom validation appears in the $error object. console.log(formulario.correo.$error); inputCorreo.val('eric@eric.com').triggerHandler('input'); expect(formulario.correo.$error.email).toBeUndefined();//Here, the name of the custom validation disappears in the $error object. Is Undefined console.log(formulario.correo.$error.email) })); }); 

Hope I can help you!

+2
Aug 12 '15 at 21:21
source share



All Articles