React-testing-library: Form does not submit when pressing enter

Created on 16 Dec 2019  路  11Comments  路  Source: testing-library/react-testing-library

  • react-testing-library version: 9.4.0
  • react version: 16.12.0
  • node version: CodeSandbox default
  • npm (or yarn) version: CodeSandbox default

Relevant code or config:

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();
});

What you did:

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

What happened:

The form submits properly in the browser, but it does not submit in the test.

Reproduction:

Here is a CodeSandbox with the minimal amount of code needed.

All 11 comments

Why not submit the form directly? Are you trying to test the browser here?

Not saying that what you want should not be provided. If you really want this, maybe take a look at @testing-library/user-event (though I cannot guarantee it already does this, but at least its intention is to provide these kind of more browser-like event sequences).

But if what you want to test is that when you submit the form certain thing happens, then just submit the form. Barring some weird overrides to browser defaults in the code being tested, you know that browsers will allow to submit a form in various ways.

I want to take the @kentcdodds approach of mimicking what the user would do and that would be pressing "Enter" which would then submit the form. If I just submit the form manually in the test, then how can I be sure that "Enter" would do the same?

If I just submit the form manually in the test, then how can I be sure that "Enter" would do the same?

That's standard browser behavior. Imagine that in your test you'd have to click on the input field, or focus on it before typing the value you want. The way you're setting the value in that input field is also not how the user would do it. My point is that there are acceptable shortcuts that you're taking in your tests all the time. Unless your components are meddling with standard browser behavior, you do not need to go that far.

Under your logic, If you just set the value directly on the input in this line...

fireEvent.change(input, { target: { value: "abc" } });

...how can you be sure that when the user types it one key at a time the input will end up with that value?

Again, not trying to tell you that you should not do that in your test. If you really want that, maybe take a look at the suggested user-event lib. I'm not sure if it handles that scenario, but it's more of the aim of that lib to give you that.

I just feel like if I fired a submit event manually that I can not necessarily be confident that the form is able to be submitted on pressing "Enter". I checked out the user-event library and it does not seem they support pressing "Enter".

Edit: Reason I want to explicitly test this behavior is because we introduced a bug that overrode this native browser behavior and I want to be sure that does not happen again.

This seems to be a limitation of enzyme as well.

Reason I want to explicitly test this behavior is because we introduced a bug that overrode this native browser behavior and I want to be sure that does not happen again.

Ok, this is what I'm talking about. Then you need to do this.

But again, I think that what you want is a bit out of the scope of RTL, and either user-event could help you (if it doesn't do that yet, then open an issue over there). Or if you want that level of more real-life testing, https://cypress.io is the real deal. I'm leaning more and more towards it.

Thanks for the help. I will keep an eye on the user-event library for "Enter" key support. In the meantime, the team and I are discussing using cypress to test this behavior. 馃憤

Nice. I'll be closing this, but feel free to continue the conversation if needed, or even re-open if you feel this is still an issue concerning RTL in some way.

Hi, I have also encoutered this problem. I need to test that a form is able to submit when pressing enter from an input, using fireEvent.submit is not an option because of what I'm trying to test.

I have an input which has to be limited to 5 characters long, the implementation looks like this:

<input
  onKeyPress={(event: React.KeyboardEvent<HTMLInputElement>): void => {
    if (event.currentTarget.value.length >= 5) {
      event.preventDefault();
    }
  }}
  // ... other props
  />

this makes the form impossible to submit using Enter, the fix is to implement it like this:

<input
  onKeyPress={(event: React.KeyboardEvent<HTMLInputElement>): void => {
    if (event.currentTarget.value.length >= 5) {
      if (event.key !== 'Enter') {
        event.preventDefault();
    }
  }}
  // ... other props
  />

I've been unable to write a regression test for this behavior, using fireEvent.submit on the input will make the form submit even if the fix is not applied.

Please, consider reopening this issue.

Try using userEvent.type('{enter}') from https://github.com/testing-library/user-event

I haven't tried it, but I think it should work.

Yep it works :) Here's a Demo.

Was this page helpful?
0 / 5 - 0 ratings