模拟表单提交时无法读取属性“值”

时间:2019-02-11 20:12:06

标签: reactjs unit-testing redux jestjs enzyme

我正在开玩笑地做一个完整的覆盖范围测试。目前,我已经对几乎所有组件进行了测试,但是有一个handleSubmit函数,在该函数中,我进行了调度以接收表单事件数据,当我运行测试时,我告诉了我

TypeError: Cannot read property 'value' of undefined

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

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

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”,而不是项目和状态。实际上,如果我从调度中删除项目和状态,则测试运行成功

2 个答案:

答案 0 :(得分:2)

好像您在第12行使用item,但是从items中提取event.target

答案 1 :(得分:2)

您选择的处理值的方式有些奇怪。相反,应像这样通过state处理值:Controlled Components

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

旁注:避免在不必要时使用data属性,因为它们会开始使您的DOM变得多余。您可以通过findelementelement.className,... and so on来选择className

工作示例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.js shallowWrapcheckProps是可以在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
  });
});