简体   繁体   English

测试 Formik 使用 react-test-renderer 验证 function

[英]Testing Formik validate function with react-test-renderer

I'm trying to test my validate function with react-test-renderer via onChange and onBlur .我正在尝试通过onChangeonBlur使用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 .事实证明onChangeonBlur需要传入元素的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.

相关问题 使用react-test-renderer进行快照测试 - snapshot testing with react-test-renderer 使用 react-test-renderer 测试异步 componentDidMount() - Testing async componentDidMount() with react-test-renderer 使用 React-Test-Renderer 测试嵌套的 React 组件 - Testing of Nested React components using React-Test-Renderer 如何使用@testing-library/react 和 react-test-renderer 测试由 Redux 状态控制的输入值? - how to test input value controlled by Redux state using @testing-library/react and react-test-renderer? react-test-renderer不正确的对等依赖 - react-test-renderer incorrect peer dependency react-test-renderer 的 create() 与 @testing-library/react 的 render() - react-test-renderer's create() vs. @testing-library/react's render() 将 react-test-renderer 与 react-testing-library 一起使用有什么意义吗? - Is there any point for using react-test-renderer with react-testing-library? react-test-renderer浅渲染器在生产模式下不可用 - react-test-renderer shallow renderer is not available in production mode 如何在 react-test-renderer 渲染器实例中查找文本元素? - How to find for a text element, in react-test-renderer renderer instance? 使用 react-test-renderer<Switch> 导致“无状态功能组件无法提供参考”警告 - Using react-test-renderer with <Switch> causes "Stateless function components cannot be given refs" warning
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM