Reputation: 1979
I am trying to test a Redux action and need assistance with testing an action with side-effects.
Here is my action :
export function login(email, password) {
return dispatch => {
dispatch(setLoginSuccess(false));
loginApi(email, password, error => {
dispatch(setLoginPending(false));
if (!error) {
dispatch(setLoginSuccess(true));
} else {
dispatch(setLoginError(error));
}
});
}
}
Below is the loginApi function to authenticate user :
export function loginApi(email, password, callback) {
if (email === 'test@test.com' && password == '123') {
return callback(null);
} else {
return callback(new Error('Please provide valid email and password'));
}
};
Additionally, I am facing an issue while simulating a form submit in my component with Enzyme and Jest.
Here is the code for the same :
render() {
let {email, password, emailValid} = this.state;
let {isLoginPending, isLoginSuccess, loginError} = this.props;
return (
<div className="col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2 col-xs-10 col-xs-offset-1">
<h3 className="text-center">Login</h3>
<form className="login-form" onSubmit={this.handleSubmit.bind(this)}>
<div className={emailValid? "form-group has-success" : (emailValid == undefined)? "form-group": "form-group has-error"}>
<label>Email address</label>
<input type="email" name="email" className="form-control" ref="userEmail"
placeholder="Enter your email" onChange={this.handleChange.bind(this)}/>
</div>
{/* Checking if email valid or not */}
{this.props.emailValid? "" : (this.props.emailValid == undefined)? "" : <p className="text-danger">Please provide a valid email!</p>}
<div className="form-group">
<label>Password</label>
<input type="password" name="password" className="form-control" ref="userPassword"
placeholder="Enter your password" onChange={this.handleChange.bind(this)}/>
</div>
<button type ="submit" className="btn btn-primary btn-block" disabled={!this.props.emailValid}>Get Started</button>
{/* Displaying error messages */}
{ loginError && <div className="auth-error-msg"><p className="text-danger">{loginError.message}</p></div> }
</form>
</div>
);
};
Here is the code for the handleSubmit event:
handleSubmit(e){
e.preventDefault();
this.props.login(this.refs.userEmail.value, this.refs.userPassword.value);
this.setState({
email: '',
password: ''
});
}
I am trying to simulate the Submit event in this way :
it('should render 1 error block on submitting invalid form', () => {
// Render a checkbox with label in the document
const spy = jest.fn();
const component = shallow(<Login login={spy}/>);
const form = component.find('form').simulate('submit');
});
But it currently throws an error as it cannot find preventDefault. How do I test this event?
Upvotes: 0
Views: 1043
Reputation: 47287
I would recommend you to split the testing. Submitting the form and testing the actions are two separate things. For testing the action with jest, you need to dispatch the action to a mock store, and see which is the final state of the store. Something like this:
describe('actions', () => {
let store
beforeEach(() => {
store = mockStore({})
})
it('should dispatch the correct actions', () => {
const expectedActions = [
{ type: 'action1', ...arguments },
{ type: 'action2', ...arguments }
]
store.dispatch(login('user', 'password'))
expect(store.getActions()).toEqual(expectedActions)
})
})
you can do multiple test cases, adapting the expected actions to what you passed as parameters.
For creating a mock store, there are multiple packages that can do the job. Here is one example with support for thunks:
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
const middlewares = [ thunk ]
const mockStore = configureMockStore(middlewares)
export default mockStore
I personally would not spend too much effort testing that the form submits. At the end, that is a standard html thing, so I would instead focus on the components that you have built yourself.
And another tip: If you have gone through all the trouble of using redux
, don't fall back to normal state. That setState
that you have would be much more easily implemented, and tested, by using a normal reducer and getting that into your state as well.
Upvotes: 1