Simulate fake keypress in jasmine

20,807

Solution 1

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

As commented, see here for information regarding .keyCode deprecation.

Solution 2

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

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:

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

and a longer explanation from ariya here:

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

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

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!

Share:
20,807
emmabukacek
Author by

emmabukacek

Updated on April 10, 2020

Comments

  • emmabukacek
    emmabukacek about 4 years

    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.

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

    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:

    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.

  • emmabukacek
    emmabukacek over 9 years
    Because this solved the actual issue at hand, I accepted this answer; thanks Chris! However, my original question wasn't really what I should have been asking, so I'll give more details on this below.
  • ollie314
    ollie314 over 8 years
    Hi, This is a old post but it may good to know that the keyCode is now deprecated see the MDN article. So the code should use key or code and thus be slightly different.
  • Michael L.
    Michael L. about 6 years
    I edited this answer with an edition of the new event.key instead of event.keycode