【问题标题】:A beginner facing error while testing react material ui form with react unit test初学者在使用反应单元测试测试反应材料 ui 表单时面临错误
【发布时间】:2021-04-07 13:55:29
【问题描述】:

我有一个只有一个文本字段的简单表单。我使用 react material ui 库和 formik 进行验证和验证。我无法通过使用浅酶法获得表单中的文本字段。不知道我做错了什么。

declarationForm.js

import React, { useState, useEffect } from 'react';
import * as Yup from 'yup';
import { Formik } from 'formik';
import { useNavigate, Prompt } from "react-router-dom";
import { Box, Button, Card, CardContent, CardHeader, Divider, Grid, TextField } from '@material-ui/core';
import { get_declarations_details, put_declarations_details } from './../../utils/service';

const DeclarationsForm = () => {

  const [ initialData, setInitialData ] = useState({ declarations:'' });

  useEffect(()=>{
    get_data();
  },[]);

  let navigate = useNavigate();

  const get_data = async() =>{
    try {
      const result = await get_declarations_details();
      if(result){
        setInitialData({
          ...initialData,
          ...result,
        });
      }
    } catch (error) {
      console.log(error);
    }
  }

  const put_data = async(data) =>{
    try {
      const result = await put_declarations_details(data);
      if(result){
        setInitialData({
          ...initialData,
          ...result,
        });
      } 
    } catch (error) {
      console.log(error);
    }
  }

  return (
    <Formik
      initialValues={initialData}
      enableReinitialize={true}
      validationSchema={
      Yup.object().shape({
        declarations: Yup.string().max(255).required('Declarations is required'),
        })
      }
      onSubmit={(values) => {
        if(JSON.stringify(initialData) !== JSON.stringify(values)){
          put_data(values);
        }
        navigate(`/summary`, { replace: true })
      }}
    >
    {({
      errors,
      handleBlur,
      handleChange,
      handleSubmit,
      isSubmitting,
      touched,
      isValid,
      values
      }) => (
      <form onSubmit={handleSubmit}>
      <Card>
        <Prompt
          when={!isValid}
          message="Are you sure you want to proceed without saving?"
        />
        <CardHeader
          subheader="The information can be edited"
          title="Declarations"
        />
        <Divider />
        <CardContent>
          <Grid
            container
            spacing={3}
          >
            <Grid
              item
              md={6}
              xs={12}
            >
              <TextField
                fullWidth
                error={Boolean(touched.declarations && errors.declarations)}
                helperText={touched.declarations && errors.declarations}
                label="Declarations"
                name="declarations"
                handleBlur={handleBlur}
                onChange={handleChange}
                required
                value={values.declarations}
                variant="outlined"
              />
            </Grid>
          </Grid>
        </CardContent>
        <Divider />
        <Box
          display="flex"
          justifyContent="flex-end"
          p={2}
        >
          <Button
            color="primary"
            variant="contained"
            disabled={isSubmitting}
            onClick={handleSubmit}
          >
            Continue
          </Button>
        </Box>
      </Card>
      </form>
      )}
    </Formik>
  );
};

export default DeclarationsForm;

我的测试文件如下

declarationForm.test.js

import { createShallow } from '@material-ui/core/test-utils';
import React from 'react';
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import DeclarationsForm from './declarationsForm';
import { ThemeProvider as MuiThemeProvider } from '@material-ui/core/styles';
import { TextField } from '@material-ui/core';

configure({ adapter: new Adapter() });

describe('<DeclarationsForm />', () => {
  let shallow, wrapper;

  beforeAll(() => {  // This is Mocha; in Jest, use beforeAll
    shallow = createShallow();
  });

  beforeEach(() => {
    wrapper = shallow(<MuiThemeProvider><DeclarationsForm /></MuiThemeProvider>);
  });
  it('should work', () => {
    
    console.log(wrapper.find(TextField).debug());
    expect(wrapper.find(TextField)).toHaveLength(1);
  });
});

当我运行下面的测试是结果

 FAIL  src/views/declarations/declarationsForm.test.js
  ● Console

    console.error node_modules/prop-types/checkPropTypes.js:20
      Warning: Failed prop type: The prop `theme` is marked as required in `ThemeProvider`, but its value is `undefined`.
          in ThemeProvider (at declarationsForm.test.js:19)
    console.log src/views/declarations/declarationsForm.test.js:23
      

  ● <DeclarationsForm /> › should work

    expect(received).toHaveLength(expected)

    Expected length: 1
    Received length: 0
    Received object: {}

      22 |     
      23 |     console.log(wrapper.find(TextField).debug());
    > 24 |     expect(wrapper.find(TextField)).toHaveLength(1);
         |                                     ^
      25 |   });
      26 | });

      at Object.<anonymous> (src/views/declarations/declarationsForm.test.js:24:37)

wrapper is unable to find text field or form. 

How to debug this? What is the right approach to write test when we have also used useNavigate method within the component?

【问题讨论】:

  • 看起来您可能需要在测试中将 theme 属性传递给 MuiThemeProvider 。我很久以前就放弃了 Enzyme,但也许如果你做了一个完整的 mountshallow,我认为 shallow 安装对子组件的处理方式不同,并且不会完全渲染它们。

标签: reactjs jestjs material-ui enzyme formik


【解决方案1】:

就像上面的Drew's 一样,你需要传入一个theme 属性来解决Failed prop type 错误。

shallow(<MuiThemeProvider theme={{}}><DeclarationsForm /></MuiThemeProvider>);

另外,wrapper 找不到 TextField,因为您正在使用 shallow。使用dive() 展开嵌套的form

console.log(wrapper.find(Formik).dive().find(TextField).debug());

【讨论】:

    猜你喜欢
    • 2020-07-07
    • 2017-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-03
    • 2016-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多