react-native-mock icon indicating copy to clipboard operation
react-native-mock copied to clipboard

Issues with mocking interfering with 3rd-party node modules

Open rlau1115 opened this issue 9 years ago • 15 comments
trafficstars

I'm having some issues getting a basic test to compile. I'm fairly new to React Native / Mocha / Babel so any insight would be helpful.

I followed your advice regarding forcing babel to compile node modules here, with some modifications of my own due to some problematic modules. However, now the issue seems to be that there is a conflict between react-native-mock getting in the way of an external node module ("react-native-router-flux" in this case) from functioning properly.

Any thoughts would be greatly appreciated!

/* .babelrc */

{ 
  "presets": ["stage-1", "react-native"]
}
/* MyComponent.js */

'use strict';

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

class MyComponent extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.baseText}>Test!</Text>
        <Button onPress={()=>Actions.login({data:"Custom data", title:'Custom title' })}>Go to Login page</Button>
        <Button onPress={Actions.signup}>Go to Register page</Button>
      </View>
    );
  }
}

var styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: 'transparent',
    },
    baseText: {
      fontFamily: 'Raleway-Regular'
    }
});

module.exports = MyComponent;
/* MyComponent_spec.js */

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

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

describe("<MyComponent/>", () => {
  it('should render', () => {
    const wrapper = shallow(<MyComponent />);
    expect(wrapper).to.be.ok;
  });
});
/* package.json */

{
  "name": "Test",
  "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-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-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-immutable": "^1.5.3",
    "enzyme": "^2.1.0",
    "mocha": "^2.4.5",
    "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"
  }
}
/* ./test/setup.js */

"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",
    ];

    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');

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

require("react-native-mock/mock");

This is the error that I get when running the tests.

npm run test

> [email protected] test .../src...
> mocha --require ./test/setup.js --compilers js:babel-core/register 'test/**/*.@(js|jsx)'
.../src.../node_modules/@exponent/react-native-navigator/ExSceneConfigs.js:193
Fade:_reactNative.Navigator.SceneConfigs.FadeAndroid,
                                        ^

TypeError: Cannot read property 'FadeAndroid' of undefined
    at Object.<anonymous> (ExSceneConfigs.js:193:9)
    at Module._compile (module.js:413:34)
    at loader (.../src.../node_modules/babel-core/node_modules/babel-register/lib/node.js:126:5)
    at Object.require.extensions.(anonymous function) [as .js] (.../src.../node_modules/babel-core/node_modules/babel-register/lib/node.js:136:7)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at Object.<anonymous> (ExRouteRenderer.js:16:1)
    at Module._compile (module.js:413:34)
    at loader (.../src.../node_modules/babel-core/node_modules/babel-register/lib/node.js:126:5)
    at Object.require.extensions.(anonymous function) [as .js] (.../src.../node_modules/babel-core/node_modules/babel-register/lib/node.js:136:7)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at Object.<anonymous> (ExNavigator.js:16:1)
    at Module._compile (module.js:413:34)
    at loader (.../src.../node_modules/babel-core/node_modules/babel-register/lib/node.js:126:5)
    at Object.require.extensions.(anonymous function) [as .js] (.../src.../node_modules/babel-core/node_modules/babel-register/lib/node.js:136:7)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at Object.<anonymous> (ExRouter.js:5:1)
    at Module._compile (module.js:413:34)
    at loader (.../src.../node_modules/babel-core/node_modules/babel-register/lib/node.js:126:5)
    at Object.require.extensions.(anonymous function) [as .js] (.../src.../node_modules/babel-core/node_modules/babel-register/lib/node.js:136:7)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at Object.<anonymous> (Router.js:12:1)
    at Module._compile (module.js:413:34)
    at loader (.../src.../node_modules/babel-core/node_modules/babel-register/lib/node.js:126:5)
    at Object.require.extensions.(anonymous function) [as .js] (.../src.../node_modules/babel-core/node_modules/babel-register/lib/node.js:136:7)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at Object.<anonymous> (index.js:4:1)
    at Module._compile (module.js:413:34)
    at loader (.../src.../node_modules/babel-core/node_modules/babel-register/lib/node.js:126:5)
    at Object.require.extensions.(anonymous function) [as .js] (.../src.../node_modules/babel-core/node_modules/babel-register/lib/node.js:136:7)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at Object.<anonymous> (Welcome.js:6:15)
    at Module._compile (module.js:413:34)
    at loader (.../src.../node_modules/babel-core/node_modules/babel-register/lib/node.js:126:5)
    at Object.require.extensions.(anonymous function) [as .js] (.../src.../node_modules/babel-core/node_modules/babel-register/lib/node.js:136:7)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at Object.<anonymous> (Welcome_spec.js:5:1)
    at Module._compile (module.js:413:34)
    at loader (.../src.../node_modules/babel-core/node_modules/babel-register/lib/node.js:126:5)
    at Object.require.extensions.(anonymous function) [as .js] (.../src.../node_modules/babel-core/node_modules/babel-register/lib/node.js:136:7)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at .../src.../node_modules/mocha/lib/mocha.js:219:27
    at Array.forEach (native)
    at Mocha.loadFiles (.../src.../node_modules/mocha/lib/mocha.js:216:14)
    at Mocha.run (.../src.../node_modules/mocha/lib/mocha.js:468:10)
    at Object.<anonymous> (.../src.../node_modules/mocha/bin/_mocha:403:18)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Function.Module.runMain (module.js:447:10)
    at startup (node.js:141:18)
    at node.js:933:3

npm ERR! Darwin 15.3.0
npm ERR! argv "/Users/noobs/.nvm/versions/node/v5.7.1/bin/node" "/Users/noobs/.nvm/versions/node/v5.7.1/bin/npm" "run" "test"
npm ERR! node v5.7.1
npm ERR! npm  v3.6.0
npm ERR! code ELIFECYCLE
npm ERR! [email protected] test: `mocha --require ./test/setup.js --compilers js:babel-core/register 'test/**/*.@(js|jsx)'`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] test script 'mocha --require ./test/setup.js --compilers js:babel-core/register 'test/**/*.@(js|jsx)''.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the TestApp package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     mocha --require ./test/setup.js --compilers js:babel-core/register 'test/**/*.@(js|jsx)'
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs TestApp
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls TestApp
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     .../src.../npm-debug.log

rlau1115 avatar Mar 11 '16 07:03 rlau1115

Also, worth noting that a simple test on a component with no 3rd party node modules passes, if it's the only test running in the suite.

/* TestComponent_spec.js */

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

import TestComponent from '../../../react/components/atoms/TestComponent'

describe("<TestComponent/>", () => {
  it('should be ok', () => {
    expect(true).to.be.ok;
  });

  it('should render stuff', () => {
    const wrapper = shallow(<TestComponent />);
    expect(wrapper.length).to.equal(1);
    expect(wrapper.contains(<Text>I wonder if there will be any problems...</Text>)).to.equal(true);
  });
});
/* TestComponent.js */

import React from "react-native";

const {
  View,
  Text
} = React;

export default class TestComponent extends React.Component {
  render() {
    return (
      <View>
        <Text>I wonder if there will be any problems...</Text>
      </View>
    );
  }
}

rlau1115 avatar Mar 11 '16 08:03 rlau1115

@rlau1115 I'm wondering if you found a fix or work around, facing the same issue :disappointed:

vysakh0 avatar Apr 05 '16 04:04 vysakh0

Unfortunately no :( Had to skip testing since I was under the gun for a release.

rlau1115 avatar Apr 05 '16 04:04 rlau1115

@rlau1115 Ah! :( thank you for the quick reply :smiley:

vysakh0 avatar Apr 05 '16 04:04 vysakh0

@rlau1115 @vysakh0 I feel that it's most RN wannabe-testers destiny... :(

slamus avatar May 02 '16 15:05 slamus

+1

sattaman avatar May 17 '16 09:05 sattaman

@rlau1115 Looks like some kind of problem in the code of exponent. The mock for navigator exposes that scene config properly. Whilst trying to use react-native-router-flux, I gave up trying to get it to work and just used Mockery to write a custom mock for that module. @sattaman Is this still happening with the most recent version?

RealOrangeOne avatar May 20 '16 15:05 RealOrangeOne

hey @RealOrangeOne can u provide an example or snippet of using Mockery to handle react-native-router-flux?

sibelius avatar May 29 '16 22:05 sibelius

@sibeliusseraphini Unfortunately the code I used is closed source by my company. I think that's more an issue for the react-native-router-flux repo, as it doesnt affect react-native-mock

RealOrangeOne avatar May 29 '16 22:05 RealOrangeOne

this is my testHelper.js

require('babel-polyfill');
require('react-native-mock/mock');

// require('babel-core/register')({
//   ignore: function(packageName) {
//     if (packageName.match(/node_modules/)) {
//       return !(packageName.match(/react-native-vector-icons/)
//         || packageName.match(/react-native-animatable/)
//         || packageName.match(/react-native-router-flux/)
//         || packageName.match(/react-native-tab-navigator/)
//       );
//     }
//     return false;
//   }
// });

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)) {
    console.log(filename, 'FALSE');
    return false; // if not in node_modules, we want to compile it
  } else if ((/\/node_modules\/react-native.*\//).test(filename)) {
    // its RN source code, so we want to compile it
    console.log(filename, 'FALSE');
    return false;
  } else {
    console.log(filename, 'TRUE');
    // it's in node modules and NOT RN source code
    return true;
  }
};

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

global.__DEV__ = true;


// var chai = require('chai');
// var dirtyChai = require('dirty-chai');
// chai.use(dirtyChai);

import chai from 'chai';
import dirtyChai from 'dirty-chai';
// import chaiImmutable from 'chai-immutable';

chai.use(dirtyChai);
//chai.use(chaiImmutable);

import mockery from "mockery";

mockery.enable();
mockery.registerMock('./node_modules/react-native-router-flux/src/menu_burger.png', 0);

and this is my npm test

"test": "node_modules/.bin/mocha --compilers js:babel-core/register --require testHelper.js **/__test__/*.js",

Maybe this could help @rlau1115 @vysakh0

sibelius avatar May 29 '16 23:05 sibelius

only the image part is not working properly

sibelius avatar May 29 '16 23:05 sibelius

Youre not setting up mockery correctly, the path is the path it imports not the path to the file. Please see mockery docs

RealOrangeOne avatar May 30 '16 07:05 RealOrangeOne

How can I add some custom mock for some custom library like https://github.com/luggg/react-native-config?

sibelius avatar Jun 08 '16 17:06 sibelius

Using mockery http://stackoverflow.com/a/37655424/168012

sattaman avatar Jun 08 '16 17:06 sattaman

config.ignore function suggested by @sibelius worked for me - was having issues with spread operator in a 3rd party module

callmephilip avatar Jul 28 '16 18:07 callmephilip