私のアプリケーションには多くのredux形式があります。ユニットテストにJestとEnzymeを使用しています。しかし、私はredux-formのテストに失敗しました。私のコンポーネントは次のようなログインフォームです。
_import { login } from './actions';
export class LoginForm extends React.Component<any, any> {
onSubmit(values) {
this.props.login(values, this.props.redirectUrl);
}
render() {
const { handleSubmit, status, invalid } = this.props;
return (
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
<TextField label="Email" name="email">
<TextField type="password" label="Password" name="password" autoComplete/>
<Button submit disabled={invalid} loading={status.loading}>
OK
</Button>
</form>
);
}
}
const mapStateToProps = (state) => ({
status: state.login.status,
});
const mapDispatchToProps = { login };
const form = reduxForm({ form: 'login' })(LoginForm);
export default connect(mapStateToProps, mapDispatchToProps)(form);
_
_redux-form
_は、ストアを使用してフォーム入力を維持します。次に_redux-mock-store
_を使用します:
_import ConnectedLoginForm from './LoginForm';
const configureStore = require('redux-mock-store');
const store = mockStore({});
const spy = jest.fn();
const wrapper = shallow(
<Provider store={store}>
<ConnectedLoginForm login={spy}/>
</Provider>);
wrapper.simulate('submit');
expect(spy).toBeCalledWith();
_
しかし、この方法ではsubmit
はシミュレートされず、テストケースが失敗しました。
疑似関数が呼び出されていると予想されました:[]しかし、呼び出されませんでした。
テストコードからreduxフォームを作成しようとしました。
_import { Provider } from 'react-redux';
import ConnectedLoginForm, { LoginForm } from './LoginForm';
const props = {
status: new Status(),
login: spy,
};
const ConnectedForm = reduxForm({
form: 'login',
initialValues: {
email: '[email protected]',
password: '000000',
},
})(LoginForm);
const wrapper = shallow(
<Provider store={store}>
<ConnectedForm {...props}/>
</Provider>);
console.log(wrapper.html());
wrapper.simulate('submit');
expect(spy).toBeCalledWith({
email: '[email protected]',
password: '000000',
});
_
この場合でも、_function not called
_のエラーが発生します。 console.log(wrapper.html())
を追加すると、エラーが発生します。
不変の違反:「Connect(ConnectedField)」のコンテキストまたはプロップのいずれにも「store」が見つかりませんでした。ルートコンポーネントをでラップするか、「store」をプロップとして「Connect(ConnectedField)」に明示的に渡します。
Redux-form、redux、jest/enzyme、またはGoogleの公式サイトでドキュメントを見つけることができません。助けてください、ありがとう。
私は実際のストア(redux-mock-store
はリデューサーをサポートしていない)とredux-formのリデューサーを使用したので、うまくいきました。コード例:
import { createStore, Store, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import { reducer as formReducer } from 'redux-form';
const rootReducer = combineReducers({
form: formReducer,
});
let store;
describe('Redux Form', () => {
beforeEach(() => {
store = createStore(rootReducer);
});
it('should submit form with form data', () => {
const initialValues = {...};
const onSubmit = jest.fn();
const wrapper = mount(
<Provider store={store}>
<SomeForm
onSubmit={onSubmit}
initialValues={initialValues}
/>
</Provider>
);
const form = wrapper.find(`form`);
form.simulate('submit');
const expectedFormValue = {...};
expect(onSubmit).toHaveBeenCalledTimes(1);
expect(onSubmit.mock.calls[0][0]).toEqual(expectedFormValue);
});
});
そのような問題に役立つツールを作りました。それはあなたがCLIツールで実行できる実際のデータ(クロム拡張がそれを収集してファイルに保存する)でテストケースを作ります。私はそれを試すことをお勧めします: https://github.com/wasteCleaner/check-state-management
あなたはここで答えを見つけることができます: https://github.com/tylercollier/redux-form-test
つまり、浅いdive()関数を使用して高次コンポーネントをテストできますが、この場合、高次コンポーネント内に高次コンポーネントがあります。
コンポーネントを2つのコンポーネントに分割する必要があります。最初のコンポーネントはプレゼンテーションコンポーネントです。
const form = reduxForm({ form: 'login' })(LoginForm);
export default connect(mapStateToProps, mapDispatchToProps)(form);
次に、最初のコンポーネントを2番目のコンポーネント(コンテナーコンポーネント)にラップします。
最初のコンポーネント(プレゼンテーションコンポーネント)を簡単にテストできます
同様の問題がありました。答えはここ https://github.com/airbnb/enzyme/issues/1002 で見つかります。要するに、storeをプロップとしてフォームに渡し、ラッパーで.dive()関数を使用する必要があります。
よろしく
パベル