簡體   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