Jest: Jest for react-native does not recognize all props for <TouchableHighlight />

Created on 16 Sep 2016  ·  3Comments  ·  Source: facebook/jest

I have a class for my custom button:

import React, { Component } from 'react';
import { StyleSheet, View, TouchableHighlight, Text, Image } from 'react-native';

class NavBarBackButton extends Component {

  static propTypes = {
    onClick: React.PropTypes.func.isRequired,
    buttonText: React.PropTypes.string,
    customStyle: React.PropTypes.object
  };

  render() {

    return (
      <TouchableHighlight
        style={[styles.backButton, this.props.customStyle]}
        onPress={() => {this.props.onClick()}} >
        <View style={{flexDirection: 'row'}}>
          <Image
            style={styles.backImage}
            source={require('../img/back-128.png')}
          />
          <Text style={styles.backButtonText}>
            {this.props.buttonText}
          </Text>
        </View>
      </TouchableHighlight>
    );
  }
}

const styles = StyleSheet.create({
  backButton: {
    justifyContent: 'center'
  },
  backButtonText: {
    fontSize: 17,
    textAlignVertical: 'center',
    color: 'black',
  },
  backImage: {
    width: 40,
    height: 40
  },
});

export default NavBarBackButton;

and the snapshot is generated with this test:

import 'react-native';
import React from 'react';
import NavBarBackButton from '../navBarBackButton';

import renderer from 'react-test-renderer';

function doWork() {
  console.log('Back button was clicked!');
}

it('renders all UI elements', () => {

  const tree = renderer.create(
    <NavBarBackButton onClick = {doWork}/>
  ).toJSON();

  expect(tree).toMatchSnapshot();
});

but when I add another prop to the <TouchableHighlight/> element, like:

underlayColor={'blue'}

and re-run the test - I don't get a diff showing that the snapshot did not expect this extra prop. In fact, the only prop evaluated seams to be "style".
Is this work in progress?
Also, on a related note - why is TouchableHighlight's type showing in snapshot (and debugger) as 'View' and not 'TouchableHightlight'?

In my package.jason I have:

{
  "name": <my_project_name>,
  "version": "0.0.1",
  "private": true,
  "scripts": {
   "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest"
  },
  "jest": {
    "preset": "jest-react-native",
    "collectCoverage": true,
    "verbose": true,
    "preprocessorIgnorePatterns": [
      "node_modules/(?!react-native|<my_project_name>|react-native-button)"
    ]
  },
  "dependencies": {
    "lodash": "^4.15.0",
    "react": "^15.3.1",
    "react-native": "^0.33.0",
  },
  "devDependencies": {
    "babel-jest": "^15.0.0",
    "babel-polyfill": "^6.13.0",
    "babel-preset-react-native": "^1.9.0",
    "jest": "^15.1.1",
    "jest-cli": "^15.1.1",
    "jest-react-native": "^15.0.0",
    "react-addons-test-utils": "^15.2.1",
    "react-shallow-testutils": "^2.0.0",
    "react-test-renderer": "^15.3.1"
  }
}

and my .babelrc in root dir is:

{
  "presets": ["react-native"]
}

Most helpful comment

@cpojer Thank you for quick response! My snapshot looks much cleaner now.
Additional question - currently my output complains that I'm not covering a line which specifies onPress prop as a function passed in

static propTypes = {
    onClick: React.PropTypes.func.isRequired,
    ...
};

<TouchableHighlight
    onPress={() => {this.props.onClick()}} > //no coverage for this line of code in test
    ...
</TouchableHighlight>

Any idea how I can simulate button click? Or do anything to have my test cover onPress={() => {this.props.onClick()}} > ? I couldn't find anything in your tutorials on the subject.

Thanks in advance!

All 3 comments

We don't specifically mock TouchableHighlight. It is rendered as View because that is what react-native renders it to.

It seems like TouchableHighlight sets props directly on its native backing element: https://github.com/facebook/react-native/blob/master/Libraries/Components/Touchable/TouchableHighlight.js#L200 and you'd need a special mock for it to make it so your prop shows up in the rendered output.

One thing that might work could be to create your own mock like suggested in the second example on the website: http://facebook.github.io/jest/docs/tutorial-react-native.html#mock-native-modules-using-jest-mock

jest.mock('TouchableHighlight', () => {
  const jestReactNative = require('jest-react-native');
  return jestReactNative.mockComponent('TouchableHighlight');
});

@cpojer Thank you for quick response! My snapshot looks much cleaner now.
Additional question - currently my output complains that I'm not covering a line which specifies onPress prop as a function passed in

static propTypes = {
    onClick: React.PropTypes.func.isRequired,
    ...
};

<TouchableHighlight
    onPress={() => {this.props.onClick()}} > //no coverage for this line of code in test
    ...
</TouchableHighlight>

Any idea how I can simulate button click? Or do anything to have my test cover onPress={() => {this.props.onClick()}} > ? I couldn't find anything in your tutorials on the subject.

Thanks in advance!

@rosiakr Yes, you can test the button click event.
Here is some code what I wrote to test the button click.

class YourComponent extends Component {
  handleButtonClick = () => {};

  render() {
    return <Button transparent onPress={() => this.handleButtonClick()}></Button>
  }
}

//jest
it("Test Component", () => {
  const component = renderer.create(
    <YourComponent/>
  );

  // manually trigger the  button click.
  component.getInstance().handleButtonClick();
};
Was this page helpful?
0 / 5 - 0 ratings

Related issues

benmonro picture benmonro  ·  119Comments

paularmstrong picture paularmstrong  ·  66Comments

calebmer picture calebmer  ·  72Comments

iffy picture iffy  ·  137Comments

eldh picture eldh  ·  84Comments