callstack / react-native-testing-library

🦉 Simple and complete React Native testing utilities that encourage good testing practices.
https://callstack.github.io/react-native-testing-library/
MIT License
3.01k stars 264 forks source link

Press event called when not passed down to event handler #1633

Closed DonBrody closed 5 days ago

DonBrody commented 1 week ago

Describe the bug

Hi. I think I'm running into an issue where an onPress event is called even when it is not passed down as a prop, but only when including a wrapper component.

For example, the component below accepts an onPress prop through its interface, but never passes that prop down to its internal Text component:

const _Text = React.forwardRef<Text, TextProps>(({ children }, ref) => (
  <Text ref={ref}>{children}</Text>
))

So we'd expect that the following would fail (and it does fail as expected):

const mockOnPress = jest.fn()

const { getByText } = render(<_Text onPress={mockOnPress}>Test Text</_Text>)

fireEvent.press(getByText('Test Text'))

expect(mockOnPress).toHaveBeenCalled()

But the above will pass if a wrapper component is provided (even a simple one like below):

 const Wrapper: React.FC<React.PropsWithChildren> = ({ children }) => children

const { getByText } = render(
  <_Text onPress={mockOnPress}>Test Text</_Text>,
  { wrapper: Wrapper },
)

Thank you in advance for any help you could provide here!

Expected behavior

The test described above should fail.

Steps to Reproduce

it('should fire onPress callback', () => {
  const mockOnPress = jest.fn()

  const Wrapper: React.FC<React.PropsWithChildren> = ({ children }) => children

  const _Text = React.forwardRef<Text, TextProps>(({ children }, ref) => (
    <Text ref={ref}>{children}</Text>
  ))

  const { getByText } = render(
    <_Text onPress={mockOnPress}>Test Text</_Text>,
    { wrapper: Wrapper },
  )

  fireEvent.press(getByText('Test Text'))

  expect(mockOnPress).toHaveBeenCalled()
  expect(mockOnPress).toHaveBeenCalledTimes(1)
})

Versions

@testing-library/react-native => 12.5.1 jest => 29.7.0 react => 18.3.1 react-native => 0.73.7

npmPackages: react: ^18.2.0 => 18.3.1 react-native: ~0.73.7 => 0.73.7

mdjastrzebski commented 5 days ago

The Fire Event API is invoking event handlers also on composite components due to compatibility reasons. If you want to have more realistic event simulation use User Event API instead.

DonBrody commented 5 days ago

Yup - the User Event API does properly handle this. We'll update our tests. Thanks for your help!