How to simulate submit handler being not called when required input fields in form are empty?

Viewed 569

I recently started testing with Jest and react-testing-library. But I ran into a little problem. I am testing my component which looks like this:

import React, { useState } from 'react';

const Login = () => {
  const [username, setUsername] = useState<string>('');
  const [password, setPassword] = useState<string>('');

  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
  };

  return (
    <div>
      <form onSubmit={handleSubmit} data-testid="loginForm">
        <label>
          Username:
          <input
            required
            type="text"
            data-testid="usernameText"
            placeholder="e.g. JohnLukeThe3rd"
            value={username}
            onChange={(event) => setUsername(event.target.value)}
            autoFocus
          />
        </label>
        <label>
          Password:
          <input
            required
            type="password"
            data-testid="passwordText"
            placeholder="e.g. ••••••••••"
            value={password}
            onChange={(event) => setPassword(event.target.value)}
          />
        </label>
        <input type="submit" data-testid="loginButton" value="Login" />
      </form>
    </div>
  );
};

export default Login;

As far as I understand onSubmit is not called when form is submitted but form's required input fields are empty. I checked this behavior by inserting a console.log('Hey') in handleSubmit but nothing got printed. So, I thought that in my test the same should happen. When I check if submit handler doesn't get called when input is empty it should succeed. But it doesn't. It fails.

Here's the testing code:

import React from 'react';
import {
  render,
  fireEvent,
  cleanup,
  RenderResult,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Login from '../components/Login';

describe('<Login />', () => {
  let screen: RenderResult;
  beforeEach(() => {
    screen = render(<Login />);
  });
  afterEach(cleanup);

  describe('typing user info', () => {
    it('shows username and password', async () => {
      expect(screen.queryByDisplayValue('JohnLukeThe3rd')).toBeNull();
      await userEvent.type(
        screen.getByLabelText(/username/i),
        'JohnLukeThe3rd',
      );
      await userEvent.type(screen.getByLabelText(/password/i), 'Password123');
      expect(screen.queryByDisplayValue('JohnLukeThe3rd')).toBeInTheDocument();
      expect(screen.queryByDisplayValue('Password123')).toBeInTheDocument();
    });
  });

  describe('clicking login button', () => {
    let loginButton: HTMLElement;
    let submitHandler: jest.Mock;
    let form: HTMLElement;

    beforeEach(() => {
      loginButton = screen.getByText(/login/i);
      submitHandler = jest.fn((e) => e.preventDefault());
      form = screen.getByTestId(/loginForm/i);
      form.onsubmit = submitHandler;
    });


    // problem area here
    it('does not call submit handler if fields empty', () => {
      expect(submitHandler).not.toHaveBeenCalled();
      userEvent.click(loginButton);
      expect(submitHandler).not.toHaveBeenCalled();
    });
    // problem area ends


    it('calls submit handler if fields non-empty', async () => {
      expect(submitHandler).not.toHaveBeenCalled();
      const usernameField = screen.getByTestId('usernameText');
      const passwordField = screen.getByTestId('passwordText');
      await userEvent.type(usernameField, 'JohnLukeThe3rd');
      await userEvent.type(passwordField, 'Password123');
      await userEvent.click(loginButton);
      expect(submitHandler).toHaveBeenCalledTimes(1);
    });
  });
});

The test 'does not call submit handler if fields empty' fails. What am I doing wrong? I couldn't find any information on testing form with required input fields anywhere. Am I doing it wrong? Thanks.

Also, just so you know: I did screen.debug() in the test and both input's value was 'value=""'

0 Answers
Related