Unit testing 测试自定义验证angularjs指令的步骤

Unit testing 测试自定义验证angularjs指令的步骤,unit-testing,angularjs,angularjs-directive,Unit Testing,Angularjs,Angularjs Directive,此自定义验证指令是官方网站上的一个示例。 它检查文本输入是否为数字格式 var INTEGER_REGEXP = /^\-?\d*$/; app.directive('integer', function() { return { require: 'ngModel', link: function(scope, elm, attrs, ctrl) { ctrl.$parsers.unshift(function(viewValue) { if (

此自定义验证指令是官方网站上的一个示例。 它检查文本输入是否为数字格式

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);
      });
    });
  });
});
我把打印语句放在各处,看看发生了什么,看起来指令从未被调用过。
测试这样一个简单指令的正确方法是什么?

我通过阅读angular应用程序代码找到了答案 这个视频也有帮助

我犯了两个错误:

  • 在执行ng模型时,不要直接绑定到范围
  • 使用表单控制器直接操作要传递给指令的内容
这是最新版本。指令是一样的,只是我改变了测试

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);
    });
  });
});
description('指令',函数()){
var$范围、形式;
在每个(模块('exampleDirective')之前;
beforeach(注入函数($compile,$rootScope){
$scope=$rootScope;
变量元素=角度元素(
'' +
'' +
''
);
$scope.model={somenum:null}
$compile(元素)($scope);
$scope.$digest();
form=$scope.form;
}));
描述('integer',函数(){
它('应该用整数传递',函数(){
表单.somenum.$setViewValue('3');
expect($scope.model.somenum).toEqual('3');
expect(form.somenum.valid).toBe(true);
});
它('shouldnotpasswithstring',function(){
form.somenum.$setViewValue('a');
expect($scope.model.somenum).toBeUndefined();
expect(form.somenum.valid).toBe(false);
});
});
});

另一个答案的测试应该写为:

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);
    });
  });
});
description('指令',函数()){
var$范围、形式;
在每个(模块('exampleDirective')之前;
beforeach(注入函数($compile,$rootScope){
$scope=$rootScope;
变量元素=角度元素(
'' +
'' +
''
);
$scope.model={somenum:null}
$compile(元素)($scope);
form=$scope.form;
}));
描述('integer',函数(){
它('应该用整数传递',函数(){
表单.somenum.$setViewValue('3');
$scope.$digest();
expect($scope.model.somenum).toEqual('3');
expect(form.somenum.valid).toBe(true);
});
它('shouldnotpasswithstring',function(){
form.somenum.$setViewValue('a');
$scope.$digest();
expect($scope.model.somenum).toBeUndefined();
expect(form.somenum.valid).toBe(false);
});
});
});

请注意,
$scope.$digest()
现在在
$setViewValue
之后调用。这会将表单设置为“脏”状态,否则它将保持“原始”,这可能不是您想要的。

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

  '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('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)
  }));
});
“严格使用”;
描述('指令:validadorCorreo',函数(){
//加载指令的模块
在每个模块之前(模块('sistemaRegistroProCivilApp');
var inputCorreo,formulario,elementoFormulario,scope,$compile;
beforeach(注入(函数($rootScope,$compile){
scope=$rootScope.$new();
$compile=\$compile;
elementoFormulario=角度元素(“”+
'' + 

“感谢您抽出时间带回答案!仅供参考,您可以提取您的答案并将其标记为已接受的答案,供以后的搜索者使用-这在这里是可以接受的;-)谢谢你的提示。我移动了我的答案。@ghiden这真的帮助了我,但是,你有过链接多个指令和测试的经验吗?比如,如果你为电话或电子邮件制定了一个指令?每当我尝试添加一个附加指令时,我都会遇到一大堆错误。想法?链接多个指令?我想即使你应用程序如果对一个元素使用多个指令,您仍然希望分别测试它们,对吗?如果每个指令都正常工作并且优先级设置正确,我想它们应该会正常工作。我有时会先执行模型验证之类的操作,然后以非常低的优先级继续执行视觉效果指令。@ghiden我发现了问题,我正在测试表单验证d我相信我的主要问题是使用name作为指令,以及输入元素的属性。不过,我现在一切都很好,并且正在测试它!非常感谢您的示例。确实帮助很大。在我添加
$scope.$digest()之前,这对我不起作用
在调用
$setViewValue
后。我是否做了一些奇怪的事情,或者您的示例中缺少了这些内容?编辑:对不起,没有看到下面的答案。我永远无法通过第二次测试(始终为真)我使用的是1.3.12,有什么变化吗?非常感谢,今天帮了我很多忙!但是我直接使用的是范围模型,而不是
$setViewValue()
,我不知道我是否错过了很多案例。。。?
  '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('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)
  }));
});