用玩笑和酵素测试React组件

时间:2020-04-28 19:00:03

标签: javascript reactjs jestjs enzyme

我有以下介绍的组件。我是单元测试的新手。谁能给我任何建议,以及在该组件中应如何测试?我试图浅化渲染,以检查是否存在h2中的文本,但仍然出现错误。

import React, { useEffect } from 'react';
import { Form, Field } from 'react-final-form';
import { useHistory, Link } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import { loginUser, clearErrorMessage } from '../../redux/auth/authActions';
import Input from '../Input/Input';
import ROUTES from '../../routes/routes';
import './LoginForm.scss';

const LoginForm = () => {
  const dispatch = useDispatch();
  const history = useHistory();

  const { loading, isLogged, errorMessage } = useSelector(state => state.auth);

  useEffect(() => {
    if (isLogged) {
      history.push('/');
    }

    return () => {
      dispatch(clearErrorMessage());
    };
  }, [dispatch, history, isLogged]);

  const handleSubmitLoginForm = values => {
    if (!loading) {
      dispatch(loginUser(values));
    }
  };

  const validate = ({ password }) => {
    const errors = {};

    if (!password) {
      errors.password = 'Enter password!';
    }

    return errors;
  };

  return (
    <article className="login-form-wrapper">
      <h2>SIGN IN</h2>
      <Form onSubmit={handleSubmitLoginForm} validate={validate}>
        {({ handleSubmit }) => (
          <form onSubmit={handleSubmit} autoComplete="off" className="login-form">
            <div className="login-form__field">
              <Field name="email" component={Input} type="email" label="E-mail" />
            </div>
            <div className="login-form__buttons">
              <button type="submit" className={loading ? 'button-disabled' : ''}>
                Sign in
              </button>
            </div>
          </form>
        )}
      </Form>
    </article>
  );
};

export default LoginForm;

我愿意接受任何建议:)

1 个答案:

答案 0 :(得分:0)

首先,我不建议在测试中使用shallow,而here是一篇很棒的文章。

我也建议您检出react-testing-library而不是酶,因为它更易于使用。

现在,回答您的问题。您在此处使用reduxreact-router的钩子,因此您需要向测试中的组件提供必要的数据,以便它可以使用这些钩子。让我为您展示一个示例测试(检查h2元素中的文本):

import React from 'react';
import { mount } from 'enzyme';
import {Provider} from 'react-redux';
import {MemoryRouter, Route} from 'react-router';
import LoginForm from './LoginForm';

describe('Login Form', () => {
  it('should have SIGN IN header', () => {
    const store = createStore();
    const component = mount(
      <Provider store={store}>
        <MemoryRouter initialEntries={['/login']}>
          <Route path="/:botId" component={LoginForm} />
        </MemoryRouter>
      </Provider>
    )

    expect(component.find('h2').text()).toEqual('SIGN IN');
  });
});

对此示例进行一些解释。

  • 我正在使用mount而不是shallow,因为我希望在测试中尽可能多地渲染,以便我可以检查所有内容是否可以正常工作。
  • 您可以看到我不是直接渲染我的组件,而是将其与其他组件(来自Provider的{​​react-redux和来自MemoryRouter的{​​{1}})包装在一起。为什么?因为我需要为组件提供上下文。在这种情况下,它是react-routerredux上下文,以便内部使用的数据存在并可以找到(例如,router必须提供某种状态,以便它可以访问useSelector(state => state.auth)属性)。如果您删除其中任何一个,则会收到一些错误消息,指出缺少此上下文,请继续进行检查:)。
  • 有关使用auth上下文进行测试的详细信息,请参见here
  • 在我的示例中,对于使用router进行测试,我没有定义redux函数,因为有几种方法可以实现。其中之一涉及创建在生产应用程序中使用的真实商店。这是我更喜欢的,我的一位同事围绕该主题here写了一篇很棒的文章。另一种是创建某种模拟存储,例如在this article中。同样,我更喜欢第一种方法,但是哪种方法对您更有利。

回答其他问题,以了解在此示例中应该测试什么。有多种可能性。这主要取决于您的业务案例,但是我将在此处测试的示例包括:

  • 在输入中输入内容,单击按钮,然后观察到登录成功(在这种情况下,通过重定向到新路径-createStore
  • 未输入密码并单击按钮-应该显示错误
  • 检查按钮类在加载时是否发生变化
  • 已加载时不要分两次执行登录操作

依此类推...

这实际上只是关于测试的冰山一角,但我希望它能有所帮助,并为您提供一个深入探讨该主题的良好开端。