用酶测试简单的Redux-Form(值在哪里?) [英] Testing simple Redux-Form with Enzyme (where is value??)

查看:65
本文介绍了用酶测试简单的Redux-Form(值在哪里?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有连接到redux示例的最简单的redux形式:

I have the most simple redux-form connected to redux example :

import * as React from 'react';
import { Field, reduxForm } from 'redux-form';
import { connect } from 'react-redux';

class TestForm extends React.PureComponent {
    render() {
        return (
            <form>
                <Field component={Input} name={'testField'}/>
            </form>
        );
    }
}

class Input extends React.PureComponent {
    render(): React.Node {
        let { input } = this.props;
        // input = {name: 'testField', value: 'test value'};
        return (
                <input name={input.name} value={input.value} type='text' onChange={()=>1}/>
        );
    }
}

const mapStateToProps = ({ testForm }) => {
    return {
        initialValues: testForm,
    };
};

export const TestFormWithReduxForm = reduxForm({ form: 'test form'})(TestForm);

export default connect(mapStateToProps)(TestFormWithReduxForm);

请注意以下几点:


  • 我有自己的自定义输入(称为Input)

  • 我要连接到reduxForm,然后再连接到redux。

  • 传入的初始值应具有名称和值。

我有以下测试(Jest +酶)

I have the following test (Jest+Enzyme)

import React from 'react';
import { Provider } from 'react-redux';
import Enzyme, { mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import configureStore from 'redux-mock-store';

import TestForm from './TestForm';

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

describe('Redux Form Test', () => {
    let wrapper;

    let mockStoreData = {
        testForm: {
            testField: 'test value',
        },
    };

    const mockStore = configureStore();
    const store = mockStore(mockStoreData);

    beforeEach(() => {
        wrapper = mount(
            <Provider store={store}>
                    <TestForm />
            </Provider>
        );
    });

    it('Check Value', () => {
        let inputs = wrapper.find('input');
        expect(inputs.at(0).prop('name')).toBe('testField'); //OK!!!
        expect(inputs.at(0).prop('value')).toBe('test value'); //empty string!!
    });
});

Jest测试将带有 testField(及其值)的 testForm对象(及其值)传递到

The Jest test passes in a 'testForm' object with 'testField' (and its value) into the the store.

正如预期的那样,第一个输入的名称为'testField',但是'value'为空(即,空字符串)。

As expected, the name on the first input is 'testField', however the 'value' is empty (ie. an empty string).

这是不期望的,因为如果我将组件呈现在正常页面中,则会出现测试值。

This is not expected, because if I were to render the component in a normal page then 'test value' would appear.

所以这里似乎有些破损。我不确定它是否与redux形式或酶有关,但是redux形式的Field对象似乎正在拦截传递到Input对象的属性。

So something seems to be broken here. I am not sure if it has something to do with redux-form or enzyme, but the redux-form Field object seems to be intercepting the properties that are passed into the Input object.

我开始质疑是否甚至可以 可能 来测试 redux表格

I am starting to question whether it is even possible to test redux form.

推荐答案

我不确定为什么您既不需要也不需要测试Redux Form的功能,因为它已经通过了测试。创作者/维护者。但是, redux-mock-store 似乎仅用于 unit 个测试(在其中模拟中间件并调用 store.dispatch(actionType)并期望 action 执行叫做)。它不处理 reducer 的副作用,也不跟踪状态的变化。

I'm not sure why you'd want nor need to test Redux Form's functionality, as it's already been tested by the creators/maintainers. However, redux-mock-store appears to be made for unit tests only (where you'll mock middlewares and call store.dispatch(actionType) and expect the action to be called). It doesn't handle reducer side effects nor track changes in state.

在上述情况下,您只需要对自定义输入进行单元测试组件,因为这是唯一与标准Redux表单不同的组件。

In the case above, you'll only need to do a unit test on your custom Input component, because that's the only component that's different from what would be considered a standard redux form.

这表示...对于集成测试,您将需要使用真实的商店,其中包含redux-form的 reducer 和您的字段状态。

That said... for an integration test, you'll need to use a real store that contains the redux-form's reducer and your field state.

工作示例 https://codesandbox.io/s/zl4p5w26xm (我已经包含了表格集成测试和 Input 单元测试-正如您会注意到的那样, Input 单元测试满足您的大部分测试需求)

Working example: https://codesandbox.io/s/zl4p5w26xm (I've included a Form integration test and an Input unit test -- as you'll notice, the Input unit test covers most of your testing needs)

containers / Form / Form.js

import React, { Component } from "react";
import { Form, Field, reduxForm } from "redux-form";
import { connect } from "react-redux";
import Input from "../../components/Input/input";

const isRequired = value => (!value ? "Required" : undefined);

class SimpleForm extends Component {
  handleFormSubmit = formProps => {
    alert(JSON.stringify(formProps, null, 4));
  };

  render = () => (
    <div className="form-container">
      <h1 className="title">Text Field</h1>
      <hr />
      <Form onSubmit={this.props.handleSubmit(this.handleFormSubmit)}>
        <Field
          className="uk-input"
          name="testField"
          component={Input}
          type="text"
          validate={[isRequired]}
        />
        <button
          type="submit"
          className="uk-button uk-button-primary uk-button-large submit"
          disabled={this.props.submitting}
        >
          Submit
        </button>
        <button
          type="button"
          className="uk-button uk-button-default uk-button-large reset"
          disabled={this.props.pristine || this.props.submitting}
          onClick={this.props.reset}
          style={{ float: "right" }}
        >
          Clear
        </button>
      </Form>
    </div>
  );
}

export default connect(({ field }) => ({
  initialValues: { [field.name]: field.value }
}))(
  reduxForm({
    form: "SimpleForm"
  })(SimpleForm)
);

容器/表格/ __ test __ / Form.js

import React from "react";
import { Provider } from "react-redux";
import { mount } from "enzyme";
import SimpleForm from "../Form";
import store from "../../../store/store";

const wrapper = mount(
  <Provider store={store}>
    <SimpleForm />
  </Provider>
);

describe("Redux Form Test", () => {
  it("renders without errors", () => {
    expect(wrapper.find(".form-container")).toHaveLength(1);
  });

  it("fills the input with a default value", () => {
    expect(wrapper.find("input").prop("name")).toBe("testField");
    expect(wrapper.find("input").prop("value")).toBe("Test Value");
  });

  it("updates input value when changed", () => {
    const event = { target: { value: "Test" } };
    wrapper.find("input").simulate("change", event);
    expect(wrapper.find("input").prop("value")).toBe("Test");
  });

  it("resets the input value to defaults when the Clear button has been clicked", () => {
    wrapper.find("button.reset").simulate("click");
    expect(wrapper.find("input").prop("value")).toBe("Test Value");
  });
});

stores / stores.js (为简单起见,我将 reducers store 到一个文件中)

stores/stores.js (for simplicity, I lumped reducers and store into one file)

import { createStore, combineReducers } from "redux";
import { reducer as formReducer } from "redux-form";

const initialValues = {
  name: "testField",
  value: "Test Value"
};

const fieldReducer = (state = initialValues, { type, payload }) => {
  switch (type) {
    default:
      return state;
  }
};
const reducer = combineReducers({
  field: fieldReducer,
  form: formReducer
});

export default createStore(reducer);

注意:除了使用 initialValues 外,在文档中,还有其他三种更新字段值的方法:利用redux-form的 reducer.plugin 并调度操作以更新表单,或者使用 this.props.intialize({testField: Test Value}); 使用 enableReinitialize:true keepDirtyOnReinitialize:true,或使用 this.props。 change( SimpleForm,{testField:测试值}); 。重要说明,因为有时 mapStateToProps 是异步的。

Note: Aside from using initialValues, buried in the documentation, there are three other ways to update field values: Utilizing redux-form's reducer.plugin and dispatching an action to update the form, or by using this.props.intialize({ testField: "Test Value" }); with enableReinitialize: true and keepDirtyOnReinitialize: true,, or by using this.props.change("SimpleForm", { testField: "Test Value" });. Important to note because sometimes mapStateToProps is asynchronous.

这篇关于用酶测试简单的Redux-Form(值在哪里?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆