web-dev-qa-db-fra.com

Jest + Enzyme: testez la forme Redux

Ma demande a beaucoup de forme redux. J'utilise Jest et Enzyme pour les tests unitaires. Cependant, je n'arrive pas à tester le formulaire redux. Mon composant est un formulaire de connexion comme:

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

Se moquer du magasin, importer un composant connecté

redux-form Utilise le magasin pour gérer les entrées du formulaire. J'utilise ensuite 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();

Mais de cette façon, le submit n'est pas simulé, mon cas de test a échoué:

Fonction de simulation supposée avoir été appelée avec: [] Mais elle n'a pas été appelée.

Mock the store, Import React component only.

J'ai essayé de créer un formulaire redux à partir du code de test:

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

Dans ce cas, j'ai toujours une erreur de function not called. Si j'ajoute console.log(wrapper.html()), j'ai une erreur:

Violation invariante: impossible de trouver "store" dans le contexte ou les accessoires de "Connect (ConnectedField)". Soit envelopper le composant racine dans un, soit passer explicitement "store" comme accessoire à "Connect (ConnectedField)".

Je ne trouve pas de documentations sur les sites officiels de redux-form ou redux ou jest/enzyme, ou même Google .. Aidez-moi, merci.

6
Joy

J'ai utilisé le vrai magasin (comme redux-mock-store ne prend pas en charge les réducteurs) et le réducteur de redux-form, cela a fonctionné pour moi. Exemple de code:


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

});

2
Eric Xin Zhang

J'ai fait un outil qui aide avec des problèmes comme ça. Il crée des cas de test avec des données réelles (l'extension Chrome les collecte et les enregistre dans un fichier) que vous pouvez exécuter avec l'outil CLI. Je vous recommande de l'essayer: https://github.com/wasteCleaner/check-state-management

0
Aleksandr Gorin

Vous pouvez trouver la réponse ici: https://github.com/tylercollier/redux-form-test

En bref, vous pouvez utiliser la fonction dive () peu profonde pour tester un composant d'ordre supérieur, mais dans votre cas, vous avez un composant d'ordre supérieur à l'intérieur d'un composant d'ordre supérieur.

Vous devez diviser votre composant en deux composants, le premier est un composant de présentation, sans

const form = reduxForm({ form: 'login' })(LoginForm);
export default connect(mapStateToProps, mapDispatchToProps)(form); 

Vous encapsulez ensuite le premier composant dans le deuxième composant (composant conteneur).

Vous pouvez facilement tester le premier composant (composant de présentation)

0
Bill Huang

J'ai eu le même problème. La réponse peut être trouvée ici https://github.com/airbnb/enzyme/issues/1002 . Pour faire court, vous devez passer store comme accessoire dans votre formulaire et utiliser la fonction .dive () sur le wrapper.

Cordialement

Pavel

0
bikerp