i-like-robots / rewireify

Rewireify is a port of Rewire for Browserify that adds setter and getter methods to each module so that their behaviour can be modified for better unit testing.
https://www.npmjs.com/package/rewireify
Other
59 stars 10 forks source link

Problem ES6 module syntax #21

Closed gseerden closed 8 years ago

gseerden commented 8 years ago

Hi,

I'm having trouble making rewirefify work with the ES6 module syntax. My setup includes browserify and karma.

karma.conf.js:

preprocessors: {
    'test/**/*_test.js': ['browserify']
},
browserify: {
    debug: true,
    transform: ['rewireify', 'babelify']
}, 

my_module_test.js

import MyModule from './my_module';

var Mock;
MyModule.__set__('OtherModule', Mock);

my_module.js

import OtherModule from 'other_module';

var MyModule = {
    // ...
};

export default MyModule;

This results in

  ReferenceError: assignment to undeclared variable DocumentStore

But it'll run fine when I use commonJS syntax in my_module.js

var OtherModule = require('other_module');

var MyModule = {
    // ...
};

At first, I thought it had something to do with the order of the browserify transforms. But it doesn't. What did I miss?

i-like-robots commented 8 years ago

It's because the ES6 module syntax is being transformed by Babel and so the properties you're expecting do not exist. Babel will take care to update references within a module but not outside - after all they're meant to be private!

So the following:

'use strict'

import MyModule from './module-a';

var SomeModule = {
    // ...
}

export default SomeModule;

Is transformed into:

'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});

var _moduleA = require('./module-a');

var _moduleA2 = _interopRequireDefault(_moduleA);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var SomeModule = {
    // ...
};

exports.default = SomeModule;

So any tests using Rewireify referencing MyModule will not work because it's been translated to _moduleA and any usage of MyModule will be updated to use the interoperable _moduleA2.