Para testar uma diretiva de validação angularjs personalizada

Essa diretiva de validação personalizada é um exemplo apresentado no site oficial angular. http://docs.angularjs.org/guide/forms Verifica se uma input de texto está em formato numérico ou não.

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; } }); } }; }); 

Para testar esse código, eu escrevi o seguinte:

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

Então eu recebo este erro:

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

Eu coloco instruções de impressão em todos os lugares para ver o que está acontecendo, e parece que a diretiva nunca é chamada. Qual é a maneira correta de testar uma diretiva simples como essa?

Os testes da outra resposta devem ser escritos como:

 describe('directives', function() { var $scope, form; beforeEach(module('exampleDirective')); beforeEach(inject(function($compile, $rootScope) { $scope = $rootScope; var element = angular.element( '
' + '' + '
' ); $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); }); }); });

Observe que $scope.$digest() agora é invocado após $setViewValue . Isso define o formulário em estado “sujo”, caso contrário, ele permaneceria “intocado”, o que provavelmente não é o que você deseja.

Eu descobri lendo código de aplicativo angular https://github.com/angular-app/angular-app Este vídeo também ajuda muito http://youtu.be/ZhfUv0spHCY?t=31m17s

Dois erros que cometi:

  • Não ligue diretamente ao escopo quando estiver fazendo o ng-model
  • Use o controlador de formulário para manipular diretamente o que passar por diretivas

Aqui está a versão atualizada. A diretiva é a mesma, apenas o teste que eu mudei.

 describe('directives', function() { var $scope, form; beforeEach(module('exampleDirective')); beforeEach(inject(function($compile, $rootScope) { $scope = $rootScope; var element = angular.element( '
' + '' + '
' ); $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); }); }); });

Eu testo minhas diretivas personalizadas procurando no object “$ error” o nome da validação personalizada. Exemplo:

  'use strict'; describe('Directive: validadorCorreo', function () { // load the directive's module beforeEach(module('sistemaRegistroProCivilApp')); var inputCorreo, formulario, elementoFormulario, scope, $compile; beforeEach(inject(function ($rootScope, _$compile_) { scope = $rootScope.$new(); $compile = _$compile_; elementoFormulario = angular.element('
' + '' + '

Espero que eu possa te ajudar!