使用特定的keyCode测试Jasmine中的keydown事件

testing keydown events in Jasmine with specific keyCode

本文关键字:Jasmine 中的 keydown 事件 测试 keyCode      更新时间:2023-09-26

我正在为AngularJS指令编写测试,该指令在按下某些键时触发<textarea>的事件。根据我的手动测试,这一切都很好。我也想做得好,有一个完整的单元测试套件,但是我遇到了一个我自己无法解决的问题:

在我的测试中,我想在我的triggerHandler()调用中发送一个特定的keyCode,但我找不到一种方法来指定实际工作的。我知道有很多关于构建和发送带有特定数据的事件的问题和答案,但它们都不适用于我的设置:

我的设置
  • Karma测试运行器
  • PhantomJS浏览器运行测试(但也尝试了Firefox和Chrome没有成功)
  • 我不使用jQuery,我希望有一个常规的JS解决方案。一定有!

测试代码
var event = document.createEvent("Events");
event.initEvent("keydown", true, true);
event.keyCode = 40; // in debugging the test in Firefox, the event object can be seen to have no "keyCode" property even after this step
textarea.triggerHandler(event); // my keydown handler does not fire

奇怪的是,我可以在Chrome中输入前3行,看到事件正在创建keyCode属性设置为40。所以看起来应该行得通。

另外,当我像这样调用最后一行textarea.triggerHandler("keydown");时,它工作并且触发事件处理程序。然而,没有keyCode可以使用,所以它是毫无意义的。

我怀疑这可能与针对不同于在浏览器中运行的常规页面的DOM运行的测试的性质有关。但是我想不出来!

我使用了以下解决方案来测试它,并根据这个SO答案在Chrome, FF, PhantomJS和IE9+中工作。它不能在Safari中工作-尝试了数百万其他解决方案,但没有成功…

function jsKeydown(code){
  var oEvent = document.createEvent('KeyboardEvent');
  // Chromium Hack: filter this otherwise Safari will complain
  if( navigator.userAgent.toLowerCase().indexOf('chrome') > -1 ){
    Object.defineProperty(oEvent, 'keyCode', {
      get : function() {
        return this.keyCodeVal;
      }
    });     
    Object.defineProperty(oEvent, 'which', {
      get : function() {
        return this.keyCodeVal;
      }
    });
  }
  if (oEvent.initKeyboardEvent) {
    oEvent.initKeyboardEvent("keydown", true, true, document.defaultView, false, false, false, false, code, code);
  } else {
    oEvent.initKeyEvent("keydown", true, true, document.defaultView, false, false, false, false, code, 0);
  }
  oEvent.keyCodeVal = code;
  if (oEvent.keyCode !== code) {
    console.log("keyCode mismatch " + oEvent.keyCode + "(" + oEvent.which + ") -> "+ code);
  }
  document.getElementById("idToUseHere").dispatchEvent(oEvent);
}
// press DEL key
jsKeydown(46);

希望有帮助

更新

今天我发现并测试了这个解决方案,它提供了更广泛的浏览器覆盖范围(启用旧版本支持):

https://gist.github.com/termi/4654819

所有的功劳归于这个GIST的作者。代码支持Safari, PhantomJS和IE9 -测试前2。

对于@MarcoL的回答,我想为将来可能会遇到这个问题的读者指出,方法initKeyboardEventinitKeyEvent是已弃用的方法,不应该再使用。请看这里和这里。

按照MDN文档的建议,事件应该通过它们各自的构造函数来创建。