Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing React Native components with images #253

Closed
rlau1115 opened this issue Mar 15, 2016 · 10 comments
Closed

Testing React Native components with images #253

rlau1115 opened this issue Mar 15, 2016 · 10 comments

Comments

@rlau1115
Copy link

I'm getting an error when trying to test a component that has an image. Any insight on how to get this test to pass? Or is it a limitation of enzyme?

/* Welcome.js */

'use strict';

var React = require('react-native');
var {View, Image, Text, StyleSheet, TouchableHighlight} = React;
var Button = require('react-native-button');
var Actions = require('react-native-router-flux').Actions;

var globalStyle = require('../../styles/global');
var WelcomeStyle = require('../../styles/WelcomeStyle');

class Welcome extends React.Component {
  render() {
    return (
      <View style={[WelcomeStyle.container]}>
        <View style={[WelcomeStyle.brandContainer]}>
          <Image source={require('../../assets/img/brand-vert.png')} style={[WelcomeStyle.logo]} />
          <Text style={[globalStyle.fontBold, WelcomeStyle.summaryText]}>Example</Text>
        </View>
        <View style={[WelcomeStyle.buttonContainer]}>
          <Button onPress={Actions.signup} style={[WelcomeStyle.signupButton, globalStyle.fontBold]} containerStyle={[WelcomeStyle.signupButtonContainer]}>Create an Account</Button>
          <Text style={[globalStyle.fontBold, WelcomeStyle.loginPromptText]}>Have an account?</Text>
          <Button onPress={()=>Actions.login({data:"Custom data", title:'Custom title' })}>Login</Button>
        </View>
      </View>
    );
  }
}

module.exports = Welcome;
/* Welcome_spec.js */

import React from 'react';
import { mount, shallow } from 'enzyme';
import { Image, View, Text, StyleSheet } from 'react-native';

import Welcome from '../../../react/components/ecosystems/Welcome';

describe("<Welcome/>", () => {
  it('should render', () => {
    const wrapper = mount(<Welcome />);
    expect(wrapper).to.be.ok;
  });
});
Error message:

1) <Welcome/> should render:
   .../TestApp/react/assets/img/brand-vert.png: Unexpected character '�' (1:0)
  SyntaxError: react/assets/img/brand-vert.png: Unexpected character '�' (1:0)
  > 1 ø �PNG

      at Parser.pp.raise (node_modules/babel-core/node_modules/babylon/index.js:1378:13)
      at Parser.getTokenFromCode (node_modules/babel-core/node_modules/babylon/index.js:5250:10)
      at Parser.readToken (node_modules/babel-core/node_modules/babylon/index.js:4887:19)
      at Parser.<anonymous> (node_modules/babel-core/node_modules/babylon/index.js:4338:20)
      at Parser.readToken (node_modules/babel-core/node_modules/babylon/index.js:3632:22)
      at Parser.nextToken (node_modules/babel-core/node_modules/babylon/index.js:4877:19)
      at Parser.parse (node_modules/babel-core/node_modules/babylon/index.js:1348:10)
      at Object.parse (node_modules/babel-core/node_modules/babylon/index.js:45:50)
      at File.parse (node_modules/babel-core/lib/transformation/file/index.js:479:24)
      at File.parseCode (node_modules/babel-core/lib/transformation/file/index.js:568:20)
      at node_modules/babel-core/lib/transformation/pipeline.js:48:12
      at File.wrap (node_modules/babel-core/lib/transformation/file/index.js:528:16)
      at Pipeline.transform (node_modules/babel-core/lib/transformation/pipeline.js:46:17)
      at Object.transformFileSync (node_modules/babel-core/lib/api/node.js:124:10)
      at compile (node_modules/babel-core/node_modules/babel-register/lib/node.js:98:20)
      at loader (node_modules/babel-core/node_modules/babel-register/lib/node.js:126:14)
      at Object.require.extensions.(anonymous function) Æas .jsÅ (node_modules/babel-core/node_modules/babel-register/lib/node.js:136:7)
      at require (internal/module.js:16:19)
      at Welcome.render (Welcome.js:16:26)
      at Æobject ObjectÅ.ReactCompositeComponentMixin._renderValidatedComponentWithoutOwnerOrContext (node_modules/react/lib/ReactCompositeComponent.js:587:34)
      at Æobject ObjectÅ.ReactCompositeComponentMixin._renderValidatedComponent (node_modules/react/lib/ReactCompositeComponent.js:607:32)
      at Æobject ObjectÅ.wrapper Æas _renderValidatedComponentÅ (node_modules/react/lib/ReactPerf.js:66:21)
      at Æobject ObjectÅ.ReactCompositeComponentMixin.mountComponent (node_modules/react/lib/ReactCompositeComponent.js:220:30)
      at Æobject ObjectÅ.wrapper Æas mountComponentÅ (node_modules/react/lib/ReactPerf.js:66:21)
      at Object.ReactReconciler.mountComponent (node_modules/react/lib/ReactReconciler.js:37:35)
      at Æobject ObjectÅ.ReactCompositeComponentMixin.mountComponent (node_modules/react/lib/ReactCompositeComponent.js:225:34)
      at Æobject ObjectÅ.wrapper Æas mountComponentÅ (node_modules/react/lib/ReactPerf.js:66:21)
      at Object.ReactReconciler.mountComponent (node_modules/react/lib/ReactReconciler.js:37:35)
      at Æobject ObjectÅ.ReactCompositeComponentMixin.mountComponent (node_modules/react/lib/ReactCompositeComponent.js:225:34)
      at Æobject ObjectÅ.wrapper Æas mountComponentÅ (node_modules/react/lib/ReactPerf.js:66:21)
      at Object.ReactReconciler.mountComponent (node_modules/react/lib/ReactReconciler.js:37:35)
      at mountComponentIntoNode (node_modules/react/lib/ReactMount.js:266:32)
      at ReactReconcileTransaction.Mixin.perform (node_modules/react/lib/Transaction.js:136:20)
      at batchedMountComponentIntoNode (node_modules/react/lib/ReactMount.js:282:15)
      at ReactDefaultBatchingStrategyTransaction.Mixin.perform (node_modules/react/lib/Transaction.js:136:20)
      at Object.ReactDefaultBatchingStrategy.batchedUpdates (node_modules/react/lib/ReactDefaultBatchingStrategy.js:62:19)
      at Object.batchedUpdates (node_modules/react/lib/ReactUpdates.js:94:20)
      at Object.ReactMount._renderNewRootComponent (node_modules/react/lib/ReactMount.js:476:18)
      at Object.wrapper Æas _renderNewRootComponentÅ (node_modules/react/lib/ReactPerf.js:66:21)
      at Object.ReactMount._renderSubtreeIntoContainer (node_modules/react/lib/ReactMount.js:550:32)
      at Object.ReactMount.render (node_modules/react/lib/ReactMount.js:570:23)
      at Object.wrapper Æas renderÅ (node_modules/react/lib/ReactPerf.js:66:21)
      at Object.ReactTestUtils.renderIntoDocument (node_modules/react/lib/ReactTestUtils.js:76:21)
      at renderWithOptions (node_modules/enzyme/build/react-compat.js:175:26)
      at new ReactWrapper (node_modules/enzyme/build/ReactWrapper.js:87:59)
      at mount (node_modules/enzyme/build/mount.js:21:10)
      at Context.<anonymous> (Welcome_spec.js:9:21)
/* package.json */

{
  "name": "TestApp",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "mocha --require ./test/setup.js --compilers js:babel-core/register 'test/**/*.@(js|jsx)'"
  },
  "dependencies": {
    "immutable": "^3.7.6",
    "react-native": "^0.21.0",
    "react-native-button": "^1.4.2",
    "react-native-code-push": "^1.8.0-beta",
    "react-native-communications": "^0.2.3",
    "react-native-gifted-messenger": "0.0.21",
    "react-native-gifted-spinner": "0.0.3",
    "react-native-router-flux": "^2.3.12",
    "react-redux": "^4.4.0",
    "redux": "^3.3.1"
  },
  "devDependencies": {
    "babel-cli": "^6.6.5",
    "babel-core": "^6.7.2",
    "babel-plugin-transform-es2015-modules-commonjs": "^6.7.0",
    "babel-polyfill": "^6.7.2",
    "babel-preset-airbnb": "^1.1.1",
    "babel-preset-es2015": "^6.6.0",
    "babel-preset-react": "^6.5.0",
    "babel-preset-react-native": "^1.5.2",
    "babel-preset-stage-1": "^6.5.0",
    "chai": "^3.5.0",
    "chai-enzyme": "^0.4.1",
    "chai-immutable": "^1.5.3",
    "enzyme": "^2.1.0",
    "jsdom": "^8.1.0",
    "mocha": "^2.4.5",
    "proxyquire": "^1.7.4",
    "react": "^0.14.7",
    "react-addons-test-utils": "^0.14.7",
    "react-dom": "^0.14.7",
    "react-native-mock": "0.0.6",
    "redux-devtools": "^3.1.1",
    "sinon": "^1.17.3",
    "slash": "^1.0.0"
  }
}

/* setup.js - runs before mocha tests */

"use strict";
require("babel-polyfill");

var fs = require('fs');
var path = require('path');

function getBabelRC() {
  var rcpath = path.join(__dirname, '..', '.babelrc');
  var source = fs.readFileSync(rcpath).toString();
  return JSON.parse(source);
}

var config = getBabelRC();

config.ignore = function(filename) {
  if (!(/\/node_modules\//).test(filename)) {

    // if not in node_modules, we want to compile it
    return false; 

  } else if ((/\/node_modules\/react-native\//).test(filename)) {

    // it's RN source code, so we want to compile it
    return false;

  } else {
    // it's in node modules and NOT RN source code
    var modulesToCompileArray = [
      "react-native-button",
      "react-native-router-flux",
      "react-native-tabs",
      "exponent",
      "react-native-clone-referenced-element",
      "react-native-mock",
    ];

    for (var i = 0; i < modulesToCompileArray.length; i++) {
      if (filename.includes(modulesToCompileArray[i])) {
        return false;
      }
    }

    return true;
  }
}

require("babel-core/register")(config);

global.__DEV__ = true;

var chai = require('chai');
var chaiImmutable = require('chai-immutable');
var chaiEnzyme = require('chai-enzyme');

global.expect = chai.expect;
chai.use(chaiImmutable);
chai.use(chaiEnzyme())

var jsdom = require('jsdom');
const doc = jsdom.jsdom('<!doctype html><html><body></body></html>');
const win = doc.defaultView;
global.document = doc;
global.window = win;

require("react-native-mock/mock");
@rlau1115 rlau1115 changed the title Testing React Testing React Native components with images Mar 15, 2016
@pablolmiranda
Copy link

@rlau1115 looks like React Native create a map of images when you start the local server:

[11:32:18 AM] <END>   Crawling File System (1607ms)
[11:32:18 AM] <START> Building in-memory fs for JavaScript
[11:32:19 AM] <END>   Building in-memory fs for JavaScript (434ms)
[11:32:19 AM] <START> Building in-memory fs for Assets
[11:32:19 AM] <END>   Building in-memory fs for Assets (356ms)
[11:32:19 AM] <START> Building Haste Map
[11:32:19 AM] <START> Building (deprecated) Asset Map
[11:32:19 AM] <END>   Building (deprecated) Asset Map (74ms)
[11:32:19 AM] <END>   Building Haste Map (253ms)
[11:32:19 AM] <END>   Building Dependency Graph (2669ms)

Kiling the current server and running it again should solve your problem.

@Purii
Copy link

Purii commented Apr 11, 2016

Same issue here. @pablolmiranda which server do you mean? Enzyme runs with react-native-mock?

@benjick
Copy link

benjick commented May 2, 2016

@Purii Did you ever figure it out? I'm running with react-native-mock as well. babel-plugin-transform-assets got me a bit closer, but image imports now gives me Error: ./src/Theme/index.js: Found empty import from ./assets/closeWhite.png.

@slamus
Copy link

slamus commented May 2, 2016

Hey Guys,

I had this problem, now I use mockery module to prevent PNG errors.
Here's an example:

import mockery from "mockery";

mockery.enable();
mockery.registerMock('../img/gender_male.png', 0)

import React from "react-native";
const {
  Text,
  TouchableHighlight,
  TouchableOpacity,
  Image,
} = React


import { shallow } from "enzyme";

// Your Tests

Mockery replaces my require('../img/gender_male.png') with a number (which is an accepted propType for the Image.src prop) .
Careful, I had to write the exact same path as written in the tested component to override it.

@pcarion
Copy link

pcarion commented May 6, 2016

I had the same issue. Was fixed by restarting the server/packager.

@tiye
Copy link

tiye commented May 31, 2016

Into this problem too. I tried babel-plugin-transforms-assets and failed, then I found it's using asset-require-hook so I install and import that package directly. Now it's warnings rather than an excetion.

@danielbh
Copy link

Use mockery. thanks @slamus

@julien-rodrigues
Copy link

julien-rodrigues commented Jul 21, 2016

I'm sorry but I really don't understand why people are saying "restart the packager"..
Do you start the packager for testing purpose? If yes, how do you run the tests from the scope of the packager?

The solution of killing it works when you are working on the app and you add a new image and the packager doesn't have any ref to it. So you're in the scope of the app, that's sure. So it seems there is a misunderstanding of the current issue.

I have the problem right now on one of my test but all my other ones are working without having to start the RN Packager.

I can't use mockery because I'm actually looking for a way to test that the image rendered is the one I expect (component displaying the app logo). I was thinking to test the path of the image or something like that.

EDIT
After doing some testing, I had it to work.
I tested mocha-image-compiler but I had warnings in the console as it has not been made to be used specifically in React.
Then I found out mockery did the job.
I just had to mock the uri of the image and then compare the source of the tested image to the mock.

@varmais
Copy link

varmais commented Aug 4, 2016

I wrote about this issue a couple of days ago: http://valuemotive.com/2016/08/01/unit-testing-react-native-components-with-mocha-and-enzyme/ See "Ignoring Images on React Native Tests".

No need for mockery and doesn't produce proptype warnings. There might be couple of other useful tips too :)

EDIT: Seems that my previous employer has moved the blog elsewhere. Check my example repo: https://github.com/varmais/react-native-unit-tests and especially https://github.com/varmais/react-native-unit-tests/blob/master/mocha-setup.js#L3-L12

@ljharb
Copy link
Member

ljharb commented Jul 6, 2018

You'd need a react native adapter to use enzyme with React Native.

Closing this in favor of #1436.

@ljharb ljharb closed this as completed Jul 6, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests