[英]Testing Formik validate function with react-test-renderer
I'm trying to test my validate
function with react-test-renderer
via onChange
and onBlur
.我正在尝试通过
onChange
和onBlur
使用react-test-renderer
测试我的validate
function 。
Here is a simplified test:这是一个简化的测试:
import renderer, { act } from 'react-test-renderer';
const byTypeAndName = (type, name) => elem =>
elem.type === type && elem.props.name === name;
const onSubmit = jest.fn();
const onValidate = jest.fn();
const instance = renderer.create(
<Formik
onSubmit={onSubmit}
initialValues={{
password: '',
password2: '',
}}
validate={onValidate}
>
<Form>
<Field
type="password"
name="password"
autoComplete="new-password"
required
/>
<ErrorMessage name="password" />
</Form>
</Formik>
).root;
await act(async () => {
const password = instance.find(byTypeAndName('input', 'password'));
password.props.onChange('123');
});
expect(onValidate).toBeCalled(); // fails
It turns out that onChange
and onBlur
require the name
of the element passed in as their currentTarget
.事实证明
onChange
和onBlur
需要传入元素的name
作为它们的currentTarget
。
This works correctly:这可以正常工作:
await act(async () => {
const password = instance.find(byTypeAndName('input', 'password'));
password.props.onChange({
currentTarget: {
// `name` is required else Formik doesn't run validation
name: 'password',
value: '123',
},
});
});
Thanks for posting, that answer helped me today: https://stackoverflow.com/a/61625127感谢您的发帖,这个答案今天帮助了我: https://stackoverflow.com/a/61625127
These days, it works for me without "name", though:这些天来,它在没有“名字”的情况下对我有用,但是:
fireEvent.change(field, { target: { value } });
Maybe, a more comprehensive example will be useful to some (this is TypeScript):也许,一个更全面的例子会对某些人有用(这是 TypeScript):
test('if all data is valid, will trigger an API call', async () => {
const { container } = render(<MySubmitForm />);
const uploadButton = screen.getByTitle<HTMLElement>('Do the upload!');
const versionField = container.querySelector('#version');
const name = 'version';
const value = '1.2';
fireEvent.change(versionField!, { target: { value, name } });
userEvent.click(uploadButton);
await waitFor(() => {
expect(versionField).toHaveAttribute('aria-invalid', 'false');
expect(mockDoUpload).toBeCalled();
});
});
What versions etc am I using?我使用的是什么版本等? Here's a bit from my package.json:
这是我的 package.json 的一点:
"dependencies": {
"@emotion/react": "^11.9.0",
"@emotion/styled": "^11.8.1",
"@mui/material": "^5.8.0",
"@mui/x-data-grid": "^5.14.0",
"@react-keycloak/web": "^3.4.0",
"axios": "^0.27.2",
"dotenv-webpack": "^8.0.0",
"formik": "^2.2.9",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-query": "^3.39.1",
"react-router-dom": "^6.3.0",
"typescript": "^4.7.4",
"yup": "^0.32.11"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
"@trivago/prettier-plugin-sort-imports": "^3.2.0",
"@types/jest": "^28.1.2",
"@types/node": "^18.0.0",
"@types/react": "^18.0.14",
"@types/react-dom": "^18.0.5",
"prettier": "^2.7.1",
"react-scripts": "^5.0.1"
}
And, finally, my Formik form code:最后,我的 Formik 表单代码:
import Button from '@mui/material/Button';
import InputLabel from '@mui/material/InputLabel';
import TextField from '@mui/material/TextField';
import { Form, Formik, useFormik } from 'formik';
import React from 'react';
import * as yup from 'yup';
import { useUploadApi } from '../../../hooks/useUploadApi';
const versionFieldName = 'version';
interface Values {
version: string;
}
const validationSchema = yup.object({
version: yup
.string()
.label('Version of the upload file')
.min(3, 'Should be at least 3 characters long, e.g. "1.0"')
.required('A value is required, e.g. "1.0"')
.matches(/^(\d+\.)*\d+\.\d+$/, {
message: 'The version must be digits, separated by dots.'
})
});
const MySubmitForm: React.FC = () => {
const { doUpload } = useUploadApi();
const formikSubmit = (values: Values) => {
const formData = new FormData();
const version = values.version;
formData.append('version', version);
doUpload(formData);
};
const formik = useFormik({
initialValues: {
version: ''
},
validationSchema: validationSchema,
onSubmit: formikSubmit,
validateOnChange: true
});
return (
<Formik
initialValues={formik.initialValues}
validationSchema={validationSchema}
onSubmit={formikSubmit}
validateOnChange={true}
>
<Form encType={'multipart/form-data'} onSubmit={formik.handleSubmit}>
<InputLabel htmlFor={versionFieldName}>Version:</InputLabel>
<TextField
id={versionFieldName}
name={versionFieldName}
value={formik.values.version}
title="Enter version"
onChange={formik.handleChange}
error={formik.touched.version && Boolean(formik.errors.version)}
helperText={formik.touched.version && formik.errors.version}
/>
<Button type="submit" title="Do the upload!">
Upload
</Button>
</Form>
</Formik>
);
};
export default MySubmitForm;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.