2017-09-03 1 views
0

J'essaie de tester une action Redux et j'ai besoin d'aide pour tester une action avec des effets secondaires.Comment tester une action asynchrone simple Réagir avec Jest?

Voici mon 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)); 
     } 
    }); 
    } 
} 

est inférieure à la fonction loginApi pour authentifier l'utilisateur:

export function loginApi(email, password, callback) { 
    if (email === '[email protected]' && password == '123') { 
     return callback(null); 
    } else { 
     return callback(new Error('Please provide valid email and password')); 
    } 
}; 

De plus, je suis confronté à un problème tout en simulant une forme soumettre dans mon élément avec l'enzyme et Plaisanter.

Voici le code pour le même:

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> 
     ); 
    }; 

Voici le code pour l'événement handleSubmit:

handleSubmit(e){ 
    e.preventDefault(); 
    this.props.login(this.refs.userEmail.value, this.refs.userPassword.value); 
    this.setState({ 
     email: '', 
     password: '' 
    }); 

} 

Je suis en train de simuler le soumettre un événement de cette manière:

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'); 

}); 

Mais il génère actuellement une erreur car il ne trouve pas preventDefault. Comment puis-je tester cet événement?

Répondre

1

Je vous recommande de partager le test. Soumettre le formulaire et tester les actions sont deux choses distinctes. Pour tester l'action avec jest, vous devez envoyer l'action à un magasin de simulation, et voir quel est l'état final du magasin. Quelque chose comme ceci:

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) 
    }) 
}) 

Vous pouvez faire plusieurs cas de test, en adaptant les actions attendues à ce que vous avez passé en tant que paramètres.

Pour créer un magasin virtuel, plusieurs packages peuvent faire l'affaire. Voici un exemple avec le support des thunks:

import configureMockStore from 'redux-mock-store' 
import thunk from 'redux-thunk' 

const middlewares = [ thunk ] 
const mockStore = configureMockStore(middlewares) 
export default mockStore 

Personnellement, je ne dépenserais pas trop d'efforts pour tester le formulaire. À la fin, c'est une chose html standard, donc je me concentrerais plutôt sur les composants que vous avez construits vous-même.

Et un autre conseil: Si vous avez eu tous les problèmes d'utiliser redux, ne pas revenir à l'état normal. Ce que vous avez serait beaucoup plus facilement mis en œuvre, et testé, en utilisant un réducteur normal et de mettre cela dans votre état.

+0

Merci, @Mario pour votre explication. J'ai un petit doute. Je n'ai pas utilisé de promesses dans mon action, donc une erreur sera lancée si j'utilise 'alors' dans mon test. J'ai parcouru les docs de redux et eux aussi ont un exemple similaire en utilisant des promesses mais dans mon cas je suis simplement en train d'attendre le callback de la fonction loginApi alors comment refactoriser le test? S'il vous plaît aider! –

+1

J'ai édité l'exemple pour le cas synchrone. Vous avez juste besoin d'enlever le 'then' et de faire vos assertions juste après l'envoi de l'action. –

+0

Pouvez-vous m'aider à tester l'événement" handleSubmit "en cliquant sur le formulaire? C'est très basique mais c'est important pour moi de bien comprendre. Merci d'avance! –