【问题标题】:Cannot read property 'value' when simulating a form submit模拟表单提交时无法读取属性“值”
【发布时间】:2019-07-05 09:50:12
【问题描述】:

我正在尝试用 jest 进行完整的伊斯坦布尔覆盖率测试。目前我有一个几乎所有测试过的组件,但是有一个 handleSubmit 函数,我在其中进行调度接收表单事件数据,当我运行测试时它告诉我

TypeError: Cannot read property 'value' of undefined

      10 |             payload: {
      11 |                 name: name.value,
    > 12 |                 item: item.value, 
         |                            ^
      13 |                 status: status.value  }
      14 |         })
      15 |     }

我正在加载一个 mockstore,安装了所有组件,所有组件都经过测试,但提交仍然失败。我的测试功能很简单:

it('testing submit', () => {
const form = component.find(`[data-test="submit"]`).first()
form.simulate('submit')
... and continues expecting some existences, but there aren't problems there

我已经试过了:enzyme simulate submit form, Cannot read property 'value' of undefined

并尝试解析模拟动作中的事件值...

完整的模块代码是……

class Filters extends Component {
    handleSubmit = event => {
        event.preventDefault()
        const {name, items, status} = event.target;
        this.props.dispatch({
            type: 'SEARCH_PLAYER',
            payload: {
                name: name.value,
                item: item.value, 
                status: status.value  }
        })
    }


    render() {
        return(
            <div>
                <form onSubmit={this.handleSubmit} data-test="submit">
                    <div className="form-group col-md-12 text-center"> ...

另一个真正疯狂的事情是我的测试识别“event.target.name.value”而不是项目和状态。事实上,如果我从调度中删除项目和状态,测试就会成功运行。

【问题讨论】:

    标签: reactjs unit-testing redux jestjs enzyme


    【解决方案1】:

    看起来您在第 12 行使用了item,但从event.target 中提取了items

    【讨论】:

      【解决方案2】:

      您选择处理值的方式有点奇怪。相反,通过state 处理值,如下所示:Controlled Components

      然后您可以测试this.props.dispatch() 是否使用正确的值调用。

      旁注:在不必要的时候避免使用data 属性,因为它们会开始用多余的属性堵塞你的DOMfind element, element.className, className, ...and so on 有很多选择。

      工作示例https://codesandbox.io/s/5j4474rkk(您可以通过单击屏幕左下方的Tests 标签来运行下面定义的测试。

      components/Form/Form.js

      import React, { Component } from "react";
      import PropTypes from "prop-types";
      
      export default class Form extends Component {
        state = {
          test: ""
        };
      
        static propTypes = {
          dispatch: PropTypes.func.isRequired
        };
      
        handleChange = ({ target: { name, value } }) => {
          this.setState({ [name]: value });
        };
      
        handleSubmit = e => {
          e.preventDefault();
          this.props.dispatch({
            type: "SEARCH_PLAYER",
            payload: {
              test: this.state.test
            }
          });
        };
      
        render = () => (
          <form onSubmit={this.handleSubmit} className="form-container">
            <h1>Form Testing</h1>
            <input
              className="uk-input input"
              type="text"
              name="test"
              placeholder="Type something..."
              onChange={this.handleChange}
              value={this.state.test}
            />
            <button type="submit" className="uk-button uk-button-primary submit">
              Submit
            </button>
          </form>
        );
      }
      

      components/Form/__tests__/Form.jsshallowWrapcheckProps 是自定义函数,可以在 test/utils/index.js 中找到)

      import React from "react";
      import { shallowWrap, checkProps } from "../../../test/utils";
      import Form from "../Form";
      
      const dispatch = jest.fn();
      
      const initialProps = {
        dispatch
      };
      
      const initialState = {
        test: ""
      };
      
      const wrapper = shallowWrap(<Form {...initialProps} />, initialState);
      describe("Form", () => {
        it("renders without errors", () => {
          const formComponent = wrapper.find(".form-container");
          expect(formComponent).toHaveLength(1);
        });
      
        it("does not throw PropType warnings", () => {
          checkProps(Form, initialProps);
        });
      
        it("submits correct values to dispatch", () => {
          const name = "test";
          const value = "Hello World!";
          const finalValues = {
            type: "SEARCH_PLAYER",
            payload: {
              [name]: value
            }
          };
      
          wrapper.find("input").simulate("change", { target: { name, value } }); // simulates an input onChange event with supplied: name (event.target.name) and value (event.target.value)
      
          wrapper
            .find(".form-container")
            .simulate("submit", { preventDefault: () => null }); // simulates a form submission that has a mocked preventDefault (event.preventDefault()) to avoid errors about it being undefined upon form submission
      
          expect(dispatch).toBeCalledWith(finalValues); // expect dispatch to be called with the values defined above
        });
      });
      

      【讨论】:

        猜你喜欢
        • 2017-05-08
        • 1970-01-01
        • 2020-03-12
        • 2020-10-26
        • 2021-07-06
        • 2015-12-17
        • 2021-07-31
        • 2020-04-06
        • 1970-01-01
        相关资源
        最近更新 更多