web-dev-qa-db-fra.com

Comment simuler un événement sur un test unitaire avec Jest, Enzyme pour React-Native

J'essaie de comprendre comment tester un événement "onPress" avec Jest dans une application React-Native afin que je puisse m'assurer que la bonne fonction est appelée.

J'ai parcouru la documentation et Google, mais je n'ai pas trouvé de solution dans React-Native.

C'est ce que j'ai trouvé qui est censé fonctionner pour React-Native avec enzyme:

const mockFunc = jest.fn();
const component = mount(<MyComponent onPress={mockFunc} />);
component.simulate('press');
expect(mockFunc).toHaveBeenCalled();

Mais ça ne marche pas. Il semble que mount ne fonctionne pas et j'obtiens cette sortie:

ReferenceError: le document n'est pas défini

J'ai essayé avec shallow à la place, mais le TouchableOpacity n'est pas rendu quand je regarde la sortie de la fonction ... et vous l'avez deviné, cela ne fonctionne pas non plus. Je ne sais pas quoi faire.

Quelqu'un a-t-il trouvé un moyen de tester des événements sur React-Native?

Merci

14
alexmngn

Enzyme ne prend pas en charge React-Native, car il est rendu différemment et n'utilise pas le DOM. C'est pourquoi vous obtenez l'erreur ReferenceError: document is not defined. Vous pouvez voir ce problème pour plus d'informations. L'équipe React travaille actuellement pour exposer une méthode .find() dans react-test-renderer Pour simuler des actions sur les composants. Ensuite, cela devrait fonctionner pour React/React-native sans avoir besoin d'un environnement DOM.

Il y a un hack que vous pouvez faire (et c'est ce que nous avons fait dans notre entreprise) qui rend un composant personnalisé qui étend TouchableOpacity et mappe onClick pour appeler onPress. Quelque chose comme ça:

const mockPressable = (name) => {
  const RealComponent = require.requireActual(name);

  class Component extends RealComponent {

    render() {
      return React.createElement(
        RealComponent.displayName || RealComponent.name,
        { ...this.props, onClick: this.props.onPress },
        this.props.children
      );
    }

  }

  return Component;
};


jest.mock('TouchableOpacity', () => mockPressable('TouchableOpacity'));

Et dans votre code de test, vous appelez component.simulate('click').

C'est un hack et je ne sais pas quelles sont les conséquences de cela, mais cela a fonctionné pour nos cas d'utilisation.

13
Lucas

Je peux exécuter des tests comme ce que vous avez décrit dans votre question dans React Native. Voici ma configuration:

package.json

"scripts": {
  ...
  "test": "node_modules/jest/bin/jest.js",
}

"devDependencies": {
  ...
  "enzyme": "^3.1.0",
  "enzyme-adapter-react-16": "^1.0.1",
  "enzyme-to-json": "^3.1.2",
  "jest": "^21.2.1",
  "jest-enzyme": "^4.0.0",
  "jest-expo": "~21.0.0",
}

"jest": {
  "preset": "jest-expo",
  "setupFiles": [
    "./test/jestSetup.js"
  ],
  "snapshotSerializers": [
    "./node_modules/enzyme-to-json/serializer"
  ]
}

test/jestSetup.js

import { configure, shallow, render, mount } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'

configure( { adapter: new Adapter() } )

// enzyme
global.shallow = shallow
global.render = render
global.mount = mount

Exemple de composant:

import React from 'react'
import { Button } from 'react-native'

const CancelButton = ( props ) =>
  <Button
    { ...props }
    onPress={ () => { props.navigation.goBack() } }
    title="Cancel"
  />

export { CancelButton }

Exemple de test

import React from 'react'
import { CancelButton } from '../CancelButton'

test( 'onPress', () => {
  const goBackFunc = jest.fn()

  const navigation = {
    goBack: goBackFunc,
  }

  const component = shallow(
    <CancelButton
      navigation={ navigation }
    />
  )

  component.simulate( 'press' )
  expect( goBackFunc ).toHaveBeenCalled()
} )

.babelrc

{
  "presets": ["babel-preset-expo"],
  "env": {
    "development": {
      "plugins": ["transform-react-jsx-source"]
    }
  }
}
5
Javid Jamae

Vous devez utiliser shallow à la place, puis appelé .dive()

const mockFunc = jest.fn();
const component = shallow(<MyComponent onPress={mockFunc} />);    
component.dive().simulate('press');
expect(mockFunc).toHaveBeenCalled();
5
msmaromi