unit test run karma e2e unit-testing angularjs angularjs-directive

unit testing - test - Para probar una directiva de validación angularjs personalizada



unit test angular 6 karma (3)

Esta directiva de validación personalizada es un ejemplo presentado en el sitio angular oficial. http://docs.angularjs.org/guide/forms Comprueba si la entrada de texto está en formato numérico o no.

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 probar la unidad de este código, escribí esto:

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

Entonces obtengo este error:

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

Puse declaraciones de impresión en todas partes para ver qué está sucediendo, y parece que nunca se llama a la directiva. ¿Cuál es la forma correcta de probar una directiva simple como esta?


Las pruebas de la otra respuesta se deben escribir como:

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

Tenga en cuenta que $scope.$digest() ahora se invoca después de $setViewValue . Esto establece la forma en estado "sucio", de lo contrario, se mantendría "prístino", que probablemente no es lo que desea.


Lo descubrí leyendo el código angular de la aplicación https://github.com/angular-app/angular-app Este video también ayuda a http://youtu.be/ZhfUv0spHCY?t=31m17s

Dos errores que cometí:

  • No se vincule directamente al alcance cuando está haciendo ng-model
  • Utilice el controlador de formulario para manipular directamente qué pasar para las directivas

Aquí está la versión actualizada. La directiva es la misma, solo la prueba que cambié.

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


Pruebo mis directivas personalizadas buscando en el objeto "$ error" el nombre de la validación personalizada. Ejemplo:

''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(''<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(''[email protected]'').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(''[email protected]'').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) })); });

¡Espero que yo puedo ayudarle!