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

form submitted despite required input #2898

Open
eps1lon opened this issue Mar 11, 2020 · 14 comments
Open

form submitted despite required input #2898

eps1lon opened this issue Mar 11, 2020 · 14 comments

Comments

@eps1lon
Copy link
Contributor

eps1lon commented Mar 11, 2020

Basic info:

  • Node.js version: 10.16.0
  • jsdom version: 16.2.1

Minimal reproduction case

https://runkit.com/eps1lon/5e6969234944ab001d7f7d5e

const { JSDOM } = require('jsdom');

const {window} = new JSDOM(`
<form>
    <input name="test" type="radio" value="1" required />
    <input name="test" type="radio" value="2" required />
    <button type="submit">Submit</button>
</form>
`);
const document = window.document;

const form = document.querySelector("form");
form.addEventListener("submit", event => {
  // without preventDefault it crashes
  event.preventDefault();
  console.log("submit");
});

const submit = document.querySelector("button");
submit.addEventListener("click", () => console.log("click"));
submit.dispatchEvent(new window.MouseEvent("click"));

Logs:

click
submit

Same issue for required textbox: https://runkit.com/eps1lon/5eff0e98c6645d001a3fabc5

How does similar code behave in browsers?

In Chrome 80 https://codesandbox.io/s/browser-submit-required-9w3z2

logs:

click

Same repro for a textbox: https://codesandbox.io/s/browser-submit-required-textfield-xv2fw

Context

Reported in testing-library/react-testing-library#607 and testing-library/react-testing-library#729

@domenic
Copy link
Member

domenic commented Mar 14, 2020

Nice find. A fix would be most welcome.

// without preventDefault it crashes

Are you sure? It should just output a console message saying that form submission is not implemented. If it crashes, that's a separate bug worth filing.

@eps1lon
Copy link
Contributor Author

eps1lon commented Mar 14, 2020

Are you sure? It should just output a console message saying that form submission is not implemented.

Forgot to link the runkit. In that one (https://runkit.com/eps1lon/5e6969234944ab001d7f7d5e) it's crashing without preventDefault.

@domenic
Copy link
Member

domenic commented Mar 14, 2020

I don't see a crash there, just a console logging of an error object.

@eps1lon
Copy link
Contributor Author

eps1lon commented Mar 14, 2020

I don't see a crash there, just a console logging of an error object.

Yeah I didn't investigate further. I don't know how I would distinguish this in runkit anyway. I'd have to try locally I think.

@eps1lon eps1lon changed the title form submitted despite required radio form submitted despite required input Jul 3, 2020
@eps1lon
Copy link
Contributor Author

eps1lon commented Jul 3, 2020

Same issue with a textbox https://runkit.com/eps1lon/5eff0e98c6645d001a3fabc5

@bwaldvogel
Copy link

I also hit this issue that the form is submitted although it’s actually invalid. (Actually doing something as described in testing-library/react-testing-library#729)

Has anyone come up with a workaround? I would appreciate any hint.

@jthannah
Copy link

Has any progress been made on this? I'm experiencing the issue with an invalid url in a type="url" input element. I enter an invalid url however the form still submits.

@griffico
Copy link

griffico commented Jan 6, 2022

Ping! Just spent half a day struggling before we realized this was an RTL issue, not ours. I'd love to hear if there has been any work done on this issue. Thankfully we can cover ourselves with a Cypress test pretty easily, but that's not ideal.

@domenic
Copy link
Member

domenic commented Jan 6, 2022

https://mobile.twitter.com/slicknet/status/782274190451671040

@tiborsaas-tw
Copy link

tiborsaas-tw commented Jun 23, 2022

It's possibly related, we are experiencing a similar issue. It's an email type input field and the test fails when we want to assert that the invalid error shows up. The Formik validator function doesn't run, only if I remove the type=email attribute from the input field. Everything works correctly if I test it in the browser manually.

Sorry, I can't provide an example at the moment.

I've updated JSDOM to 20.0.0 but unfortunately this did not solve the issue.

@Zekumoru
Copy link

I'm using Jest and React, and the workaround I did is to fire the invalid events ourselves.

Example:

import '@testing-library/jest-dom';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { act } from 'react-dom/test-utils';

describe('Invalid event on form submit', () => {
  test('that the form triggers an invalid event if input elements are invalid', async () => {
    // Problem:
    //   <form> is submitted even if inputs are invalid hence the
    //   act below triggers the needed invalid events for this test
    // GitHub issue: jsdom/jsdom#2898
    const handleInvalid = jest.fn();
    const user = userEvent.setup();
    render(
      <form onSubmit={(e) => e.preventDefault()}>
        <label htmlFor="input">Input:</label>
        {/* Notice that the input here is required*/}
        <input id="input" type="text" onInvalid={handleInvalid} required />
        <button>Submit</button>
      </form>
    );

    // submitting the form will STILL submit and
    // won't call that it's invalid (since the input
    // is empty and it is required)
    await user.click(screen.getByRole('button'));

    expect(() => {
      expect(handleInvalid).toHaveBeenCalledTimes(1);
    }).toThrow(/expected number of calls/i);

    // the workaround is to fire the invalid event
    // ourselves, it is OPTIONAL to click the submit button
    // but be aware that it'll fire submit events
    // (Note: In an actual browser, if a form is invalid,
    //   because one of its input elements is invalid,
    //   it won't fire submit events)
    await user.click(screen.getByRole('button'));
    act(() => {
      screen.getByLabelText(/input/i).dispatchEvent(
        new InputEvent('invalid', {
          bubbles: true,
          cancelable: true,
        })
      );
    });

    expect(handleInvalid).toHaveBeenCalledTimes(1);
  });
});

@albertnev
Copy link

albertnev commented May 10, 2023

Any news for this issue that's been opened for 3 years? I'm trying to test right now a form with fields that do not have the correct data (they do not match the pattern specified) and the form is triggering the onSubmit anyway. If I query the form and check for its validity (just to confirm everything is as expected), it is invalid:

expect(screen.getByTestId('supplier-register-form')).toBeValid();
-------
Received element is not currently valid:
      <form data-testid="supplier-register-form" />

So if the form is not valid, the onSubmit should not be executed, but it is executing and it's making the test fail.

Any workaround or fix available for this?

@AndrewEastwood
Copy link

hey! any updates on that?

@domenic
Copy link
Member

domenic commented Nov 18, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants