2013-03-05 133 views
74

此自定义验证指令是在官方角度网站上提供的示例。 http://docs.angularjs.org/guide/forms 它检查文本输入是否是数字格式。测试自定义验证angularjs指令

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

进行单元测试的代码,我写了这个:

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

然后我得到这个错误:

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

我把打印语句随处可见,看看是怎么回事,和它看起来像指令永远不会被调用。 什么是测试像这样的简单指令的正确方法?

+0

感谢您花时间带回答案!只是FYI,你可以提取你的答案,并将其标记为后来搜索者接受的答案 - 在这里可以接受;-) – 2013-06-25 01:05:58

+0

谢谢你的提示。我提出了我的答案。 – ghiden 2013-07-06 07:54:22

回答

80

对方回答的测试应该被写入。这将表单设置为“脏”状态,否则它将保持“原始状态”,这可能不是你想要的。

+0

非常感谢,今天帮了我很多! 但我直接使用范围模型而不是'$ setViewValue()',我不知道我是否错过了很多情况......? – 2016-06-16 12:56:59

67

我想通了阅读角的应用程序代码https://github.com/angular-app/angular-app 此视频也有助于太http://youtu.be/ZhfUv0spHCY?t=31m17s我犯

两个错误:

  • 当你正在做NG不要直接绑定到范围-model
  • 使用表单控制器直接操作该怎么传递的指令

这里是更新的版本。该指令是相同的,只是我改变了的测试。

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

注意$scope.$digest()现在$setViewValue后调用:作为

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

谢谢你,这节省了我一天;) – luacassus 2013-07-15 10:47:22

+0

@ghiden这真的帮了我,但是,你有任何经验的链接多个指令和测试?就像你是否为电话或电子邮件发出指令一样?任何时候我都会遇到一堆错误,并添加一个额外的指令。思考? – thescientist 2013-09-05 00:20:59

+0

链接多个指令?我猜即使你对一个元素应用了多个指令,你仍然想单独测试它们,对吗?如果每一个工作正常,优先级设置正确,我想他们应该工作。我有时会先做模型验证之类的事情,然后以非常低的优先级继续使用视觉效果指令。 – ghiden 2013-09-05 09:15:27

2

测试我的自定义指令在对象物搜索“$错误”的自定义验证的名称。例如:

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

我希望我能帮助你!