React-native: RN v0.62.0-rc.0 - Touchable[Highlight|WithoutFeedback] are rendering into a component without name under jest

Created on 9 Jan 2020  Â·  21Comments  Â·  Source: facebook/react-native

I am trying to migrate from 0.59.3 to 0.62 rc0

However, I got a strange state of the app. Touchable[Highlight|WithoutFeedback] became to render without display name under jest (see snippets below).

I have the following control:

function backspaceIcon(backspacer: Backspacer, iconProps: IconProps) {
  return (
    <TouchableHighlight
      activeOpacity={1}
      underlayColor="#FFF"
      onShowUnderlay={() => (backspacer.backspaceUnderlay = true)}
      onHideUnderlay={() => (backspacer.backspaceUnderlay = false)}
      onPressIn={() => backspacer.backspace()}
      delayLongPress={500}
      onLongPress={() => backspacer.startBackspace()}
      onPressOut={() => backspacer.endBackspace()}
      style={styles.backspace}
      accessibilityRole="button"
      accessibilityLabel="delete"
    >
      <Icon
        {...iconProps}
        color={backspacer.backspaceUnderlay ? '#999' : '#333'}
      />
    </TouchableHighlight>
  )
}

Snapshot before migration:

<TouchableHighlight
  accessibilityLabel="delete"
  accessibilityRole="button"
  activeOpacity={1}
  delayLongPress={500}
  onHideUnderlay={[Function]}
  onLongPress={[Function]}
  onPressIn={[Function]}
  onPressOut={[Function]}
  onShowUnderlay={[Function]}
  style={
    Object {
      "alignItems": "center",
      "borderRadius": 15,
      "display": "flex",
      "height": 60,
      "justifyContent": "center",
      "width": 60,
    }
  }
  underlayColor="#FFF"
>
  <View
    color="#333"
    name="ios-backspace"
    size={30}
  />
</TouchableHighlight>

Snapshot after migration (no TouchableHighlight name):

<
  accessibilityLabel="delete"
  accessibilityRole="button"
  activeOpacity={1}
  delayLongPress={500}
  onHideUnderlay={[Function]}
  onLongPress={[Function]}
  onPressIn={[Function]}
  onPressOut={[Function]}
  onShowUnderlay={[Function]}
  style={
    Object {
      "alignItems": "center",
      "borderRadius": 15,
      "display": "flex",
      "height": 60,
      "justifyContent": "center",
      "width": 60,
    }
  }
  underlayColor="#FFF"
>
  <View
    color="#333"
    name="ios-backspace"
    size={30}
  />
</>

The same thing happens to TouchableWithoutFeedback. However, other controls look fine.

React Native version:
0.62 rc0

Steps To Reproduce

Not sure.

Describe what you expected to happen:
TouchableHighlight rendered to TouchableHighlight
TouchableWithoutFeedback rendered to TouchableWithoutFeedback

Bug

Most helpful comment

Isn't a simpler version enough:

jest.mock('react-native/Libraries/Components/Touchable/TouchableOpacity', () => 'TouchableOpacity');

Currently for my snapshot tests this line seems to be enough. Do you see any problem with that?

All 21 comments

Interesting... I have replaced the following line
https://github.com/facebook/react-native/blob/5b4816741bc9ca55d166a0c6c625bbeeed2ca81b/Libraries/Components/Touchable/TouchableHighlight.js#L380
with

module.exports = TouchableHighlight

and now it works fine.

Those lines are introduced there: https://github.com/facebook/react-native/commit/7c01172befd07f1d082b18993b87fc880e4b718f

@yungsters

@scotthovestadt is working on a fix to how Jest renders React.forwardRef in snapshots.

@scotthovestadt Am I right that PR https://github.com/facebook/jest/pull/9422 is what I am looking for?

Ah.. no.. it is not. Sorry

I have the same problems here, since 0.62.0 all of my tests with TouchableHighlight or TouchableOpacity-Components now fail.

@yungsters @scotthovestadt Is there any link that we can use to track it? or even help with the fix.

This problem has broken our native-testing-librarytests after upgrading to react-native 0.62: https://github.com/testing-library/native-testing-library/issues/113

I applied a temp fix by mocking TouchableOpacity:

jest.mock(
  'react-native/Libraries/Components/Touchable/TouchableOpacity.js',
  () => {
    const { TouchableHighlight } = require('react-native')
    const MockTouchable = props => {
      return <TouchableHighlight {...props} />
    }
    MockTouchable.displayName = 'TouchableOpacity'

    return MockTouchable
  }
)

@halilb Thanks for your snippet, but I had to modify slightly because I have the same issue with TouchableHighlight. All tests now passing though:

jest.mock('react-native/Libraries/Components/Touchable/TouchableOpacity.js', () => {
    const {View} = require('react-native');
    const MockTouchable = (props) => {
        return <View {...props} />;
    };

    MockTouchable.displayName = 'TouchableOpacity';

    return MockTouchable;
});

jest.mock('react-native/Libraries/Components/Touchable/TouchableHighlight.js', () => {
    const {View} = require('react-native');
    const MockTouchable = (props) => {
        return <View {...props} />;
    };

    MockTouchable.displayName = 'TouchableHighlight';

    return MockTouchable;
});

@halilb Thanks for your snippet, but I had to modify slightly because I have the same issue with TouchableHighlight. All tests now passing though:

Oh I've forgotten adding MockTouchable.displayName = 'TouchableOpacity' line there. Thanks for the feedback. Mocking that with View also worked for me.

Isn't a simpler version enough:

jest.mock('react-native/Libraries/Components/Touchable/TouchableOpacity', () => 'TouchableOpacity');

Currently for my snapshot tests this line seems to be enough. Do you see any problem with that?

I discovered that if you export them from react-native-gesture-handler it still works with RN0.62 however by using the react native one it breaks testing libraries, for example .toBeDisabled()

// works
import { TouchableOpacity } from 'react-native-gesture-handler'
// doesn't work
import { TouchableOpacity } from 'react-native'

More info here https://github.com/testing-library/jest-native/issues/23#issuecomment-610982229 but tl;dr I suspect the issue might be related to bundling/transpiling? Seems like the displayName or name is lost.

Actually I think the reason behind this is the fact that I heard they want to move towards a single Touchable element (which seems like they have already built behind the scenes perhaps) so they used that forwardRef to provide backwards compatibility but seems like it didn't work as expected as the displayName is lost.

Looking at https://github.com/facebook/react-native/issues/21937#issuecomment-460084554 seems like a quick fix could be

TouchableOpacity = (React.forwardRef((props, hostRef) => (...
TouchableOpacity.displayName = 'TouchableOpacity';
module.exports = TouchableOpacity

I still have issues with firing events. My fireEvent.press(...) does not cause handler calls.

Sounds like it is related to this ticket also https://github.com/testing-library/native-testing-library/issues/106

Oddly I have the same issue with TextInput being rendered as Component after upgrading to 0.62.2. I mocked it in the same fashion and my tests passed.

Could you please tell me the exact Facebook page you’re working on? Is it
Kikiama?

On Mon, Mar 30, 2020 at 5:21 AM devproivansurzhenko <
[email protected]> wrote:

@yungsters @scotthovestadt Is there any link that we can use to track it?
or even help with the fix.

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.

jest.mock('react-native/Libraries/Components/Touchable/TouchableOpacity', () => 'TouchableOpacity');

@sebk Working for me! Thanks :)

Came up with this, snapshots will be changed a little, but events tests will pass:

jest.mock('react-native/Libraries/Components/Touchable/TouchableOpacity', () => {
    const TouchableOpacity = jest.requireActual('react-native/Libraries/Components/Touchable/TouchableOpacity');

    TouchableOpacity.displayName = 'TouchableOpacity';

    return TouchableOpacity
});

jest.mock('react-native/Libraries/Components/Touchable/TouchableHighlight', () => {
    const TouchableHighlight = jest.requireActual('react-native/Libraries/Components/Touchable/TouchableHighlight');

    TouchableHighlight.displayName = 'TouchableHighlight';

    return TouchableHighlight
});

@halilb Thanks for your snippet, but I had to modify slightly because I have the same issue with TouchableHighlight. All tests now passing though:

jest.mock('react-native/Libraries/Components/Touchable/TouchableOpacity.js', () => {
    const {View} = require('react-native');
    const MockTouchable = (props) => {
        return <View {...props} />;
    };

    MockTouchable.displayName = 'TouchableOpacity';

    return MockTouchable;
});

jest.mock('react-native/Libraries/Components/Touchable/TouchableHighlight.js', () => {
    const {View} = require('react-native');
    const MockTouchable = (props) => {
        return <View {...props} />;
    };

    MockTouchable.displayName = 'TouchableHighlight';

    return MockTouchable;
});

same issue here, this solution worked for me.

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions.

I am on 0.62.1. Issue is still appearing. We just skipped those specs for now. I am planning to migrate my project to 0.63 during the current week.

@devproivansurzhenko I just migrated to 0.63.2, are you not still seeing this problem?

i am facing this issue on 0.63.4

Was this page helpful?
0 / 5 - 0 ratings