@testing-library/user-event version: 12.1.6I simulate user input with userEvent.type:
test("log key codes", () => {
const handleKeyUp = (event) => {
console.log({ key: event.key, keyCode: event.keyCode });
};
render(<input type="text" onKeyUp={handleKeyUp} />);
const input = screen.getByRole("textbox");
userEvent.type(input, ".");
userEvent.type(input, "{del}");
});
Both the dot character and the delete key seem to have the same key code:
console.log src/App.test.js:7
{ key: '.', keyCode: 46 }
console.log src/App.test.js:7
{ key: 'Delete', keyCode: 46 }
However, according to http://www.javascriptkeycode.com/ the dot character is supposed to have a key code of 190.
Am I missing something or is there a bug somewhere?
Reproduction repository: https://github.com/andreaswilli/user-event-test
(created with create-react-app and updated @testing-library/jest-dom, @testing-library/react and @testing-library/user-event to most recent version)
KeyCode is basically not implemented at all - special chars aside.
This only works for numbers and uppercase letters:
https://github.com/testing-library/user-event/blob/5feaa942f46bb37d96c2f2fbeb4b33e8beff75ad/src/type.js#L295
KeyCodes are subject to the keyboard layout. But I guess best approach would be to ignore those and add a mapping for all chars and functional keys as on common US-keyboards. (Maybe with an option to inject own mappings for other localizations.)
So one could use userEvent.type(element, '{num9}.fOo&bar{f4}', {keyMap: myKeyboardLayoutMapping}). This should trigger key events for
num9 {key: "9", keyCode: 105}
. {key: "Shift", keyCode: 16}{key: ".", keyCode: 190}{key: "Shift", keyCode: 16}
fOo {key: "f", keyCode: 70}{key: "O", keyCode: 79}{key: "o", keyCode: 79}
& {key: "Shift", keyCode: 16}{key: "&", keyCode: 55}{key: "Shift", keyCode: 16}
bar {key: "b", keyCode: 66}{key: "a", keyCode: 65}{key: "r", keyCode: 82}
f4 {key: "f4", keyCode: 115}
I see. Maybe it should be mentioned in the docs until something like this is implemented.
KeyCodes are subject to the keyboard layout.
@ph-fritsche Are you saying it might be a bad idea to depend on keyCodes in my application?
Depends on what you're trying to accomplish.
If you use keyCode to provide some nice-to-have/convenience functionality / shortcuts that can be accessed by other means, you're probably fine.
Just bear in mind that you're designing a feature that might not be accessible by everyone.
Assuming a keyboard US layout sounds like it could cause difficult to debug issues for software tested in other regions. Is there a subset of keycodes we could support that would be consistent on any QWERTY keyboard?
I briefly looked into this.
keyCode seems to be deprecated anyway:
In the past, there was a keypress event, and also keyCode, charCode, which properties of the event object.
New properties are code and key:
code – the “key code” ("KeyA", "ArrowLeft" and so on), specific to the physical location of the key on keyboard.
key – the character ("A", "a" and so on), for non-character keys, such as Esc, usually has the same value as code.
key seems to be layout-independent so it should be possible to at least implement this property without taking into account different keyboard layouts.
Sounds good. Should we edit this issue to focus on supporting key instead of keyCode then? We could potentially copy the standardized value to keyCode as well as key, though that risks us having confusing failures versus a more obvious undefined value.
Assuming a keyboard US layout sounds like it could cause difficult to debug issues for software tested in other regions. Is there a subset of keycodes we could support that would be consistent on any QWERTY keyboard?
Even with the subset you still end up with a mapping that is just probably that of a given user of yours. There is no "true" keyCode for a given key as it is assigned by the manufacturer and although most use similar layouts it depends on the keyboard model, the driver and even OS settings.
E.g. if you say: "I want to use the button right next to [L]"
You don't know the key nor the keyCode of that button for any given user.
On an US-QWERTY-101-keyboard the button next to it is [;] with key=; and keyCode=186.
On a GER-QWERTZ-101-keyboard the button next to it is [Ö] with key=ö and keyCode=186.
But e.g. for the Logitech-G110 it has keyCode=192.
code – the “key code” ("KeyA", "ArrowLeft" and so on), specific to the physical location of the key on keyboard.
Yes, code tries to bring some sanity into this mess.
The key right next to [L] will have code=Semicolon.
But mapping code to key is still a case of probability.
Sounds good. Should we edit this issue to focus on supporting
keyinstead ofkeyCodethen? We could potentially copy the standardized value tokeyCodeas well askey, though that risks us having confusing failures versus a more obviousundefinedvalue.
This issue exists only for the physical location of a button.
For key there is no issue:
https://github.com/testing-library/user-event/blob/5feaa942f46bb37d96c2f2fbeb4b33e8beff75ad/src/type.js#L294
If we want to support that,
I guess best approach would be to add a mapping for all chars and functional keys as on common US-keyboards. (Maybe with an option to inject own mappings for other localizations.)
We could use the mapping in each direction and provide the option to use either by the user.
userEvent.type(el, "a9[Semicolon][Numpad9]")
// could translate to:
{key: "a", keyCode: 65, code: "KeyA"}
{key: "9", keyCode: 57, code: "Digit9"}
{key: ";", keyCode: 186, code: "Semicolon"}
{key: "NumPad 9", keyCode: 105, code: "Numpad9"}
We could use different brackets to differenciate between
the new usage of defining the button per code also allowing single key down/up events for meta keys like Shift: a[Shift]b
and the previous usage as modifier: "a{shift}b{/shift}"
Resolved in v13.0.0 :rocket: