-
Notifications
You must be signed in to change notification settings - Fork 254
Description
Environment
@testing-library/user-event@^12.8.1
jest@^26.6.3
jsdom@^16.4.0
What you did
- Created an input element that has a keydown event handler that calls
event.preventDefault()
if theevent.key
isArrowLeft
. - Use
userEvent.type
to enter text into the input element. - Use
userEvent.type
to enter the{arrowleft}
special key. - Attempted to assert that the input's
selectionStart
was 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.