Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

userEvent.type: wrong keyCode for dot character? #456

Closed
andreaswilli opened this issue Sep 27, 2020 · 8 comments
Closed

userEvent.type: wrong keyCode for dot character? #456

andreaswilli opened this issue Sep 27, 2020 · 8 comments
Labels
accuracy Improves the accuracy of how behavior is simulated

Comments

@andreaswilli
Copy link

  • @testing-library/user-event version: 12.1.6
  • Testing Framework and version: jest 24.9.0
  • DOM Environment: jsdom 14.1.0

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

@ph-fritsche
Copy link
Member

KeyCode is basically not implemented at all - special chars aside.

This only works for numbers and uppercase letters:

const keyCode = char.charCodeAt(0)

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}

@andreaswilli
Copy link
Author

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?

@ph-fritsche
Copy link
Member

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.

@nickserv
Copy link
Member

nickserv commented Nov 9, 2020

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?

@nickserv nickserv added the needs investigation Someone has to do research on this label Nov 9, 2020
@andreaswilli
Copy link
Author

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.

@nickserv
Copy link
Member

nickserv commented Nov 9, 2020

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.

@ph-fritsche
Copy link
Member

ph-fritsche commented Nov 9, 2020

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

This issue exists only for the physical location of a button.
For key there is no issue:

const key = char // TODO: check if this also valid for characters with diacritic markers e.g. úé etc

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}"

@nickserv nickserv added accuracy Improves the accuracy of how behavior is simulated help wanted labels Nov 10, 2020
@ph-fritsche ph-fritsche mentioned this issue Dec 14, 2020
8 tasks
@ph-fritsche
Copy link
Member

Resolved in v13.0.0 🚀

@ph-fritsche ph-fritsche removed the needs investigation Someone has to do research on this label Jul 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accuracy Improves the accuracy of how behavior is simulated
Projects
None yet
Development

No branches or pull requests

3 participants