How can I spy on TouchableNativeFeedback onPress in React Native with @testing-library/react-native?

Viewed 790

Help me please...

I have a React Native custom Button component that receives an onPress prop and passes that onPress to a TouchableNativeFeedback. I make a unit testing with @testing-library/react-native. I try to spy on onPress, to check if it is triggered when the TouchableNativeFeedback is touched. Somehow the spy function is not called when I simulate press event on the Button. Is there any mistake in my implementation?

FI: This behavior only occurs in TouchableNativeFeedback, but working perfectly with Button

Here is my implementation:

Button.js

const Button = ({onPress, label}) => (
  <TouchableNativeFeedback onPress={onPress} testID="button">
    <View style={someStyling}>
      <Text>{label}</Text>
    </View>
  </TouchableNativeFeedback>
)

export default Button

Button.test.js

  it("Fire onPress props when button pressed", () => {
    const mockFn = jest.fn();

    const { getByTestId } = render(<Button onPress={mockFn} />);
    const button = getByTestId("button");
    
    fireEvent.press(button);
    
    expect(mockFn).toHaveBeenCalled();
  });

2 Answers

I had the same issue in a component using <TouchableNativeFeedback/>. My test case failed with a message saying No instances found on the getByText call.

After few attempts, I used following snippet for debugging:

const { debug } = render(<Tag onPress={handler}>Press me</Tag>);
debug();

Along with some other details, following message popped up in console:

TouchableNativeFeedback is not supported on this platform!

At this moment, there is a related thread regarding Touchable* components on react-native-testing-library GH issues where they explain details and provide some workarounds.

I ended up using platform detection in my component, as that's what I wanted to do anyway:

const TouchComponent =
  Platform.OS === 'android' ? TouchableNativeFeedback : TouchableOpacity;

return (
  <TouchComponent onPress={onPress}>
    ...
  </TouchComponent>
);

I had the same issue.

What solved it for me was that fact that my TouchableXXX component was imported from
react-native-gesture-handler. This library probably was imported as dependency by one of my dependecies. I guess when I wrote TouchableXXX it was imported automatically from there by my IDE.
After changing the import statement to import from react-native - everything worked for me in tests.
So eventually my change was from this:

import { TouchableHighlight } from 'react-native-gesture-handler'

to this

import { TouchableOpacity } from 'react-native'
Related