如何在 AngularJS 中的指令测试中触发 ng-change [英] How to trigger ng-change in directive test in AngularJS

查看:28
本文介绍了如何在 AngularJS 中的指令测试中触发 ng-change的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have the following AngularJS directive that creates an input element. Input has ng-change attribute that runs doIt() function. In my directive's unit test I want to check if doIt function is called when users changes the input. But the test does not pass. Though it works in the browser when testing manually.

指令:

...
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=预览

Live demo (ng-change): http://plnkr.co/edit/0yaUP6IQk7EIneRmphbW?p=preview

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

Now, the test passes if I manually bind change event instead of using ng-change attribute.

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=预览

Live demo (manual binding): http://plnkr.co/edit/dizuRaTFn4Ay1t41jL1K?p=preview

有没有办法使用 ng-change 并使其可测试?谢谢.

Is there a way to use ng-change and make it testable? Thank you.

推荐答案

来自您的解释性评论:

我想在指令的测试中做的就是检查当用户更改输入时是否调用了 doIt.

All I want to do in directive's test is to check that doIt is called when user changes the input.

ng-change 指示的表达式是否被正确计算实际上是 ngModel 指令的责任,所以我不确定我会以这种方式进行测试;相反,我相信 ngModelngChange 指令已被正确实现和测试以调用指定的函数,只需测试调用函数本身是否会影响指令正确的方式.可以使用端到端或集成测试来处理全使用场景.

Whether or not the expression indicated by ng-change is correctly evaluated or not is really the responsibility of the ngModel directive, so I'm not sure I'd test it in this way; instead, I'd trust that the ngModel and ngChange directives have been correctly implemented and tested to call the function specified, and just test that calling the function itself affects the directive in the correct manner. An end-to-end or integration test could be used to handle the full-use scenario.

也就是说,您可以获取驱动 ngModel 更改回调的 ngModelController 实例并自己设置视图值:

That said, you can get hold of the ngModelController instance that drives the ngModel change callback and set the view value yourself:

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

不过,正如我所说,我觉得这超出了 ngModel 的职责范围,打破了自然可组合指令的黑箱.

As I said, though, I feel like this is reaching too far into ngModel's responsibilities, breaking the black-boxing you get with naturally composable directives.

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

[更新]

在查看 AngularJS 源代码后,我发现以下内容也有效:

After looking around at the AngularJS source, I found that the following also works:

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

在某些浏览器中,该事件似乎有所不同;input 似乎适用于 Chrome.

It looks like the event is different in some browsers; input seems to work for Chrome.

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

这是 相关AngularJS 代码,它使用 $sniffer 服务来确定要触发的事件:

Here is the relevant AngularJS code, which uses the $sniffer service to figure out which event to trigger:

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

即使有这个,我也不确定我会以这种方式测试指令.

Even having this, I'm not sure I'd test a directive in this way.

这篇关于如何在 AngularJS 中的指令测试中触发 ng-change的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆