一尘不染

如何在AngularJS的指令测试中触发ng-change

angularjs

我有以下创建input元素的AngularJS指令。输入具有ng- change运行doIt()功能的属性。在指令的单元测试中,我想检查doIt用户更改输入时是否调用了函数。但是测试没有通过。虽然在手动测试时可以在浏览器中使用。

指示:

...
template: "<input ng-model='myModel' ng-change='doIt()' type='text'>"

测试:

el.find('input').trigger('change') // Dos not trigger ng-change

实时演示(ng-change):http :
//plnkr.co/edit/0yaUP6IQk7EIneRmphbW?p=preview


现在,如果我手动绑定change事件而不是使用ng-change属性,则测试通过。

template: "<input ng-model='myModel' type='text'>",
link: function(scope, element, attrs) {
  element.bind('change', function(event) {
    scope.doIt();
  });
}

现场演示(手动绑定):http :
//plnkr.co/edit/dizuRaTFn4Ay1t41jL1K?p=preview


有没有一种方法可以使用ng-change并使其可测试?谢谢。


阅读 235

收藏
2020-07-04

共1个答案

一尘不染

根据您的解释性意见:

我在指令的测试中要做的只是检查doIt用户更改输入时调用了该指令。

指示符ng- change是否正确评估是ngModel指示符的责任,因此,我不确定是否可以通过这种方式对其进行测试;相反,我相信ngModeland
ngChange指令已正确实现并经过测试可以调用指定的函数,并且只需测试调用函数本身以正确的方式影响指令即可。可以使用端到端或集成测试来处理整个使用场景。

也就是说,您可以掌握ngModelController驱动ngModel变更回调的实例并自行设置视图值:

it('trigger doIt', function() {
  var ngModelController = el.find('input').controller('ngModel');
  ngModelController.$setViewValue('test');
  expect($scope.youDidIt).toBe(true);
});

但是,正如我所说,我觉得这已经太过ngModel分担责任了,打破了自然可组合指令所带来的黑匣子。

示例:http//plnkr.co/edit/BaWpxLuMh3HvivPUbrsd?p
= preview


[更新]

浏览AngularJS源代码后,我发现以下内容也适用:

it('trigger doIt', function() {
  el.find('input').trigger('input');
  expect($scope.youDidIt).toBe(true);
});

看起来某些浏览器中的事件有所不同;input似乎适用于Chrome。

示例:http//plnkr.co/edit/rbZ5OnBtKMzdpmPkmn2B?p
= preview

以下是相关的AngularJS代码,该代码使用$sniffer服务确定要触发的事件:

changeInputValueTo = function(value) {
  inputElm.val(value);
  browserTrigger(inputElm, $sniffer.hasEvent('input') ? 'input' : 'change');
};

即使有了这个,我也不确定我是否会以此方式测试指令。

2020-07-04