[英]React. Fromik. Material-ui form submit event testing fails using react-testing-library
I have a react app using Formik and Material-ui. 我有一个使用Formik和Material-ui的React应用。 I grabbed the submit button html element, But fireEvent is not working.
我抓住了提交按钮html元素,但是fireEvent无法正常工作。 I think the issue is coming from Formik library layer.
我认为问题出在Formik库层。 'Button' component is a reusable material ui button.
“按钮”组件是可重复使用的材质ui按钮。 'change fireEvent' tests are passed.
通过了“ change fireEvent”测试。
But I receive 'Expected mock function to have been called one time, but it was called zero times.' 但是我收到“预期的模拟函数被调用过一次,但被调用了零次。” message for 'submit fireEvent'.
消息“提交fireEvent”。
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);
});
...
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>
);
};
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>
);
};
[ To get submit button ] [获取提交按钮]
const getByType = queryByAttribute.bind(null, 'type'); const submitButton = getByType(container, 'submit'); -> console.log(submitButton) // HTMLButtonElement -> fireEvent.click(submitButton)
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' instead of 'Form' from Formik. [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>
It actually has to do with how Formik handles the submit. 实际上,它与Formik处理提交的方式有关。 Since it is using a promise, it takes at least a tick before the onSubmit call is being called.
由于它使用了Promise,因此在调用onSubmit调用之前至少要花费一个勾号。
Testing library has a wait utility which waits for a given time. 测试库具有一个wait实用程序,它会等待给定的时间。 But since we only need to wait for a single tick, we can just omit the duration.
但是由于我们只需要等待一个滴答声,我们就可以省略持续时间。
First, import wait from react-testing-library. 首先,从react-testing-library导入等待。 Then make your
it
function async
and wrap the expect part with a wait
function. 然后使您的
it
函数async
并用wait
函数包装期望部分。
I've tested this with a click event on the submit button. 我已经通过“提交”按钮上的click事件进行了测试。
// 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);
});
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.