reactjs - 做出反应。弗罗米克。Material-ui 表单提交事件测试失败使用 react-testing-library
问题描述
我有一个使用 Formik 和 Material-ui 的反应应用程序。我抓住了提交按钮 html 元素,但是 fireEvent 不起作用。我认为问题来自 Formik 库层。'Button' 组件是一个可重复使用的材质 ui 按钮。'change fireEvent' 测试通过。
但是我收到“预期的模拟函数已被调用一次,但它被调用了零次。” '提交fireEvent'的消息。
loginForm.test.js
import { Router, MemoryRouter } from 'react-router-dom';
import { queryByAttribute } from 'react-testing-library';
import React, { render, cleanup, fireEvent } from '../../../setupTests';
import LoginForm from '../../../../components/auth/login/loginForm';
afterEach(cleanup);
const mockSubmit = jest.fn();
const mockKeepMeLoggedIn = jest.fn();
const defaultProps = {
handleSubmit: mockSubmit,
isSubmitting: false,
userData: [],
keepMeLoggedIn: mockKeepMeLoggedIn,
};
const setUp = (props = {}) => {
const setupProps = { ...defaultProps, ...props };
const component = render(
<MemoryRouter>
<LoginForm {...setupProps} />
</MemoryRouter>,
);
const { container, getByTestId, getByText } = component;
const getByName = queryByAttribute.bind(null, 'name');
const usernameInput = getByName(container, 'username');
const passwordInput = getByName(container, 'password');
const getByType = queryByAttribute.bind(null, 'type');
const submitButton = getByType(container, 'submit');
return { component, usernameInput, passwordInput, submitButton };
};
describe('Login Form Component', () => {
it('simulate input type and click the form submit button', () => {
const { usernameInput, passwordInput, submitButton } = setUp();
fireEvent.change(usernameInput, { target: { value: 'yuch' } });
expect(usernameInput.value).toBe('yuch');
fireEvent.change(passwordInput, { target: { value: 'testpwd1234' } });
expect(passwordInput.value).toBe('testpwd1234');
fireEvent.click(submitButton);
expect(mockSubmit).toHaveBeenCalledTimes(1);
});
loginForm.js
...
import { Formik, Form } from 'formik';
/* --- Components --- */
import FormikField from '../../../shared/form/formikField';
import PasswordField from '../../../shared/form/passwordField';
import Button from '../../../shared/form/formButton';
const LoginForm = ({
keepMeLoggedIn,
keepLoggedIn,
userData,
handleSubmit,
loginValidation,
}) => {
const foundUsername = userData.length !== 0 ? userData[0].username : '';
const values = { username: foundUsername, password: '' };
return (
<Formik
initialValues={values}
validationSchema={loginValidation}
onSubmit={handleSubmit}
>
{({ isSubmitting }) => (
<div className="login-container">
<Form
className="flex flex-column-m center"
data-testid="form"
>
<FormikField
label="아이디"
name="username"
type="text"
icon="filledUser"
styleName="textField"
required
/>
...
<Button
typeValue="submit"
variantValue="contained"
buttonName="로그인"
className="login-btn"
isSubmitting={isSubmitting}
/>
</Form>
...
</div>
)}
</Formik>
);
};
按钮.js
import React from 'react';
import Button from '@material-ui/core/Button';
import { withStyles } from '@material-ui/core/styles';
const styles = theme => ({
...
});
const FormButton = ({
typeValue,
variantValue,
buttonName,
width,
isSubmitting,
classes,
className,
}) => {
...
return (
<Button
type={typeValue}
variant={variantValue}
color="primary"
size="small"
style={widthStyle}
className={`${className} ${classes.button}`}
disabled={isSubmitting}
>
{buttonName}
</Button>
);
};
我尝试过的事情。
[获取提交按钮]
const getByType = queryByAttribute.bind(null, 'type'); const submitButton = getByType(container, 'submit'); -> console.log(submitButton) // HTMLButtonElement -> fireEvent.click(submitButton)
2.
const submitButton = getByText('로그인');
-> console.log(submitButton) // HTMLSpanElement
-> fireEvent.click(submitButton)
const submitButton = getByTestId('form'); -> console.log(submitButton) // HTMLFormElement -> fireEvent.submit(submitButton)
[ form ] 1. html 'form' 而不是 Formik 的 'Form'。
import { Formik, Form } from 'formik';
<Formik
initialValues={values}
validationSchema={loginValidation}
onSubmit={handleSubmit}
>
{({ handleSubmit, isSubmitting }) => (
<div className="login-container">
<form
className="flex flex-column-m center"
onSubmit={handleSubmit}
data-testid="form"
>
...
</form>
解决方案
它实际上与 Formik 如何处理提交有关。由于它使用的是 Promise,因此在调用 onSubmit 调用之前至少需要一个滴答声。
测试库有一个等待给定时间的实用程序。但是由于我们只需要等待一个滴答声,我们可以省略持续时间。
首先,从 react-testing-library 导入 wait。然后制作你的it
函数async
并用函数包装期望部分wait
。
我已经用提交按钮上的点击事件对此进行了测试。
// import wait
import { wait } from 'react-testing-library';
// add async
it('simulate input type and click the form submit button', async () => {
const { usernameInput, passwordInput, submitButton } = setUp();
fireEvent.change(usernameInput, { target: { value: 'yuch' } });
expect(usernameInput.value).toBe('yuch');
fireEvent.change(passwordInput, { target: { value: 'testpwd1234' } });
expect(passwordInput.value).toBe('testpwd1234');
fireEvent.click(submitButton);
// wrap expect in `await wait`
await wait(() => {
expect(mockSubmit).toHaveBeenCalledTimes(1);
});
});
推荐阅读
- informatica-powercenter - 在开始工作流之前,我们是否需要在 Informatica 中创建目标输出文件?
- docker - Mesos 上的马拉松未能更新容器的资源
- wordpress - 定义了帖子表的 Wordpress 和插件(发明者)
- r - 多元线性回归:绘制一条带置信区间的直线
- react-native - 隐藏/显示动态创建的视图 - React Native
- css - 发出媒体请求时使项目处于活动状态
- php - api平台 | 有没有办法在特定操作或路由上禁用 WriteListener?
- nginx - Nginx 在特定时间自动停止
- excel - 遍历字典时类型不匹配
- javascript - 字符串删除jQuery