首页 > 解决方案 > 当表单中所需的输入字段为空时,如何模拟未调用提交处理程序?

问题描述

我最近开始使用 Jest 和 react-testing-library 进行测试。但是我遇到了一个小问题。我正在测试我的组件,它看起来像这样:

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. ••••••••••&quot;
            value={password}
            onChange={(event) => setPassword(event.target.value)}
          />
        </label>
        <input type="submit" data-testid="loginButton" value="Login" />
      </form>
    </div>
  );
};

export default Login;

据我了解,提交表单时不会调用 onSubmit,但表单的必填输入字段为空。我通过在 handleSubmit 中插入 console.log('Hey') 来检查此行为,但没有打印任何内容。所以,我认为在我的测试中也应该发生同样的情况。当我检查输入为空时是否未调用提交处理程序时,它应该成功。但事实并非如此。它失败。

这是测试代码:

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

测试“如果字段为空,则不调用提交处理程序”失败。我究竟做错了什么?我在任何地方都找不到有关带有必填输入字段的测试表格的任何信息。我做错了吗?谢谢。

另外,你知道:我在测试中做了 screen.debug() 并且两个输入的值都是 'value=""'

标签: javascriptreactjsunit-testingjestjsreact-testing-library

解决方案


推荐阅读