【问题标题】:jQuery Trigger Event in AngularJS Karma TestAngularJS Karma 测试中的 jQuery 触发事件
【发布时间】:2014-01-18 23:07:12
【问题描述】:

我正在尝试测试我正在编写的新指令。但是,我似乎无法在 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);

    });

  });

});

我的 karma 配置包括 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 事件对输入起作用的建议?

【问题讨论】:

  • 这就是问题所在。 [object Object] has no method 'trigger' 所以,我不能触发任何事件。
  • 对不起,我的意思是angular.element(inputEl).trigger('keydown')
  • @dcodesmith 谢谢。试过了。没有运气。还是Object [object Object] has no method 'trigger'

标签: javascript jquery angularjs jasmine karma-runner


【解决方案1】:

我希望这行得通

  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

【讨论】:

  • 我通过 Twitter 得到了另一个相同的答案,但你在这里得到了投票。 $(inputEl).trigger(e) 成功了。谢谢
【解决方案2】:

TLDR:在 AngularJS 之前加载 jQuery。

一开始,你可能会认为 jQuery 是不包括在内的。然而,它是 包括。如果不是,测试将在 $.Event 处失败。

这里有 2 个对 jQuery 的依赖:

  1. $.Event,直接参考;和
  2. $,被angular.element()间接引用;

当 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 的 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 用户查看,仍然没有回答 核心 问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-17
    • 2014-11-29
    • 2016-10-06
    • 1970-01-01
    • 1970-01-01
    • 2013-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多