javascript 模拟茉莉花中的假按键

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26966044/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 06:45:26  来源:igfitidea点击:

Simulate fake keypress in jasmine

javascriptunit-testingjasmine

提问by emmabukacek

I'm trying to simulate a keypress in Jasmine (the test browser is PhantomJS) so I can unit test some of my functions that use key presses. Unfortunately, I can't test it properly with Jasmine because I'm getting errors.

我正在尝试在 Jasmine 中模拟按键(测试浏览器是 PhantomJS),因此我可以对我的一些使用按键的功能进行单元测试。不幸的是,我无法使用 Jasmine 正确测试它,因为我遇到了错误。

Here's the code I'm trying to test:

这是我要测试的代码:

function Controls() {
  'use strict';
  this.codes = {
    37: 'left',
    39: 'right',
    38: 'forward',
    40: 'backward'
  };
  this.states = {
    'left': false,
    'right': false,
    'forward': false,
    'backward': false
  };
  document.addEventListener('keydown', function() { this.onKey.bind(this, true); }, false);
  document.addEventListener('keyup', function() { this.onKey.bind(this, false); }, false);
}

Controls.prototype.onKey = function(val, e) {
  var state = this.codes[e.keyCode];

  if (typeof state === 'undefined') return false;

  this.states[state] = val;

  // Stop the key press from repeating
  e.preventDefault();
  e.stopPropagation();

  return true;
};

controls = new Controls();

(NOTE: The above code wraps the functions in the addEventListener with anon functions so that Jasmine will actually attempt to run my tests. Without the anonymous wrap, this results in another error: TypeError: 'undefined' is not a function (evaulating 'this.onKey.bind(this, true)'Solving this problem would be great too. )

(注意:上面的代码用匿名函数包装了 addEventListener 中的函数,这样 Jasmine 就会实际尝试运行我的测试。如果没有匿名包装,这会导致另一个错误:TypeError: 'undefined' is not a function (evaulating 'this.onKey.bind(this, true)'解决这个问题也会很棒。)

And this is my attempt at testing:

这是我的测试尝试:

function keyPress(key) {
  var pressEvent = document.createEvent('KeyboardEvent');
  pressEvent.initKeyEvent('keydown', true, true, window,
                            false, false, false, false,
                            0, key);
  document.dispatchEvent(pressEvent);
}

describe("Controls", function() {
  var controls;

  it("should initialize properly", function() {
    controls = new Controls();
    expect(controls).not.toBe(null);
  });

  it("should reflect changes in state when arrow keys are used", function() {
    keyPress(37);
    expect(controls.states[state]).toBe(37);
  });
});

This results in an error from Jasmine:

这会导致 Jasmine 出现错误:

TypeError: 'undefined' is not a function (evaluating 'pressEvent.initKeyEvent('keydown', true, true, window, false, false, false, false, 0, key)')

I'm still very new to Jasmine (and for that matter, Javascript), so any help in general would be appreciated.

我对 Jasmine(以及就此而言,Javascript)仍然很陌生,因此任何帮助都将不胜感激。

回答by Chris

It looks like your problem is with how you're creating your event.

看起来您的问题在于您如何创建活动。

The example code below shows how an event is created, triggered, and intercepted.

下面的示例代码显示了如何创建、触发和拦截事件。

var keyPressed = null;

function keyPress(key) {
  var event = document.createEvent('Event');
  event.keyCode = key; // Deprecated, prefer .key instead.
  event.key = key;
  event.initEvent('keydown');
  document.dispatchEvent(event);
}

document.addEventListener('keydown', function(e){
   keyPressed = e.key;
});

keyPress(37)
alert(keyPressed);

Here's a plunker too: http://plnkr.co/edit/TxGXcT0DnPa44C0PkHkN?p=preview

这也是一个 plunker:http://plnkr.co/edit/TxGXcT0DnPa44C0PkHkN?p=preview

As commented, see herefor information regarding .keyCode deprecation.

正如所评论的,有关 .keyCode 弃用的信息,请参见此处

回答by emmabukacek

EDIT: This issue should be resolved as of PhantomJS 2. More information in the issue below.

编辑:这个问题应该从 PhantomJS 2 开始解决。更多信息在下面的问题中。

So the reason

所以原因

this.onKey.bind(this, true)

was returning an error is because as of the date of this post, PhantomJS doesn't support binds yet. You can find more information on that here:

返回错误是因为截至本文发布之日,PhantomJS 尚不支持绑定。你可以在这里找到更多信息:

https://github.com/ariya/phantomjs/issues/10522

https://github.com/ariya/phantomjs/issues/10522

and a longer explanation from ariya here:

以及来自 ariya 的更长解释:

https://groups.google.com/forum/#!msg/phantomjs/r0hPOmnCUpc/uxusqsl2LNoJ

https://groups.google.com/forum/#!msg/phantomjs/r0hPOmnCUpc/uxusqsl2LNoJ

A way around this issue is to create a polyfill as suggested by creationix:

解决此问题的一种方法是按照creationix 的建议创建一个polyfill:

https://github.com/c9/smith/blob/master/tests/public/test.js#L2-L7

https://github.com/c9/smith/blob/master/tests/public/test.js#L2-L7

Given all of this information, it should make testing a little more manageable knowing that I can circumvent the prototype issue. Thanks for all of the help!

鉴于所有这些信息,知道我可以绕过原型问题,它应该使测试更易于管理。感谢所有的帮助!