角度测试:如何期望触发元素事件?

Mis*_*hko 3 jasmine angularjs angular-directive

我正在装饰这样的表格:

angular.module('Validation').directive('form', function() {
  return {
    restrict: 'E',
    link: function(scope, element) {
      var inputs = element[0].querySelectorAll('[name]');

      element.on('submit', function() {
        for (var i = 0; i < inputs.length; i++) {
          angular.element(inputs[i]).triggerHandler('blur');
        }
      });
    }
  };
});
Run Code Online (Sandbox Code Playgroud)

现在,我正在尝试测试这个指令:

describe('Directive: form', function() {
  beforeEach(module('Validation'));

  var $rootScope, $compile, scope, form, input, textarea;

  function compileElement(elementHtml) {
    scope = $rootScope.$new();
    form = angular.element(elementHtml);
    input = form.find('input');
    textarea = form.find('textarea');
    $compile(form)(scope);
    scope.$digest();
  }

  beforeEach(inject(function(_$rootScope_, _$compile_) {
    $rootScope = _$rootScope_;
    $compile = _$compile_;

    compileElement('<form><input type="text" name="email"><textarea name="message"></textarea></form>');
  }));

  it('should trigger "blur" on all inputs when submitted', function() {
    spyOn(input, 'trigger');
    form.triggerHandler('submit');
    expect(input.trigger).toHaveBeenCalled(); // Expected spy trigger to have been called.
  });
});
Run Code Online (Sandbox Code Playgroud)

但是,测试失败了.

测试该指令的Angular方法是什么?

Kha*_* TO 7

你有一些问题:

1)input = form.find('input');并且angular.element(inputs[i]);是包装相同底层DOM对象的2个不同的包装器对象.

2)你应该创建一个间谍triggerHandler.

3)您正在直接使用难以进行单元测试的DOM.

这方面的一个例子是:angular.element(inputs[i]) 没有注入,所以我们在单元测试中难以伪装它.

确保点1)返回相同的对象.我们可以伪造它angular.element以返回预先训练的值,即input = form.find('input');

//Jasmine 1.3: andCallFake
//Jasmine 2.0: and.callFake
angular.element = jasmine.createSpy("angular.element").and.callFake(function(){
         return input; //return the same object created by form.find('input');
});
Run Code Online (Sandbox Code Playgroud)

旁注:由于form已经是angularJs指令,为避免与已定义的指令冲突,您应该创建另一个指令并将其应用于form.像这样的东西:

<form mycustomdirective></form>
Run Code Online (Sandbox Code Playgroud)

我不确定这是否有必要.因为我们正在监视可能在许多地方使用的全局函数(angular.element),我们可能需要保存以前的函数并在测试结束时恢复它.您的完整源代码如下所示:

it('should trigger "blur" on all inputs when submitted', function() {

    var angularElement = angular.element; //save previous function

    angular.element = jasmine.createSpy("angular.element").and.callFake(function(){
         return input;
    });

    spyOn(input, 'triggerHandler');
    form.triggerHandler('submit');

    angular.element = angularElement; //restore
    expect(input.triggerHandler).toHaveBeenCalled(); // Expected spy trigger to have been called.
  });
Run Code Online (Sandbox Code Playgroud)

运行DEMO