speedskater / babel-plugin-rewire Goto Github PK
View Code? Open in Web Editor NEWA babel plugin adding the ability to rewire module dependencies. This enables to mock modules for testing purposes.
A babel plugin adding the ability to rewire module dependencies. This enables to mock modules for testing purposes.
Let's say I have a React component as follows:
import React from 'react';
const InfoButton = ({enabled}) => (
<div className={enabled ? 'enabled' : ''}>Info</div>
);
export default InfoButton;
Here I'm using React 0.14's new stateless functional component syntax but the problem applies to any React component.
Despite not explicitly using the React
import I have to define it or Babel will complain and fail. However this is a bit annoying not least because of the eslint warnings but also because it's unclear to other developer why that seemingly redundant line needs to be there.
So, I discover babel-plugin-react-require
and now I can remove the problematic import React from 'react';
line.
However when using this plugin alongside babel-plugin-rewire
as we do in our tests we get the following error:
ERROR in ./InfoButton.jsx
Module build failed: TypeError: ./InfoButton.jsx: Cannot set property 'constant' of undefined
at ./node_modules/babel-plugin-rewire/src/babel-plugin-rewire.js:242:49
at Array.forEach (native)
at NodePath.Plugin.visitor.ImportDeclaration (./node_modules/babel-plugin-rewire/src/babel-plugin-rewire.js:236:21)
Hey! I'm currently stuck with this error:
var Bla = _BlaTemp;
^
ReferenceError: _BlaTemp is not defined
That's because my Bla
is an import of a flow type:
import type Bla from './Bla';
And Bla
exports a type:
export type Bla = 'BLABLA' | 'BLAH';
Well, I dunno if it is a problem with this plugin, it could be something with babel. But the point is that those import type
declarations should be ignored.
Getting a whole bunch of errors now.
TypeError: intlStore.getState is not a function
at IntlConnection.render (/Users/shawnlim/Documents/react/Boa/tests/tests_index.js:30304:31 <- webpack:///src/utils/connect-to-intl-store.js:24:27)
Error: Store IntlStore was not registered.
at DispatcherContext.getStore (/Users/shawnlim/Documents/react/Boa/tests/tests_index.js:23755:20 <- webpack:///~/fluxible/~/dispatchr/lib/DispatcherContext.js:39:0)
at MockComponentContext.getStore (/Users/shawnlim/Documents/react/Boa/tests/tests_index.js:23958:36 <- webpack:///~/fluxible/utils/MockComponentContext.js:18:0)
and many more errors.
I am simply doing this at the start of my test:
LoginForm.__Rewire__("FormattedMessage", React.createClass({
render: function(){
return <div />;
}
}))
describe('LoginForm', function() {
var context;
var TestUtils;
var MockIntlStore;
var MockAuthStore;
var component;
var foundComponent;
var LoginFormWrap;
beforeEach(function(){
// mock and stub out the flux's dependencies so we can test just the component's interactions
MockIntlStore = createStore({
storeName: 'IntlStore',
getMessage: function(){}
});
MockAuthStore = createStore({
storeName: 'AuthStore'
});
context = createMockComponentContext({
stores: [MockIntlStore, MockAuthStore]
});
the intlStore.getState shouldn't even be called. On 1.3 it works.
Getting an error when performing simple rewire inside of karma test
TypeError: Plugin "rewire" is resolving to a different Babel version than what is performing the transformation.
The list for babel-core looks as follows, they all seem to use 5.7.4, confused how could it possibly in any way resolve to different versions of babel
├─┬ [email protected]
│ └── [email protected]
├── [email protected]
├─┬ [email protected]
│ └── [email protected]
├─┬ [email protected]
│ └── [email protected]
└─┬ [email protected]
└── [email protected]
my config:
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
// we use this pattern to load test files
// see https://github.com/webpack/karma-webpack/issues/23
'tests/tests_index.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'tests/tests_index.js': [ 'webpack', 'sourcemap' ]
},
webpack: {
devtool: 'cheap-source-map',
module: {
loaders: [
{ test: /\.js$/, exclude: /node_modules/, loaders: ["babel?plugins=babel-plugin-rewire"] } // loaders can take parameters as a querystring
]
}
},
webpackServer: {
noInfo: true //please don't spam the console when running in karma!
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['dots','html'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
});
};
when i do that, then i get the following error:
Uncaught TypeError: Object.assign is not a function
at /blah/tests/tests_index.js:953
The error goes away if i remove plugins=babel-plugin-rewire
from loaders: ["babel?plugins=babel-plugin-rewire"]
I prefer to keep cleanup-code out of my actual specs, and thought maybe it would be possible to return a "restore" function from __Rewire__
like the original rewire does?
var revert = myModule.__set__("port", 3000);
// port is now 3000
revert();
// port is now the previous value
First, thanks for your work on this plugin.
I have the following issue when try to export an object:
// config.js
export let config = { mode: 'development' };
// other_module.js
import { config } from './config.js';
console.log(config.mode);
The test bundle compiles ok, but upon execution in the browser it dies with the following error:
Uncaught TypeError: Cannot read property 'mode' of undefined
// webpack config
module: {
loaders: [
{
test: /\.jsx?$/,
include: path.resolve(__dirname, 'js'),
loader: 'babel-loader',
query: {
cacheDirectory: '/tmp',
plugins: ['babel-plugin-rewire']
}
},
]
},
I am using lastest webpack and babel. If I disable the plugin everything is ok. I looked through the transpiled code and I couldn't see anything wrong. Any ideas what could be causing this, or how I can debug?
If a module containing a declaration like import type {someType} from './someFile';
is imported when babel-plugin-rewire
is enabled, a ReferenceError
is thrown:
var someType = _someTypeTemp;
^
ReferenceError: _someTypeTemp is not defined
Other uses of flow don't have any issues, so for now I can work around this by re-declaring the type inside the module I'm testing.
This seems like it may be related to #69, but I'm not familiar enough with the internals of babel's flow-stripping transformer or of babel-plugin-rewire to know for sure.
Hey, I have a karma.conf.js with the following content:
var babelPluginRewire = require('babel-plugin-rewire');
module.exports = function (config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '../../',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['browserify', 'jasmine'],
[...]
browserify: {
debug: true,
plugin: ['tsify'],
transform: [['babelify', {plugins: [babelPluginRewire]}], ['stringify', {extensions: ['*.json']}]]
},
[...]
and I do not get any RewireApi object in my tests (the following test fails):
import React from 'react';
describe('rewire', () => {
it('works', () => {
expect(React.__RewireApi__).toBeDefined();
});
});
Can you help me with this?
I stumbled over a issue with mutual imports.
Within my code base I have situation like this:
mod1.js
import { SUCCESS, FAILURE } from '.mod2';
import { fun3 } from './mod3';
function start() {
let res = fun3(SUCCESS);
console.log(res);
let res = fun3(FAILURE);
console.log(res);
}
start();
mod2.js
import { STATUS } from './mod3';
export const SUCCESS = 'SUCCESS';
export const FAILURE = 'FAILURE';
function porcStatus() {
return STATUS;
}
mod3.js
import { SUCCESS, FAILURE } from './mod2';
export const STATUS = 'OK';
export function fun3(signal) {
switch (signal) {
case SUCCESS:
return 'positive';
case FAILURE:
return 'negative';
default:
return 'uups';
}
Processing these file with babel alone works fine the output is as expected
positive
negative
running the files with babel --plugins rewire
leads to the output
uups
uups
When running with rewire, at the stage of running the switch statement in fun3
the imported constants SUCCESS
and FAILURE
appear to be undefined.
I guess that is not really expected behavior or would there be some work around for this problem?
question is in the title--thanks!
A contrived example:
MyClass.js
export default class MyClass {
}
index.js
const MyClass = require('./MyClass');
MyClass.foo = 'bar';
export default MyClass;
This leads to an error whereby __Rewire__
is added to the MyClass
export in MyClass.js
and index.js
, causing Object.defineProperty
to fail the second time around:
Object.defineProperty(_defaultExport, '__Rewire__', {
'value': __Rewire__,
'enumberable': false
});
I'd love have a go at a PR for this but have never worked with the Babel internals and it looks a bit mad...
M
Say I have a custom FormattedMessage component with the following contents:
import { FormattedMessage } from "react-intl";
import connectToIntlStore from "../utils/connect-to-intl-store";
export default connectToIntlStore(FormattedMessage);
connectToIntlStore simply wraps the default FormattedMessage
component from react-intl
and returns a new component.
Afterwards I have a new component that depends on FormattedMessage
import React, { PropTypes, Component } from "react";
import FormattedMessage from '../formatted-message';
class LoginForm extends Component {
constructor(props) {
super(props);
this.state = {
username: '',
pass: ''
};
}
render(){
return (
<div className="login-form">
<FormattedMessage {...this.props} />
</div>
)
}
}
export default LoginForm
In my spec I require LoginForm
:
LoginForm.__Rewire__("TestComp", React.createClass({
render: function() { return <div />; }
}));
LoginForm.__ResetDependency__("TestComp");
describe('LoginForm', function() {
var component;
var foundComponent;
beforeEach(function(){
component = TestUtils.renderIntoDocument(
<LoginForm />
);
foundComponent = TestUtils.findRenderedDOMComponentWithClass(
component, 'login-form');
});
it("renders", function() {
expect(foundComponent).toBeDefined();
});
it("should have an initial state", function() {
let componentState = component.state
let initialState = {
username: '',
pass: ''
}
expect(componentState).toEqual(initialState);
});
});
This will then break with the following error which should never show up if FormattedMessage was properly stubbed:
WARN: 'Warning: Failed Context Types: Required context `getStore` was not specified in `IntlConnection`. Check the render method of `LoginForm`.'
WARN: 'Warning: Failed Context Types: Required context `getStore` was not specified in `IntlConnection`. Check the render method of `LoginForm`.'
Chrome 43.0.2357 (Mac OS X 10.10.1) LoginForm should have an initial state FAILED
TypeError: this.context.getStore is not a function
It passes immediately when I replaced FormattedMessage's contents with:
import React, { PropTypes, Component } from "react";
export default class TestComp extends Component {
render(){
return (
<p>Substitute</p>
)
}
}
The plugin does not seem to work if the stubbed component is a wrapper.
babel-plugin-rewire should make sure that if you Object.keys() on a module that you don't see the added functions in the array:
[ 'myKey1',
'myKey2',
'__GetDependency__',
'__get__',
'__Rewire__',
'__set__',
'__ResetDependency__' ]
I fixed this in my package rewire-global
And we just fixed this in rewireify: i-like-robots/rewireify#14
I spent hours today troubleshooting an issue in which I had two React components that imported one another. I was using @badsyntax's react-seed project as a starting point for my project, which has the following line:
jsxLoader = ['babel-loader?optional[]=runtime&stage=0&plugins=rewire'];
After pulling my hair out as to why one of my modules was seeing the other as undefined, assuming the issue was with my code, I tried removing rewire from the loader configuration, and everything worked as expected.
I'm afraid I don't have much more information to supply at this point, but thought it was worth sharing in case it's a known issue.
Hey there,
Well done on the plugin! I've come across a bug, when wiring the plugin into Babel, then attempting to use it with my unit tests.
The class I'm using is this one:
import 'isomorphic-fetch';
/**
* Eclipse API client
*
* This class is the main client for the Eclipse API. It relies on environment variables (set on
* compilation of browser code and )
*/
export default class EclipseClient
{
constructor() {
if (process.env.NODE_ENV !== 'production') {
this.apiUrl = 'http:///';
} else {
this.apiUrl = 'http:///';
}
}
// TODO: Write translation of varargs to proper body call for fetch
async sendRequest(...args) {
if (args.length == 0) {
return null;
}
try {
let result = await fetch(this.apiUrl, {});
if (result.status !== 200) {
throw new ServerException(result.status, 'Eclipse API Error!');
}
return await result.json();
} catch(e) {
throw(e);
}
}
}
And the error is as follows:
[08:40:16] SyntaxError in plugin 'gulp-mocha'
Message:
/Users/josh/Work/Projects/viewfinder-1.3/code/src/shared/utils/EclipseClient.js:39
exports['default'] = Object.assign(var EclipseClient = (function () {
^^^
Unexpected token var
Stack:
/Users/josh/Work/Projects/viewfinder-1.3/code/src/shared/utils/EclipseClient.js:39
exports['default'] = Object.assign(var EclipseClient = (function () {
^^^
SyntaxError: Unexpected token var
at exports.runInThisContext (vm.js:73:16)
at Module._compile (module.js:443:25)
at normalLoader (/Users/josh/Work/Projects/viewfinder-1.3/code/node_modules/babel-core/lib/babel/api/register/node.js:147:5)
at Object.require.extensions.(anonymous function) [as .js] (/Users/josh/Work/Projects/viewfinder-1.3/code/node_modules/babel-core/lib/babel/api/register/node.js:160:7)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Module.require (module.js:365:17)
at require (module.js:384:17)
at Object.<anonymous> (/Users/josh/Work/Projects/viewfinder-1.3/code/tests/unit/utils/EclipseTest.js:9:36)
at Module._compile (module.js:460:26)
And I've traced the error to this line in the plugin:
return t.exportDefaultDeclaration(t.callExpression(t.memberExpression(t.identifier('Object'), t.identifier('assign')), [ node.declaration, t.objectExpression([
But I don't know enough about Babel's AST to fix it. Any ideas?
I'm now trying to work with a Karma Webpack setup, and without even trying to mock anything I get the following error from my tests:
INFO [karma]: Karma v0.12.37 server started at http://localhost:9876/
INFO [launcher]: Starting browser PhantomJS
INFO [PhantomJS 1.9.8 (Mac OS X 0.0.0)]: Connected on socket FV664eyGWLxApd_KTvrr with id 51361345
PhantomJS 1.9.8 (Mac OS X 0.0.0) ERROR
TypeError: Attempting to define property on object that is not extensible.
at /Users/me/myproject/app/components/__tests__/Something_test.js:26431
Any idea what might be wrong? I'm using babel 5.8 and webpack 1.10
I've set the webpack config to debug: 'inline-source-maps' but the line number from the error is not referencing the original souce. It's outside of the scope of this issue but if someone can give me advise on how to fix that I'd appreciate it :)
I can't figure out how to make this plugin work correctly. I'm using webpack and have installed the latest version of the plugin. I've tried adding the following to my webpack config:
module: {
loaders: [
{
test: /\.js$/,
loaders: ['react-hot', 'babel?stage=0', 'babel-loader?plugins=babel-plugin-rewire'],
include: path.join(__dirname, 'src/js')
},
...
}
I'm not seeing any errors from webpack, but when I then do the following:
sessionActions.js
export function login(email, password) {
...
};
tests/sessionActions-test.js
import * as SessionRewireAPI from '../sessionActions';
There is no __Rewire__
call being added to the module. Obviously I'm missing something and I can't figure out what. How exactly does the plugin get loaded? How can I test to see if it is getting loaded correctly?
I've also tried the following but then SesssionRewireAPI is just undefined.
import {login, __RewireAPI__ as SessionRewireAPI} from '../sessionActions';
if i use your plugin with webpack configuration: babel-loader?plugins=rewire
and in my code is:
for (var key in obj) {...}
i get:
Module build failed: Error: /Users/.../findInObj.js: We don't know what to do with this node type. We were previously a Statement but we can't fit in here? error message
Hi,
I updated my babel version to latest, and getting this error.
The plugin interface was changed and can you please have a look
https://babeljs.io/docs/advanced/plugins/
Module build failed: TypeError: The plugin "rewire" didn't export a Plugin instance
at PluginManager.validate (/usr/local/lib/node_modules/babel-loader/node_modules/babel-core/lib/transformation/file/plugin-manager.js:164:13)
at PluginManager.add (/usr/local/lib/node_modules/babel-loader/node_modules/babel-core/lib/transformation/file/plugin-manager.js:213:10)
at File.buildTransformers (/usr/local/lib/node_modules/babel-loader/node_modules/babel-core/lib/transformation/file/index.js:236:21)
at new File (/usr/local/lib/node_modules/babel-loader/node_modules/babel-core/lib/transformation/file/index.js:136:10)
at Pipeline.transform (/usr/local/lib/node_modules/babel-loader/node_modules/babel-core/lib/transformation/pipeline.js:164:16)
at transpile (/usr/local/lib/node_modules/babel-loader/index.js:12:22)
at Object.module.exports (/usr/local/lib/node_modules/babel-loader/index.js:69:12)
@ multi main
versions
"babel": "^5.8.3",
"babel-eslint": "^3.1.15",
"babel-loader": "^5.3.2",
"babel-plugin-rewire": "^0.1.11",
Wallaby.js is a test runner for various IDE's and text editors.
As it says in big letters, "wallaby runs your code as you write it".
I don't know how it works, exactly, but from what I can tell, the code is analyzed and modules or portions thereof are re-run as you type.
I'm running into an issue with the code generated by this plugin. Specifically, the following (and its ilk):
Object.defineProperty(_defaultExport, '__get__', {
'value': __GetDependency__,
'enumberable': false
});
Typo aside, this code will be run twice. The second run of the code will throw an exception, because the property is not configurable
.
This is one of those chicken-or-the-egg problems where I'm not sure if it's this module's fault or Wallaby's fault. I can't make Wallaby work with this module, but I can make this module work with Wallaby by making the property configurable.
Hello, I followed your instructions and added the required plugin webpack config to my karma config:
// use sepia to cache outgoing HTTP requests for faster tests
// karma first run will break if there is no fixtures. run a second time to ensure passing.
// process.env.VCR_MODE = 'cache';
// require('sepia');
// Karma configuration
// Generated on Tue Apr 07 2015 17:34:20 GMT+0800 (SGT)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
// we use this pattern to load test files
// see https://github.com/webpack/karma-webpack/issues/23
'tests/tests_index.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'tests/tests_index.js': [ 'webpack', 'sourcemap' ]
},
webpack: { //kind of a copy of your webpack config
devtool: 'inline-source-map', //just do inline source maps instead of the default
module: {
loaders: [
{ test: /\.js$/, exclude: /node_modules/, loaders: ["babel-loader?plugins=rewire"] } // loaders can take parameters as a querystring
]
}
},
webpackServer: {
noInfo: true //please don't spam the console when running in karma!
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// we need this proxy so that the karma server will call akamaru api which is running on localhost:5000
proxies: {
'/api': 'http://localhost:5000/api'
}
});
};
However, when i run karma start
, I am getting these errors:
Module build failed: TypeError: Transformer "rewire" is resolving to a different Babel version to what is doing the actual transformation...
at Transformer.buildPass (/Users/shawnlim/Documents/react/Boa/node_modules/babel-plugin-rewire/node_modules/babel-core/lib/babel/transformation/transformer.js:118:13)
at File.addPlugin (/Users/shawnlim/Documents/react/Boa/node_modules/babel-core/lib/babel/transformation/file/index.js:287:48)
at File.buildTransformers (/Users/shawnlim/Documents/react/Boa/node_modules/babel-core/lib/babel/transformation/file/index.js:215:12)
at new File (/Users/shawnlim/Documents/react/Boa/node_modules/babel-core/lib/babel/transformation/file/index.js:88:10)
at Object.transform (/Users/shawnlim/Documents/react/Boa/node_modules/babel-core/lib/babel/transformation/index.js:18:14)
at transpile (/Users/shawnlim/Documents/react/Boa/node_modules/babel-loader/index.js:54:24)
at Object.module.exports (/Users/shawnlim/Documents/react/Boa/node_modules/babel-loader/index.js:43:24)
This is in no way a criticism of your work, but I'm wondering if there is a reason this plugin seems to break so frequently? Is it because Babel is constantly changing how it handles things / API? There have been numerous "OMG!" moments lately where a deploy has broke due to babel-plugin-rewire, and it would be nice to either:
A) Mention the general API instability in the README, or perhaps think of another approach? Or
B) LIMIT the scope of this plugins reach similar to how the original Rewire does it:
var rewire = require('rewire');
var ClassToChange = rewire('path/to/file');
That way we're only worrying about certain areas of the app rather than attaching additional exports to every single module (which seems largely incorrect to me) which will break everything, rather than just tests.
Commentary appreciated.
Given the following, I notice that the functions in the tested file refer to the original, unwired functions.
// file.js
import { setupAjaxForm } from 'utils/APIUtils';
...
componentDidMount() {
setupAjaxForm('form'); // <-- this refers to _setupAjaxFormOrig()
}
// file-test.js
import APIUtils from 'utils/APIUtils';
APIUtils.__Rewire__('setupAjaxForm', jasmine.createSpy('setupAjaxForm'));
describe('#componentDidMount', function() {
it('should call setupAjaxForm', () => {
let {setupAjaxForm} = require('utils/APIUtils'); // <-- This refers to setupAjaxForm()
expect(setupAjaxForm).toHaveBeenCalled();
});
});
The result is tests fail since the spy function is never called.
The only way I managed to have them refer to the rewired copy of the function was by requiring them again inside componentDidMount, but that's not a tenable solution, in my view.
Rewiring static methods works ok. I am getting an issue when trying to rewire instance methods.
Example:
module aclass.es6:
import { BClass } from './bclass.es6';
class AClass {
constructor() {
this.bValue = BClass.aStaticMethod();
}
getBValue() {
return this.bValue;
}
getBName() {
return new BClass().getName();
}
}
export { AClass };
module bclass.es6:
class BClass {
constructor() {
this.name = 'B';
}
getName() {
return this.name;
}
static aStaticMethod() {
return 'static';
}
}
export { BClass };
and the tests:
import { AClass, __Rewire__ } from './aclass.es6';
describe('Test for rewiring dependencies of a class', function() {
__Rewire__('BClass', {
aStaticMethod: () => 'rewired static',
getName: () => 'rewired getName'
});
it('should rewire a static method', function() {
let theClass = new AClass();
theClass.getBValue().should.equal('rewired static');
});
it('should rewire an instance method', function() {
let theClass = new AClass();
theClass.getBName().should.equal('rewired getName');
})
});
Test for rewiring dependencies of a class
✓ should rewire a static method
1) should rewire an instance method
Is this case supported at all?
Hello,
Is it possible to get access to methods of an exported class. In my case a singleton flux
store, something like.
class TestStore extends Store {
constructor() {
super();
this.state = {};
}
handleAction(action) {
const {type, payload} = action;
switch (type) {
case 'TEST_ADD'
....
});
}
getState(){
return his.state;
}
}
export default TestStore.getInstance();
the super class method getInstance()
returns a singleton instance.
now, is there a way get hold of handleAction
in my test file. Something along the lines of
let handleAction = TestStore.__get__("handleAction");
when I tried I get error
TypeError: undefined is not a constructor (evaluating '__$Getters__[name]()') in http://0.0.0.0:3000/bundle.js (line 197)
I could probably export these private method to a public variable, and remove on production build. But, wonder is it possible without that.
When I enable babel-plugin-rewire I get errors in JSX compilation.
I've tried the fixes mentioned in this issue, enabling babel-runtime but this creates more errors.
Any ideas ?
node v2.3.1 (iojs)
babel-core 5.7.3
babel 5.6.23
babel-loader 5.3.2
I've noticed strange behaviour when using this export/import construct. It does not expose the original module, just object with the rewrite enhancement methods.
export { default } from './components/Table';
{ __GetDependency__: [Function: __GetDependency__],
__get__: [Function: __GetDependency__],
__Rewire__: [Function: __Rewire__],
__set__: [Function: __Rewire__],
__ResetDependency__: [Function: __ResetDependency__] }
You can find failing test for such a scenario in following commit kamilio@2b3b0fc
Thanks a lot
Functions that are defined in modules can't be rewired.
I'm getting such error once I call __Rewire__()
on a module in my test code:
TypeError: 'undefined' is not a function (evaluating '__$Setters__[name](value)')
Did you happen to see this error before? (I can set up a sample repo to reproduce that)
Rewire doesn't seem to be subbing in my mock. I get an error if I specify a dependency that doesn't exist so it seems to be hooking into the right one (config), but the config object still has the original path ('/something/images') as opposed to ('/images')
Test code
import ImageAsset from '../../src/js/assets/ImageAsset';
import {assert, expect} from 'chai';
ImageAsset.__Rewire__('config', {
compositionImagePath: '/images'
});
describe('ImageAsset:', () => {
let imageAsset;
beforeEach('create locally sourced image asset', () => {
imageAsset = new ImageAsset('local', 'LOCAL_0001.png');
});
it('should have a createjs load queue', () => {
expect(imageAsset.loadQueue).to.be.instanceof(window.createjs.LoadQueue);
});
it('should have its "type" property set to image', () => {
expect(imageAsset.type).to.equal('image');
});
it('should have it\'s app context id set to "LOCAL_0001"', () => {
expect(imageAsset.id).to.equal('LOCAL_0001');
});
describe('local strategy', () => {
it('should load a locally hosted image', () => {
imageAsset.load((success) => {
expect(success).to.equal(true);
expect(imageAsset.isLoaded).to.equal(true);
expect(imageAsset.path).to.equal('/images/LOCAL_0001.png');
});
});
});
describe('noun project strategy', () => {
});
});
Class - seems imageAssetStrategies.local.localImagePath is using the config.compositionImagePath from the original file (Ie no rewiring has happened).
import BaseAsset from './BaseAsset';
import config from '../config';
const imageAssetStrategies = {};
/**
* !! calls to loadImage() should be scoped to the ImageAsset instance.
*/
imageAssetStrategies.local = {
localImagePath: config.compositionImagePath,
appContextId(sourceId) {
return sourceId.split('.')[0];
},
loadImage(callback) {
const path = this.__strategy.localImagePath + '/' + this.sourceId;
// Set image asset specific properties
this.path = path;
this.isLoaded = true;
callback(true);
}
};
imageAssetStrategies.nounProject = {
appContextId() {
return 'NOUN_PROJECT_' + sourceId;
},
loadImage(callback) {
}
};
export default class ImageAsset extends BaseAsset {
constructor(strategy, sourceId) {
super(strategy, sourceId);
this.__strategy = imageAssetStrategies[this.strategy];
this.id = this.__strategy.appContextId(sourceId);
this.type = 'image';
}
_load(callback) {
this.__strategy.loadImage.apply(this, [callback]);
}
}
config.js
const config = {
compositionImagePath: '/comp-assets/images'
};
export default config;
I'm not sure what's causing this yet. I will close this bug if it turns out to be our fault. I included the babel rewire plugin in our webpack config:
babel-loader?plugins=rewire&optional=runtime
When I run webpack (building our test bundle), I get:
ERROR in vendors.js
Module build failed: TypeError: Filename must be a string
The content of vendors.js aren't anything exciting:
require('react');
require('lodash');
require('react-router');
The stack trace exits at
at Object.module.exports (/node_modules/babel-loader/index.js:43:24)
so I'm not sure what's originating the error. If I log inside that line to see what filename is it prints out a very large object that isn't immediately recognizable.
Does this plugin still work with regular require statements alongside es6 import statements? Actually, even if I make the contents of that file only import "react";
it gives me the same error...
Might be worth noting I'm using rewire-webpack, although this error still persists if I remove rewire-webpack it from my webpack plugins list.
rewire-webpack allows you to leak private variables and override variables within a module, not just the external module dependencies. This can be often useful for testing.
Is this something that might be possible in babel-plugin-rewire?
Got this error:
Module build failed: TypeError: Transformer "rewire" is resolving to a different Babel version to what is doing the actual transformation...
at Transformer.buildPass (/Users/shawnlim/Documents/react/Boa/node_modules/babel-core/lib/babel/transformation/transformer.js:114:13)
at PluginManager.add (/Users/shawnlim/Documents/react/Boa/node_modules/babel-loader/node_modules/babel-core/lib/babel/transformation/file/plugin-manager.js:138:55)
at File.buildTransformers (/Users/shawnlim/Documents/react/Boa/node_modules/babel-loader/node_modules/babel-core/lib/babel/transformation/file/index.js:287:21)
at new File (/Users/shawnlim/Documents/react/Boa/node_modules/babel-loader/node_modules/babel-core/lib/babel/transformation/file/index.js:150:10)
at TransformerPipeline.transform (/Users/shawnlim/Documents/react/Boa/node_modules/babel-loader/node_modules/babel-core/lib/babel/transformation/transformer-pipeline.js:96:16)
at transpile (/Users/shawnlim/Documents/react/Boa/node_modules/babel-loader/index.js:10:22)
at Object.module.exports (/Users/shawnlim/Documents/react/Boa/node_modules/babel-loader/index.js:65:12)
my babel versions npm ls babel-core
├─┬ [email protected]
│ └── [email protected]
├── [email protected]
└─┬ [email protected]
└── [email protected]
When exporting an object as in example below:
import { node } from 'utils/dom';
import React from 'react';
import Card from 'components/card.component';
class WelcomePanel extends Card {
constructor(props){
super(props);
}
render() {
return (
<div className="welcome-panel">
<Card content={node.toString()} />
</div>
)
}
initPanel(el,content){
React.render( <WelcomePanel content={content} />, el);
}
}
export default { WelcomePanel}
and importing it through destructuring:
import { assert } from 'chai';
import React, { Component } from 'react';
import { WelcomePanel as ComponentToTest } from 'modules/welcomePanel/welcomePanel.component';
'use strict'
describe('Tests General Configuration', function(){
it('should not be null', function(){
ComponentToTest.__Rewire__('node',"hey I'm mock")
let panel = new ComponentToTest
panel.initPanel(document.body,`This is message no `)
assert.isNotNull("Basic Test")
})
})
ComponentToTest.__ResetDependency__('node');
I get the following error:
Uncaught TypeError: $Resetters[name] is not a function
The same for $Setters[name]
Hi! I was trying out 0.1.23-beta-3 today and noticed that it doesn't seem to want to play nicely in my setup with Babel 5.8.33. No matter what I try, I'm seeing consistent reference errors relating to the name of the import.
I tried updating to Babel 6 and 1.0.0 beta, but ran into a host of incompatibilities with other modules I need (as I understand it that's not uncommon right now) so for now, I'm stuck on 5.x.
My .babelrc:
{
"stage": 0,
"env": {
"development": {
"plugins": ["react-transform"],
"extra": {
"react-transform": {
"transforms": [{
"transform": "react-transform-hmr",
"imports": ["react"],
"locals": ["module"]
}]
}
}
}
}
}
My webpack loader:
babel-loader?optional[]=runtime&stage=0&plugins=rewire
I'm sorry I don't have more information than this at the moment to reproduce, but I'm happy to gather anything else you need.
Thanks!
/Users/me/myproject/dist/tests.js:25909
module.exports.__GetDependency__ = __GetDependency__;
^
TypeError: Cannot assign to read only property '__GetDependency__' of true
I'm getting this as an error from webpack. Any idea what might be wrong?
webpack 1.10.1, babel 5.8.20
I am using Karma and Webpack to run this plugin.
This seems to occur around these lines:
if (typeof module.exports === 'object' || typeof module.exports === 'function') {
Object.defineProperty(module.exports, '__Rewire__', {
'value': __Rewire__,
'enumberable': false
});
This is my webpack loader config:
module: {
loaders: [
{
test: /\.(js|jsx|es6)$/,
exclude: '../../node_modules/',
loader: 'babel-loader?plugins=babel-plugin-rewire&modules=common&stage=0'
}
]
},
Currently the plugin can't handle non default async functions. When using them in the code the following error is given, this is not a problem without the plugin in Babel.
await promiseFunction();
^^^^^^^^^^^^^^^^^
SyntaxError: Unexpected identifier
I have solved this in a coming PR.
Hi.
In my mocha.opts
I use --compilers js:babel/register
so that I can write my tests in ES6.
Can you provide me a hint on how to use this with Mocha + Babel?
This plugin by necessity adds a bunch of method declarations to the output file. If you then run unit tests with code coverage, the fact that these generated methods aren't tested means that coverage levels are not reported correctly.
Istanbul supports adding comments to the code to indicate that the next entry is ignored, which will cause coverage levels to be better reported.
What's needed to support this is to add the comment:
/* istanbul ignore next */
immediately before the appropriate method declarations. This would be the declarations of:
It seems that rewiring a module does not isolate nested dependencies. I've got this structure:
- BodyComponent
- TextComponent
- ImageComponent
- CdnImageComponent
The CdnImageComponent
has logic to figure out what resolution we need in this particular case. The thing is, that shouldn't matter when testing BodyComponent
. I rewire TextComponent
and ImageComponent
like this:
var React = require('react');
var TestUtils = require('react/lib/ReactTestUtils');
var Component;
describe('BodyComponent', () => {
beforeEach(() => {
Component = require('../_body_component');
Component.__Rewire__('TextComponent', React.createClass({
render() { return <div className="TextComponent"></div> }
}));
Component.__Rewire__('ImageComponent', React.createClass({
render() { return <div className="ImageComponent"></div> }
}));
});
afterEach(() => {
Component.__ResetDependency__('TextComponent');
Component.__ResetDependency__('ImageComponent');
});
describe('TextComponent', () => { ... })
describe('ImageComponent', () => { ... })
});
When I run this I get this exception:
TypeError: Can't call method on undefined
at TypeError (native)
at Object.assertDefined (base/karma.webpack.js?96b09f906331a23ec15db3852c234ce0c662749c:20029:64)
at assign (base/karma.webpack.js?96b09f906331a23ec15db3852c234ce0c662749c:20101:21)
at Object.<anonymous> (base/karma.webpack.js?96b09f906331a23ec15db3852c234ce0c662749c:40659:23)
at Object.<anonymous> (base/karma.webpack.js?96b09f906331a23ec15db3852c234ce0c662749c:40667:31)
at __webpack_require__ (base/karma.webpack.js?96b09f906331a23ec15db3852c234ce0c662749c:20:30)
at Object.<anonymous> (base/karma.webpack.js?96b09f906331a23ec15db3852c234ce0c662749c:40427:16)
at __webpack_require__ (base/karma.webpack.js?96b09f906331a23ec15db3852c234ce0c662749c:20:30)
at Object.<anonymous> (base/karma.webpack.js?96b09f906331a23ec15db3852c234ce0c662749c:21705:28)
at __webpack_require__ (base/karma.webpack.js?96b09f906331a23ec15db3852c234ce0c662749c:20:30)
The error references karma.webpack
but I've got a hunch that it's still a babel-plugin-rewire-issue, because when I strip out CdnImageComponent
from ImageComponent
the error goes away. I'm guessing that it does not properly rewire ImageComponent
. Am i right?
I had raised this issue originally here prometheusresearch-archive/webtest#7
But, I found that the test work fine if I don't use babel-rewire
Basically, just trying to spy on a dependent function like
/** @module dependency */
'use strict';
/** Does some stuff. */
export function baz(qux) {
return qux.toLowerCase();
}
/** Does other stuff. */
export function foo(bar) {
return bar.toUpperCase();
}
/** @module main */
'use strict';
import {foo} from './dependency';
/** Executes the module. */
export function run() {
foo('bar');
}
/* global beforeEach, describe, expect, it, spyOn */
'use strict';
var dependency = require('../dependency');
import {run} from '../main';
describe('Main', function() {
beforeEach(function() {
spyOn(dependency, 'foo');
});
it('calls dependency\'s foo:', function() {
run();
expect(dependency.foo).toHaveBeenCalledWith('bar');
});
});
webpack conf
loaders: [
{
test: /\.js$/,
// loaders: ['babel?optional[]=runtime&stage=0&plugins=rewire'],
loaders: ['babel?optional[]=runtime&stage=0'],
exclude: /node_modules/
}
]
},
the test fails if rewire
enabled in the above config.
The transform injects new code in many places which changes the line numbers of the original file making it hard to debug. If we could inject all of the necessary code at the end of the file it would be much easier to handle.
The build is currently broken:
Error: Cannot find module './src/ExportsNumberPrimitiveViaCommonJs.js'
...
babel-plugin-rewire/samples/issue28/sample.js:138:28
This modified code from the README.md does not work. Only the import of Path has changed.
//var Path = require('path');
import Path from 'path';
var env = 'production';
module.exports = function(name) {
return Path.normalise(name);
}
var Normaliser = require('Normaliser');
Normaliser.__Rewire__('Path', {
normalise: (name) => name;
});
Normaliser.__Rewire__('env', 'testing');
....
Normaliser.__ResetDependency__('Path');
Is this a known limitation?
When exporting undefined variables, stand-alone babel <filename>.js
transpiles the following just fine
export var status;
is translated to
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var status;
exports.status = status;
running the same snippet together with babel --plugins rewire <filename>.js
leads to an error message
TypeError: <filename.js>: Cannot read property 'declarations' of undefined
at ..../babel-plugin-rewire.js:210:49
....
Just to give some context why somebody would export a undefined variable (it's actually not my choice). We work on a Typescript project and Typescript offers the possibility for defining enums like
export enum Status = { LOADING, SUCCESS, FAILURE }
this get's compiled from the typescript compiler into
export var Status;
(function (Status) {
Status[Status["LOADING"] = 0] = "LOADING";
Status[Status["SUCCESS"] = 1] = "SUCCESS";
Status[Status["FAILURE"] = 2] = "FAILURE";
})(Status || (Status = {}));
;
trying to run that code through babel with rewire plugins leads to the error described above.
Hi
I'm trying to run tests using karma and the latest version of babel-loader 5.3.2 fails with the following error.
Cannot modify non-writable property '__get__'
This issue does not occur with babel-loader 5.3.0
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.