Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

testing keydown events in Jasmine with specific keyCode

I am writing tests for an AngularJS directive which fires events of a <textarea> when certain keys are pressed. It all works fine per my manual testing. I want to be good and have a full unit-test suite too, but I have run into a problem I can't solve on my own:

I want to send a specific keyCode in my triggerHandler() call in my test, but I can't find a way to specify the key that actually works. I am aware of a lot of questions and answers on the topic of building and sending events with specific data, but none of them work on my setup:

My setup

  • Karma test runner
  • PhantomJS browser running the tests (but also tried Firefox and Chrome without success)
  • I'm not using jQuery and I'm hoping there is a regular JS solution. There must be!

Test code

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

The strange thing is, I can type the first 3 lines into the console in Chrome and see that the event is being created with the keyCode property set to 40. So it seems like it should work.

Also, when I call the last line like this textarea.triggerHandler("keydown"); it works and the event handler is triggered. However, there is no keyCode to work with, so it is pointless.

I suspect it may be something to do with the nature of the test running against a DOM that is different to a regular page running in the browser. But I can't figure it out!

like image 962
Michael Bromley Avatar asked Mar 22 '14 06:03

Michael Bromley


People also ask

How do I trigger Keydown event?

keydown: This event is triggered when a key is pressed down. keypress: This event is triggered when a key is pressed. This event fails to recognise keys such as tab, shift, ctrl, backspace etc. keyup: This event is triggered when a key is released.

Is Keydown an event?

The keydown event is fired when a key is pressed. Unlike the keypress event, the keydown event is fired for all keys, regardless of whether they produce a character value. The keydown and keyup events provide a code indicating which key is pressed, while keypress indicates which character was entered.

How do you use Keydown function?

The keydown() is an inbuilt method in jQuery which is used to trigger the keydown event whenever User presses a key on the keyboard. If the key is kept pressed, the event is sent every time the operating system repeats the key. So, Using keydown() method we can detect if any key is on its way down.

What is the use of on Keydown event?

Definition and Usage The onkeydown event occurs when the user is pressing a key (on the keyboard). Tip: The order of events related to the onkeydown event: onkeydown. onkeypress.


1 Answers

I've used the following solution to test it and having it working in Chrome, FF, PhantomJS and IE9+ based on this SO answer. It doesn't work in Safari - tried millions of other solution without any success...

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);

Hope it helps

Update

Today I've found and tested this solution which is offers a much wider coverage of browsers (enabling the legacy support):

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

All the credit goes to the author of this GIST. The code does support Safari, PhantomJS and IE9 - tested for the first 2.

like image 156
MarcoL Avatar answered Nov 10 '22 05:11

MarcoL