chieffancypants / angular-hotkeys

Configuration-centric keyboard shortcuts for your Angular apps.
http://chieffancypants.github.io/angular-hotkeys/
MIT License
1.68k stars 254 forks source link

How to test ESC press in angualr unit test? #290

Closed superbazza closed 5 years ago

superbazza commented 5 years ago

Trying to write a component test to test keyboard shortcuts. Have registered hotkeys bound to scope.

How does one trigger an ESC key in the test to test the hotkey handler?

I have tried jquery

const component = $compile('<my-component></my-component>')($scope)
const element = angular.element(component[0]);
element.trigger({type: "keypress", keyCode: 27})

but that doesn't seem to work.

aramando commented 5 years ago

angular.element doesn't have a trigger() method, so I'm assuming you're using full jQuery?

The docs for jQuery#trigger suggest you should be doing it like this: element.trigger("keypress", { keyCode: 27 })

Also, AngularJS's built-in jqLite only provides the similar triggerHandler() method, which has some subtle differences. I'm not sure which one is best to use, but there may be a good reason why Angular gives you that rather than the trigger method, so it may be worth trying that instead as well. If it works, you might as well use the one that doesn't require full jQuery.

superbazza commented 5 years ago

Thanks. Hm, angular.element has trigger() for me (angular 1.6.6)

I got it working:

  1. keypress event doesn't work for 'non letter' keys like ESC, HOME, etc. You need to use keydown/keyup events
  2. Mousetrap registers the listeners on the low-level document. So the keyboard events on $document need to be bridged down to the document
        function _bridgeKeyboardEvent(e) {
            $document.trigger(e);
            // also bridge to non-angular code
            document.dispatchEvent(new KeyboardEvent(e.type, {
                keyCode: e.keyCode,
            }));
        }

        element.bind('keydown', _bridgeKeyboardEvent);
        element.bind('keyup', _bridgeKeyboardEvent);
        element.bind('keypress', _bridgeKeyboardEvent);

BTW, same kind of bridging needs to be done for mouse events if one is trying to test mouse interaction