用酶测试简单的Redux-Form(值在哪里?) [英] Testing simple Redux-Form with Enzyme (where is value??)
问题描述
我有连接到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屋!