Reputation: 1
I have a SignUp React component which uses redux form and my onSubmit basically dispatches an async action. I am trying to test my component using Enzyme and Jest by adding a spy to my dispatch and checking if dispatch is invoked on simulating a form submission. However, my test fails.
Here is my SignUp redux form component:
import React from 'react';
import {reduxForm, Field, focus} from 'redux-form';
import Input from './input';
import {required, nonEmpty, email, isTrimmed, length} from '../validators';
import {registerUser} from '../actions/users';
import {login} from '../actions/auth';
export class SignUpForm extends React.Component {
onSubmit(values) {
const {username, password, fname, lname} = values;
const newUser = {
username,
password,
user: {
firstName: fname,
lastName: lname
}
};
return this.props
.dispatch(registerUser(newUser))
.then(() => this.props.dispatch(login(username, password)));
}
render() {
let errorMessage;
if (this.props.error) {
errorMessage = (
<div className="message message-error">{this.props.error </div>
);
}
return (
<form className='signup-form' onSubmit={this.props.handleSubmit(values =>
this.onSubmit(values)
)}>
{errorMessage}
<Field
name="fname"
type="text"
component={Input}
label="First Name"
validate={[required, nonEmpty]}
/>
<Field
name="lname"
type="text"
component={Input}
label="Last Name"
validate={[required, nonEmpty]}
/>
<Field
name="username"
type="email"
component={Input}
label="Email"
validate={[required, nonEmpty, email, isTrimmed]}
/>
<Field
name="password"
type="password"
component={Input}
label="Password"
validate={[required, nonEmpty, length({min: 10, max: 72})]}
/>
<button
type="submit"
disabled={this.props.pristine || this.props.submitting}>
Sign Up
</button>
</form>
);
}
}
export default reduxForm({
form: 'signup',
onSubmitFail: (errors, dispatch) =>
dispatch(focus('signup', Object.keys(errors)[0]))
})(SignUpForm);
Here is my test:
import React from 'react';
import {shallow, mount} from 'enzyme';
import SignUpForm from './signup';
import {registerUser} from '../actions/users';
import { reducer as formReducer } from 'redux-form'
import { createStore, combineReducers, applyMiddleware } from 'redux'
import { Provider } from 'react-redux'
import thunk from 'redux-thunk';
import {stockReducer} from '../reducers';
describe('<SignUpForm />', () => {
let store
let wrapper
let dispatch
beforeEach(() => {
store = createStore(combineReducers({ form: formReducer, stock: stockReducer }),applyMiddleware(thunk))
dispatch = jest.fn()
wrapper = mount(
<Provider store={store}>
<SignUpForm dispatch={dispatch}/>
</Provider>
);
})
it('should fire onSubmit callback when form is submitted', (done) => {
const form = wrapper.find('form');
form.find('#fname').simulate('change', {target: {value: 'fname'}});
form.find('#lname').simulate('change', {target: {value: 'lname'}});
form.find('#username').simulate('change', {target: {value: '[email protected]'}});
form.find('#password').simulate('change', {target: {value: 'password1234'}});
form.simulate('submit');
expect(dispatch).toHaveBeenCalled();
});
});
My test fails with the following error: expect(jest.fn()).toHaveBeenCalled() Expected mock function to have been called.
Please help me understand what is going wrong.
Upvotes: 0
Views: 1609
Reputation: 816
The problem here is that you are not awaiting anywhere in your test on the promise returned by your onSubmit function so your assert is getting executed before your promise resolves.
I will suggest you to properly refactor your code to make it "testable". You can take a look at following link on how to test async calls using jest: https://facebook.github.io/jest/docs/en/asynchronous.html
I will also suggest you to use redux-thunk which will make your life easier.
Upvotes: 1