javascript AngularJS Karma 测试中的 jQuery 触发事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21211036/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jQuery Trigger Event in AngularJS Karma Test
提问by Justin Noel
I'm trying to test a new directive I'm writing. However, I can't seem to get the keydown event to trigger with jQuery inside Karma/Jasmine.
我正在尝试测试我正在编写的新指令。但是,我似乎无法在 Karma/Jasmine 中使用 jQuery 触发 keydown 事件。
Here is a simplified version of the test :
这是测试的简化版本:
'use strict';
describe('', function() {
var $compile;
var $scope;
beforeEach(inject(function(_$compile_, _$rootScope_) {
$compile = _$compile_;
$scope = _$rootScope_.$new();
}));
describe('Getting Trigger To Work', function() {
it('Should Trigger a KeyDown Event', function() {
var el = $compile('<form name="testing"><input id="field1" name="testfield" ng-model="result" type="text" ng-minlength="5" ng-maxlength="50"/></form>')($scope);
console.log(el);
var inputEl = el.find('input');
console.log(inputEl);
var e = $.Event('keydown');
e.which = 65;
inputEl.trigger(e);
});
});
});
My karma config includes AngularJS and jQuery. Here's that section:
我的业力配置包括 AngularJS 和 jQuery。这是那个部分:
//
files: [
'lib/angular.js',
'lib/angular-mocks.js',
'lib/jquery-1.10.2.min.js',
'test/**/*Spec.js'
],
When I run the test, I get an error that my input element has no trigger method :
当我运行测试时,我收到一个错误,指出我的输入元素没有触发方法:
INFO [watcher]: Changed file "/Volumes/Macintosh HD/dev_libraries/val-on-timeout/test/valOnTimeoutSpec.js".
LOG: Object{0: <form name="testing" class="ng-scope ng-pristine ng-valid"><input id="field1" name="testfield" ng-model="result" type="text" ng-minlength="5" ng-maxlength="50" class="ng-pristine ng-valid"></form>, length: 1}
LOG: Object{0: <input id="field1" name="testfield" ng-model="result" type="text" ng-minlength="5" ng-maxlength="50" class="ng-pristine ng-valid">, length: 1}
Chrome 32.0.1700 (Mac OS X 10.8.5) testing valOnTimeout Should load FAILED
TypeError: Object [object Object] has no method 'trigger'
at null.<anonymous> (/Volumes/Macintosh HD/dev_libraries/val-on-timeout/test/valOnTimeoutSpec.js:79:21)
Chrome 32.0.1700 (Mac OS X 10.8.5): Executed 1 of 1 (1 FAILED) ERROR (0.327 secs / 0.033 secs)
At first, you may think that jQuery is not included. However, it is included. If it were not, the test would fail at $.Event
.
一开始,您可能认为 jQuery 不包括在内。但是,它包括在内。如果不是,则测试将在 处失败$.Event
。
Suggestions on getting the keydown event to work on the input?
关于让 keydown 事件对输入起作用的建议?
回答by dcodesmith
I hope this works
我希望这有效
var e = $.Event('keydown');
e.which = 65;
$(inputEl).trigger(e); // convert inputEl into a jQuery object first
// OR
angular.element(inputEl).triggerHandler(e); // angular.element uses triggerHandler instead of trigger to trigger events
回答by André Werlang
TLDR: load jQuery before AngularJS.
TLDR:在 AngularJS 之前加载 jQuery。
At first, you may think that jQuery is not included. However, it is included. If it were not, the test would fail at $.Event.
一开始,您可能认为 jQuery 不包括在内。但是,它包括在内。如果不是,则测试将在 $.Event 处失败。
You have 2 dependencies on jQuery here:
您在此处对 jQuery 有 2 个依赖项:
$.Event
, a direct reference; and$
, indirectly referenced byangular.element()
;
$.Event
,直接引用;和$
, 间接引用angular.element()
;
When AngularJS is loaded, it looks for a previously loaded jQuery instance, and in case it does exist, it makes element
just an alias to $
. Otherwise it loads a reference to jqLite, which does not have a trigger
method.
当 AngularJS 被加载时,它会寻找一个先前加载的 jQuery 实例,如果它确实存在,它element
只是为$
. 否则,它会加载对 jqLite 的引用,该引用没有trigger
方法。
So, I'm sure you do have jQuery loaded, but that does not mean AngularJS will use it. To do so, you must ensure jQuery is loaded (anywhere) before AngularJS.
所以,我确定您确实加载了 jQuery,但这并不意味着 AngularJS 会使用它。为此,您必须确保在 AngularJS 之前加载 jQuery(任何地方)。
When angular.element()
refers to jqLite, it would never call jQuery, even after jQuery is loaded. So you can only call methods defined on jqLite:
当angular.element()
引用 jqLite 时,它永远不会调用 jQuery,即使在加载 jQuery 之后。所以只能调用jqLite上定义的方法:
angular.element(inputEl).triggerHandler(e);
However, jqLite's triggerHandler
would not perform event bubbling, it's not reliable to mock raising events. jQuery's trigger
is way better.
但是,jqLitetriggerHandler
不会执行事件冒泡,模拟引发事件是不可靠的。jQuery 的trigger
要好得多。
To use jQuery, do this on your HTML:
要使用 jQuery,请在您的 HTML 上执行以下操作:
<script src="jquery.js">
<script src="angular.js">
Or on your karma.conf.js:
或者在你的 karma.conf.js 上:
files: [
'lib/jquery-1.10.2.min.js',
'lib/angular.js',
'lib/angular-mocks.js',
'test/**/*Spec.js'
],
Reference:
参考:
- https://docs.angularjs.org/api/ng/function/angular.element
- https://github.com/angular/angular.js/blob/master/src/Angular.js#L1608
- https://docs.angularjs.org/api/ng/function/angular.element
- https://github.com/angular/angular.js/blob/master/src/Angular.js#L1608
Suggestions on getting the keydown event to work on the input?
关于让 keydown 事件对输入起作用的建议?
You have found one approach by working-around the problem. It's not a big deal for your unit tests, where you would want a better DOM library, but now you know what's going on.
您已经通过解决问题找到了一种方法。对于您的单元测试来说,这不是什么大问题,您会想要一个更好的 DOM 库,但现在您知道发生了什么。
PS: I really liked answering this one. A question from more than a year, viewed by 6k users, and still no answer to the coreproblem.
PS:我真的很喜欢回答这个问题。一年多的问题,6k用户查看,仍然没有解决核心问题。