Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Mocha working with React Native - errors w/ requiring & addons

I've been trying to get Mocha to work with React Native. This is what I've done so far (following the Mocha docs):

-added a test folder

-added a test.js file inside the test folder

-added a simple test to the test.js file

var assert = require("assert");
describe('Array', function() {
  describe('#indexOf()', function () {
    it('should return -1 when the value is not present', function () {
      assert.equal(-1, [1,2,3].indexOf(5));
      assert.equal(-1, [1,2,3].indexOf(0));
    });
  });
});

-i ran 'mocha' in the terminal, and the test passed.

Now, what I'm stuck on: when I try to require a module (for example one of them is called Search)

var Search = require("./../Search");

I get:

var {
^
Unexpected token {
  Search.js:6
  var {
      ^
SyntaxError: Unexpected token {
      at exports.runInThisContext (vm.js:53:16)
      at Context.<anonymous> (test/test.js:6:14)

which is referring to the destructuring assignment I have in Search.js

"use strict";

var React = require("react-native");
var SearchBooks = require("./../SearchBooks");

var {
  Component,
  NavigatorIOS,
  StyleSheet,
} = React;

so I did

npm install --save-dev babel

and added

"scripts": {
"test": "mocha --compilers js:babel/register"
}

to package.json, so now it can be required without error when I run with "npm test." However, I still can't require React addons. var React = require('react/addons'); and it throws Error: Cannot find module 'React'.

So I install React and try npm test again. Then I get Error: Cannot find module 'ActivityIndicatorIOS', and that's where I'm at now. This error is coming form react native's own js file, which is why I think I'm just doing something wrong.

Do React's TestUtils even work with React Native in the first place? Does anyone have any suggestions about what I'm doing wrong, what can be done to mediate the error, or how to properly get Mocha to work with React Native?

(I also tried using Jest, but for one, it's super slow (I used a similar test and it took nearly 2 seconds), and two, I ended up getting errors there, too, though I can't remember exactly what they were.)

like image 283
KirRogue Avatar asked Nov 18 '25 07:11

KirRogue


1 Answers

ActivityIndicatorIOS is a native component, and these can't run under npm (npm is Node/V8 on a PC vs React Native being JavaScriptCore bridging with a mobile environment). Therefore, you need to mock any native components used in any code loaded by your tests.

react-native-simple-auth has an example of using mocha, chai, proxyquire and sinon.spy to unit test a component. It's not a perfect solution, but works great for testing pure JS React Native code:

let expect = require('chai').use(require("sinon-chai")).expect;
let proxyquire = require('proxyquire');
let sinon = require('sinon');

describe('SimpleAuthClient', () => {

  let configureSpy;
  let authorizeSpy;
  let simpleAuthClient;

  before(() => {
    configureSpy = sinon.spy();
    authorizeSpy = sinon.spy();
    simpleAuthClient = proxyquire('../lib/simpleauthclient', {
      'react-native': {
        NativeModules: {
          SimpleAuthWrapper: {
            configure: configureSpy,
            authorize: authorizeSpy
          }
        },
        '@noCallThru': true
      }
    });
  });

  afterEach(() => {
    configureSpy.reset();
    authorizeSpy.reset();
  });

  after(() => {
    configureSpy = null;
    authorizeSpy = null;
    simpleAuthClient = null;
  });

  it('should instantiate ok', () => {
    expect(simpleAuthClient).to.be.ok;
  });

  it('should configure a single provider', () => {
    simpleAuthClient.configure('foo', {bar: 'baz'});
    expect(configureSpy).to.have.been.calledWith('foo', {bar: 'baz'});
  });

  it('should configure a multiple providers', () => {
    simpleAuthClient.configure({
      foo: {
        bar: 'baz'
      },
      qux: {
        quux: 'quuux'
      }
    });
    expect(configureSpy).to.have.been.calledTwice;
    expect(configureSpy.firstCall).to.have.been.calledWith('foo', {bar: 'baz'});
    expect(configureSpy.secondCall).to.have.been.calledWith('qux', {quux: 'quuux'});
  });

  it('should authorize the given provider', () => {
    simpleAuthClient.authorize('foo');
    expect(authorizeSpy).to.have.been.calledWith('foo');
  });

});
like image 82
pjcabrera Avatar answered Nov 20 '25 21:11

pjcabrera