Reputation: 2137
I am trying to test that a form submits when the user presses the "Enter" key. I have a passing test for when pressing the Submit
button, but I also want to be sure the form submits with the keyboard (convenience and a11y).
test("should submit when pressing enter", () => {
const handleSubmit = jest.fn();
const { getByLabelText } = render(<App handleSubmit={handleSubmit} />);
const input = getByLabelText("Name:");
fireEvent.change(input, { target: { value: "abc" } });
fireEvent.keyPress(input, { key: "Enter", code: 13, charCode: 13 });
expect(handleSubmit).toHaveBeenCalled();
});
Here is a CodeSandbox with the minimal amount of code needed.
Upvotes: 40
Views: 55256
Reputation: 319
This is a similar solution, in my case I needed the form to call a method when they hit enter, I'm using angular 9.1.
it('should call loginFromKey when enter key is pressed', () => {
fixture.detectChanges();
const loginFromKeySpy = jest.spyOn(component, 'loginFromKey');
const formElement: HTMLElement = queryNativeElement('form');
expect(formElement).toBeTruthy();
formElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }));
expect(loginFromKeySpy).toBeCalled();
});
Upvotes: 0
Reputation: 261
I found a way to force it without any changes or new libraries as follow
const btnDeepPropsKey = Object.keys(
wrapper.getByTestId('input-search')
)?.find(item => item?.includes('__reactProps'))
await waitFor(async () =>
(wrapper.getByTestId('input-search') as any)?.[
btnDeepPropsKey
]?.onKeyPress({ key: 'Enter' })
)
If you can't reach that prop you can log it as well
console.log(wrapper.getByTestId("input-search"))
Note that some states may have been lost if you try to access any other onKeyPress of those props that was shown in log above
Upvotes: 0
Reputation: 19532
I followed the above answer but it's not worked for me because I am using keydown
listener to check my input.
Please remember, use only e.key
not e.keyCode/e.which
its deperecated
. https://stackoverflow.com/a/4471635/8798220
import React, { useState } from "react";
import userEvent from "@testing-library/user-event";
import { render } from "@testing-library/react";
const Input = () => {
const [value, setValue] = useState("");
const handleEnter = (e) => {
if (e.key === "Enter") {
const value = e.target.value;
// API CALLING / LOGIC
}
};
return (
<input
placeholder="Search..."
value={value}
onChange={(e) => setValue(e.target.value)}
onKeyDown={handleEnter}
/>
);
};
it("should submit when pressing enter", async () => {
const text = "hello";
render(<Input />);
const input = screen.getByPlaceholderText("Search...");
await userEvent.type(input, `${text}[Enter]`);
expect(input).toHaveValue(text);
// check about enter logic.
});
Upvotes: 2
Reputation: 748
You are not passing the correct options to fireEvent.keyDown
event. Try to pass keyCode: 13
along with key: "enter"
The following piece of code works for me
it('Check if added todo show in list with label', () => {
render(<TodoApp/>)
const input = screen.getByTestId('add-todo')
fireEvent.change(input, {target: {value: 'Task with label @health'}});
fireEvent.keyDown(input, {key: 'enter', keyCode: 13})
const todoList = screen.getByTestId('todo-list')
expect(todoList).toHaveTextContent('health')
});
Upvotes: -1
Reputation: 806
The following worked for me:
import userEvent from "@testing-library/user-event";
import { render } from "@testing-library/react";
test("should submit when pressing enter", () => {
const handleSubmit = jest.fn();
const { getByLabelText } = render(<App handleSubmit={handleSubmit} />);
const input = getByLabelText("Name:");
userEvent.type(input, "abc{enter}");
expect(handleSubmit).toHaveBeenCalled();
});
Upvotes: 22
Reputation: 5844
You can submit by button but the event target will be the button and not the form. To resolve this:
Submitting the form is only accessible if it has an accessible name. In this sense, using role="my-form"
(ByRole) or aria-label="form's purpose"
(ByLabelText or ByRole("form")).
import "@testing-library/jest-dom/extend-expect";
import { getByRole, fireEvent } from '@testing-library/dom';
test("test form", () => {
const div = document.createElement("div");
div.innerHTML = `
<form role="my-form">
<label for="first_name">
First Name:
<input id="first_name" type="text" />
</label>
<button type="submit">Submit</button>
</form>
`;
const handleSubmit = jest.fn();
div.querySelector('form').onsubmit = handleSubmit;
fireEvent.submit(getByRole(div, "my-form"));
expect(handleSubmit).toHaveBeenCalledTimes(1);
});
Upvotes: 0
Reputation: 1
To simulate keyboard show/hide I first focus on input and then simulate typing. This way you can fire onSubmitEditing
event to simulate submit button pressed on a Keyboard.
import { fireEvent } from '@testing-library/react-native'
const input = getByTestId('input');
fireEvent.focus(input);
fireEvent.changeText(input, 'hello world')
fireEvent.submitEditing(input);
Upvotes: -1
Reputation: 3771
It's a little less clear what the source of the interaction is intended to be, but submit
can be called on the input
and it appears to fix the test in the sandbox:
fireEvent.submit(input);
Upvotes: 14