AngularJS Karma测试中的jQuery触发事件

时间:2014-01-18 23:07:13

标签: javascript jquery angularjs jasmine karma-runner

我正在尝试测试我正在编写的新指令。但是,我似乎无法在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事件处理输入的建议?

2 个答案:

答案 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个依赖项:

  1. $.Event,直接参考;和
  2. $,由angular.element()间接引用;
  3. 当加载AngularJS时,它会查找以前加载的jQuery实例,如果它存在,它会使element成为$的别名。否则,它会加载对jqLit​​e的引用,该引用没有trigger方法。

    所以,我确定你已经加载了jQuery,但这并不意味着AngularJS会使用它。为此,您必须确保在AngularJS之前(任何地方)加载jQuery。

    angular.element()引用jqLit​​e时,即使加载了jQuery,它也永远不会调用jQuery。所以你只能调用jqLit​​e上定义的方法:

    angular.element(inputEl).triggerHandler(e);
    

    但是,jqLit​​e的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用户查看,但仍然无法解决核心问题。