1

I am working on a large ReactJS based website and need to write some test where I can defer loading of various modules because I need to have Sinon set up first.

The basic setup looks like this

const assert = require('chai').assert;
const sinon = require('sinon');
const reducerUtils = require('../../app/utils/reducerUtils');
const connectToReducerStub = sinon.stub(
  reducerUtils,
  'connectToReducer',
  (stateMap, actionMap) => { console.log(`Connecting to reducer`); }
);

At this point I just need to import a component that tries to use reducerUtils.connectToReducer that I've stubbed away, but my issue is that if I do like everywhere else in the codebase:

import MyComponent from '../../app/components/myComponent.jsx';

The import is run as the first thing (before everything else), making the import to- and call to reducerUtils.connectToReducer take place before I get to stub it away.

On the other hand, trying to just defer it by using require doesn't seem to work:

const MyComponent = require('../../app/components/myComponent.jsx');

What happens here is that MyComponent is just undefined.

I'm using ES6 classes to define my components along the lines of:

import react from 'react';
import connectToReducer from '../../utils/reducerUtils';

class MyComponent {
  ...
}

export connectToReducer(<stateMap>, <actionMap>)(MyComponent);

After having played around with trying to make require work, I gave up and tried SystemJS as an alternative module loader, but it doesn't resolve paths the same way that require does, so it seems that most module paths have to be set up by hand.

mzedeler
  • 4,177
  • 4
  • 28
  • 41

2 Answers2

1

import statements are executed before the rest of your module, as you noticed. See this answer for more info.

It should work with require(), but because ES6 modules have a notion of a "default import/export" (which you're using), and require() doesn't, the workaround is that the default exports is made accessible through the default property.

In other words:

const MyComponent = require('../../app/components/myComponent.jsx').default;
Community
  • 1
  • 1
robertklep
  • 198,204
  • 35
  • 394
  • 381
  • Thanks! Actually I found a bug in my code making the `require` fail. Once the bug was removed, it worked. – mzedeler Aug 29 '16 at 15:02
0

The problem is that the connectToReducerStub must return the original component or the component wrapped another component:

const connectToReducerStub = sinon.stub(
  reducerUtils,
  'connectToReducer',
  (stateMap, actionMap) => {
    return component => {
      const props = ...
      const wrapper = <MyWrapper><component {...props} /></MyWrapper>;
      return wrapper;
    };
  }
);
mzedeler
  • 4,177
  • 4
  • 28
  • 41