繁体   English   中英

是的,Formik 在使用 Jest 和 React 测试库进行测试时没有验证表单

[英]Yup and Formik not validating form when testing with Jest and React Testing Library

我最近将 Jest 更新为最新的 28. 版本,我的单元测试停止工作,特别是在使用 Yup 和 Formik 验证我的表单并显示错误消息的测试中。 如果我回滚 Jest 版本,它确实可以正常工作。

这是我的 package.json 依赖项

"dependencies": {
    "@chakra-ui/icons": "^1.0.16",
    "@chakra-ui/react": "^1.6.10",
    "@emotion/react": "^11.5.0",
    "@emotion/styled": "^11.3.0",
    "@types/styled-components": "^5.1.15",
    "axios": "^0.24.0",
    "formik": "^2.2.9",
    "framer-motion": "^4.1.17",
    "graphql": "^16.3.0",
    "graphql-request": "^4.0.0",
    "next": "^12.2.0",
    "next-i18next": "^10.2.0",
    "nookies": "^2.5.2",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "react-icons": "^4.3.1",
    "react-number-format": "^4.9.3",
    "react-query": "^3.34.6",
    "styled-components": "^5.3.3",
    "yup": "^0.32.11"
  },
  "devDependencies": {
    "@testing-library/dom": "^8.16.0",
    "@testing-library/jest-dom": "^5.16.4",
    "@testing-library/react": "^12.1.5",
    "@testing-library/react-hooks": "^7.0.2",
    "@testing-library/user-event": "^13.5.0",
    "@types/node": "18.0.5",
    "@types/react": "17.0.33",
    "eslint": "7.32.0",
    "eslint-config-next": "12.0.1",
    "eslint-config-prettier": "^8.3.0",
    "jest": "^28.1.3",
    "jest-environment-jsdom": "^28.1.3",
    "msw": "^0.39.2",
    "react-test-renderer": "^17.0.2",
    "typescript": "4.4.4"
  }

这是我的 jest.config.js

// jest.config.js
const nextJest = require('next/jest');

const createJestConfig = nextJest({
  // Provide the path to your Next.js app to load next.config.js and .env files in your test environment
  dir: './',
});

// Add any custom config to be passed to Jest
const customJestConfig = {
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  // if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
  moduleNameMapper: {
    // Handle module aliases (this will be automatically configured for you soon)
    '^@/components/(.*)$': '<rootDir>/components/$1',

    '^@/pages/(.*)$': '<rootDir>/pages/$1',
  },
  moduleDirectories: ['node_modules', '<rootDir>/'],
  testEnvironment: 'jsdom',
};

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig);

这是我失败的测试


  it('validates empty form values', async () => {
    server.use(
      graphql.query('GetAllProducts', (req, res, ctx) => {
        return res(ctx.status(200), ctx.data(getProductsResponseBody));
      })
    );

    const signupResult = renderWithDefaultClient(<ProductPage />);

    await userEvent.click(
      await signupResult.findByText('addProductButtonLabel')
    );

    await userEvent.click(await signupResult.findByText('createButtonLabel'));

    expect(await signupResult.findByText('required')).toBeInTheDocument();
  });

这是我正在测试的组件

import {
  Button,
  FormControl,
  FormErrorMessage,
  FormLabel,
  HStack,
  Input
} from '@chakra-ui/react';
import { Field, Form, Formik } from 'formik';
import { useTranslation } from 'next-i18next';
import React from 'react';
import * as Yup from 'yup';
import {
  FormProduct,
  IProduct
} from '../../interfaces/pages/product/ProductInterface';
import { returnEmptyStringIfNull } from '../../utils/StringUtils';
  
  const ProductForm = () => {
    const { t } = useTranslation(['product', 'shared']);
  
    const ProductFormSchema = Yup.object().shape({
      code: Yup.string().max(45, t('characterLimitFortyFive', { ns: 'shared' })),
      name: Yup.string()
        .max(45, t('characterLimitFortyFive', { ns: 'shared' }))
        .required(t('required', { ns: 'shared' })),
    });
  
    const initialValues: FormProduct = {
      code: returnEmptyStringIfNull(product.code),
      name: returnEmptyStringIfNull(product.name),
    };
  
    const onSubmitForm = (productForm: FormProduct) => {
        createMutation.mutate(productForm);
    };
  
    return (
      <>
        <Formik
          initialValues={initialValues}
          validationSchema={ProductFormSchema}
          onSubmit={(form) => {
            onSubmitForm(form);
          }}
        >
          {(props) => (
            <Form data-testid='productForm' style={{ marginTop: '20px' }}>
              <HStack spacing={'24px'} w={'2xl'} mb={3}>
                <Field name='code'>
                  {
                    // @ts-ignore
                    ({ field, form }) => (
                      <FormControl
                        isInvalid={form.errors.code && form.touched.code}
                      >
                        <FormLabel htmlFor='code'>{t('codeLabel')}</FormLabel>
                        <Input {...field} id='code' data-testid='code' />
                        <FormErrorMessage>{form.errors.code}</FormErrorMessage>
                      </FormControl>
                    )
                  }
                </Field>
                <Field name='name'>
                  {
                    // @ts-ignore
                    ({ field, form }) => {
                      return (
                        <FormControl
                          isInvalid={form.errors.name && form.touched.name}
                          isRequired
                        >
                          <FormLabel htmlFor='name'>{t('nameLabel')}</FormLabel>
                          <Input {...field} id='name' data-testid='name' />
                          <FormErrorMessage>{form.errors.name}</FormErrorMessage>
                        </FormControl>
                      );
                    }
                  }
                </Field>
              </HStack>
              <HStack spacing={'24px'} mt={4}>
                <Button colorScheme='blue' type='submit'>
                  {t('createButtonLabel', { ns: 'shared' })}
                </Button>
              </HStack>
            </Form>
          )}
        </Formik>
      </>
    );
  };
  
  export default ProductForm;
  

如您所见,我正在尝试验证是否确实显示了所需的错误消息,但是在我更新 jest 并安装 jsdom 后它不起作用。

它通过安装 Jest 27.5.1 再次起作用,我所有失败的测试都是由于 formik 的错误而没有显示。

显然 JSDOM 现在正在验证 HTML5 表单输入,当它具有所需的属性集时,在我取出 ChakraUI 上的“isRequired”后它起作用了,即使这是在真实浏览器环境中所期望的,但以前的版本就像我使用的那样没有按照应有的方式验证表单。

可以在这里看到对 JSDOM 的引用: https ://github.com/jsdom/jsdom/issues/2898

做了一些搜索,我发现了这个 GitHub 问题: https://github.com/jaredpalmer/formik/issues/544

尝试将noValidate添加到您的表单组件。 我在进行更改时通过了它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM