-
Notifications
You must be signed in to change notification settings - Fork 255
Description
Environment
@testing-library/user-event@^12.8.1jest@^26.6.3jsdom@^16.4.0
What you did
- Created an input element that has a keydown event handler that calls
event.preventDefault()if theevent.keyisArrowLeft. - Use
userEvent.typeto enter text into the input element. - Use
userEvent.typeto enter the{arrowleft}special key. - Attempted to assert that the input's
selectionStartwas not moved by the arrow left key press.
What happened:
When using userEvent.type to enter the {arrowleft} special key the selectionStart is updated despite preventDefault being called on the event by an event handler attached on the input element.
Reproduction repository:
https://codesandbox.io/s/react-testing-library-selectionstart-issue-yb15q?file=/src/App.test.js
export default function CustomInput() {
return (
<input
data-testid="testInput"
type="text"
onKeyDown={(event) => {
if (event.key === "ArrowLeft") {
event.preventDefault();
}
}}
/>
);
}describe("user-event {arrowkey}", () => {
it("should respect preventDefault when updating selectionStart", () => {
const { container } = render(<CustomInput />);
const inputElement = getByTestId(container, "testInput");
userEvent.type(inputElement, "Hello, World!");
expect(inputElement.selectionStart).toBe(13);
userEvent.type(inputElement, "{arrowleft}");
expect(inputElement.selectionStart).toBe(13);
});
});Problem description:
The preventDefault does not appear to be respected with regards to using the arrow keys when determining the selectionStart.
In type.js I can see that the arrow keys uses navigationKey which does not appear to have any handling for if the event default was prevented.
[specialCharMap.arrowLeft]: navigationKey('ArrowLeft')However, I do see that some other characters do have special handling for this use case, for example the backspace key:
[specialCharMap.backspace]: handleBackspace,
...
function handleBackspace({currentElement, eventOverrides}) {
...
const keyPressDefaultNotPrevented = fireEvent.keyDown(currentElement(), {
key,
keyCode,
which: keyCode,
...eventOverrides,
})
if (keyPressDefaultNotPrevented) {
fireInputEventIfNeeded({Suggested solution:
Minimally it seems like navigationKey method should have support for not updating the selectionStart when the event default is prevented. However, I see that in other cases in type.js there are other special key event handlers that also do not respect event.preventDefault, namely: handleArrowDown, handleArrowUp, handleEsc, handleSelectAll, and handleSpace. It's worth noting that some of these handlers for the special keys utilize multiple key events (keyDown and keyUp as opposed to keyPress). Perhaps in all cases where they are custom event handlers attached to these native events there should be some checking if the default was prevented.
Related and possibly duplicative
Apologies if this issue has already been captured elsewhere in sufficient detail.