我正在尝试测试我正在编写的新指令。但是,我似乎无法在Karma / Jasmine中使用jQuery触发keydown事件。
以下是测试的简化版本:
'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);
});
});
});
我的业力配置包括AngularJS和jQuery。这是该部分:
//
files: [
'lib/angular.js',
'lib/angular-mocks.js',
'lib/jquery-1.10.2.min.js',
'test/**/*Spec.js'
],
当我运行测试时,我得到一个错误,我的输入元素没有触发器方法:
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)
首先,您可能认为不包含jQuery。但是,它包括在内。如果不是,则测试将在$.Event
处失败。
关于让keydown事件处理输入的建议?
答案 0 :(得分:11)
我希望这有效
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
答案 1 :(得分:2)
TLDR :在AngularJS之前加载jQuery。
首先,您可能认为不包含jQuery。但是,确实如此 包括在内。如果不是,测试将在$ .Event失败。
这里有jQuery的2个依赖项:
$.Event
,直接参考;和$
,由angular.element()
间接引用; 当加载AngularJS时,它会查找以前加载的jQuery实例,如果它存在,它会使element
成为$
的别名。否则,它会加载对jqLite的引用,该引用没有trigger
方法。
所以,我确定你已经加载了jQuery,但这并不意味着AngularJS会使用它。为此,您必须确保在AngularJS之前(任何地方)加载jQuery。
当angular.element()
引用jqLite时,即使加载了jQuery,它也永远不会调用jQuery。所以你只能调用jqLite上定义的方法:
angular.element(inputEl).triggerHandler(e);
但是,jqLite的triggerHandler
不会执行事件冒泡,模拟引发事件也不可靠。 jQuery&#39; s trigger
更好。
要使用jQuery,请在HTML上执行此操作:
<script src="jquery.js">
<script src="angular.js">
或者你的karma.conf.js:
files: [
'lib/jquery-1.10.2.min.js',
'lib/angular.js',
'lib/angular-mocks.js',
'test/**/*Spec.js'
],
参考:
关于让keydown事件处理输入的建议?
通过解决问题找到了一种方法。对于你的单元测试来说,这不是什么大不了的事情,你需要一个更好的DOM库,但现在你知道发生了什么。
PS:我真的很喜欢回答这个问题。一个多年的问题,由6k用户查看,但仍然无法解决核心问题。