Reputation: 1979
I'm trying to simulate a keydown event in a unit test (angular2/TypeScript). I do not always have a DebugElement available, so I'm trying to emit the event on a native element. The problem I have is how to define the keyCode when creating the KeyboardEvent. The keyCode is not defined as part of KeyboardEventInit definition, and on the KeyboardEvent itself it is only exposed as a readonly property.
Simply just adding a keyCode property (and set the obj type as ) doesn't work either.
let elm = <HTMLElement>content.nativeElement;
let ev = new KeyboardEvent('keydown', {
code: '123',
//keyCode: 345,
key: 'a',
});
elm.dispatchEvent(ev);
Any suggestions ?
Edit: According to the mdn link, keyCode is deprecated and should not be used, instead 'code' should be used. https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
Upvotes: 19
Views: 26949
Reputation: 2014
Have a look :
<!DOCTYPE html>
<html>
<body>
<script>
function EventHandler(e) {
e = e || window.event;
var code = typeof e.which !== 'undefined' ? e.which : e.keyCode;
if(code == 112 || code == 113
|| code == 114 || code == 115
|| code == 116 || code == 117
|| code == 118 || code == 119
|| code == 120 || code == 121
|| code == 122 || code == 123) {
e.returnValue = false;
var target2 = document.getElementById("iFrameId");
var targetBody = target2.contentDocument.body;
var keyboardEvent = document.createEvent("KeyboardEvent");
Object.defineProperty(keyboardEvent, 'keyCode', {
get : function() {
return this.keyCodeVal;
}
});
Object.defineProperty(keyboardEvent, 'which', {
get : function() {
return this.keyCodeVal;
}
});
var initMethod = typeof keyboardEvent.initKeyboardEvent !== 'undefined' ? "initKeyboardEvent" : "initKeyEvent";
keyboardEvent[initMethod](
"keydown", // event type : keydown, keyup, keypress
true, // bubbles
true, // cancelable
window, // viewArg: should be window
false, // ctrlKeyArg
false, // altKeyArg
false, // shiftKeyArg
false, // metaKeyArg
code, // keyCodeArg : unsigned long the virtual key code, else 0
0 // charCodeArgs : unsigned long the Unicode character associated with the depressed key, else 0
);
keyboardEvent.keyCodeVal = code;
targetBody.dispatchEvent(keyboardEvent);
}
}
</script>
<form>
<input type="text" name="first" onkeydown="EventHandler()" > <br>
<iframe id="iFrameId" src="frame.html" > </iframe>
</form>
</body>
</html>
Upvotes: 0
Reputation: 2014
or example, if you wanted to run a function when a user hit CTRL+ALT+D, your code would look something like this.
window.addEventListener('keydown', (event: KeyboardEvent) => {
// Fall back to event.which if event.keyCode is null
const keycode = event.keyCode || event.which;
if (keycode === 68 && event.ctrlKey && event.altKey) {
// Do stuff here
}
});
Upvotes: 0
Reputation: 337
If you're using angular, you can set the keyboard event, and key in your HTML template and bind to your method.
See angular docs on this: https://angular.io/guide/user-input#key-event-filtering-with-keyenter
And since you don't need to test the angular API as it's not your system under test, you should simply write your unit tests by passing mocked data into the method you've bound the key event to.
All of this isn't particularly helpful though if you meant UI/Integration tests, as the above is really only valid for unit tests.
Upvotes: 0
Reputation: 1058
I still think that this is a bug from the Typescript's side because of the initializer LanguageEvent has. In any case, a workaround would be to use Object.define to set the keyCode.
let arrowRight = new KeyboardEvent('keydown');
Object.defineProperty(arrowRight, 'keyCode', {
get : () => 39
});
console.log(arrowRight.keyCode, arrowRight.key, arrowRight.code);
No matter the fact that the keyCode is deprecated, that doesn't mean that the initializer shouldn't support it. The most strong argument is the fact that Internet Explorer 9 and 11 depends on that and they don't support the code https://caniuse.com/#search=event.code or fully support the key https://caniuse.com/#search=event.key So I think that LanguageEvent should allow keyCode in its initializer.
let arrowRight = new KeyboardEvent('keydown', { keyCode: 39 });
Upvotes: 4
Reputation: 3661
keyCode
is deprecated, Angular itself operates with key
— I suggest you rewrite your logic to use it too. Keep in mind that it is browser dependent — in IE space bar is Space
and in other browsers it is . Also
Esc
and Escape
are different. Don't remember any other ones that differ.
Upvotes: 1