How to simulate an event on a unit test with Jest, Enzyme for React-Native

alexmngn picture alexmngn · Feb 16, 2017 · Viewed 14.5k times · Source

I'm trying to figure out how to test an "onPress" event with Jest in a React-Native app so I can make sure the right function is called.

I went through the documentation and Google but couldn't find a solution for it in React-Native.

This is what I found that is supposed to work for React-Native with enzyme:

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

But this doesn't work. Seems like mount doesn't work and I get this output:

ReferenceError: document is not defined

I tried with shallow instead but the TouchableOpacity is not getting rendered when I look at the output of the function... and you've guessed it, it doesn't work either. Not sure what to do.

Does anyone found a way to test events on React-Native?

Thanks

Answer

Lucas picture Lucas · Feb 23, 2017

Enzyme does not support React-Native, because it's rendered differently and doesn't use the DOM. That's why you're getting the error ReferenceError: document is not defined. You can see this issue for more information. The React team is currently working to expose a .find() method in react-test-renderer to simulate actions on components. Then it should work for both React/React-native without needing a DOM environment.

There's a hack you can do (and that's what we did in our company) that is rendering a custom component that extends TouchableOpacity and map onClick to call onPress. Something like this:

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

And in your test code, you call component.simulate('click').

It's a hack and I'm not sure what are the consequences of doing this but it has worked for our use cases.