GithubHelp home page GithubHelp logo

i-like-robots / rewireify Goto Github PK

View Code? Open in Web Editor NEW
60.0 5.0 11.0 37 KB

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.

Home Page: https://www.npmjs.com/package/rewireify

License: Other

JavaScript 100.00%

rewireify's Introduction

⚠️ This module is no longer maintained ⚠️

Rewireify Build status

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. With Rewireify you can:

  • Inject mocks for other modules
  • Leak private variables
  • Override variables within the module

Rewireify is compatible with Browserify 3+

Usage

First install and save Rewireify into your project's development dependencies:

$ npm install rewireify --save-dev

Include the Rewireify transform as part of your test bundle:

$ browserify -e app.js -o test-bundle.js -t rewireify -s test-bundle

Rewireify can also ignore certain files with the --ignore option and a filename or glob expression. Multiple files or patterns can be excluded by separating them with commas:

$ browserify -e app.js -o test-bundle.js -t [ rewireify --ignore filename.js,**/*-mixin.js ] -s test-bundle

Now you can inspect, modify and override your modules internals in your tests. The __get__ and __set__ methods are the same as Rewire:

var bundle = require("./path/to/test-bundle");

// Private variables can be leaked...
subject.__get__("secretKey");

// ...or modified
subject.__set__("secretKey", 1234);

// Nested properties can be inspected or modified
subject.__set__("user.firstname", "Joe");

// Dependencies can be mocked...
subject.__set__("config", {
  cache: false,
  https: false
});

// ...or methods stubbed
subject.__set__("http.get", function(url, cb) {
  cb("This method has been stubbed");
});

// And everything can be reverted
var revert = subject.__set__("port", 3000);

revert();

For more details check out the Rewire documentation.

Usage with ES6

Rewireify will continue to work in ES6 environments but variables declared as constants (using const) may pose some issues. Constants cannot be reassigned and is now common practice to declare dependencies as such and therefore Rewireify will be unable to to replace them. However, variables declared as constants are not immutable so their individual methods and properties can still accessed and modified. If you must replace an entire dependency in your test environment and you have switched to using const then I recommended checking out Proxyquireify.

rewireify's People

Contributors

i-like-robots avatar iamrandys avatar rjmk avatar shebson avatar thesavior avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

rewireify's Issues

Intermittent error attempting to define __get__ more than once on Karma startup.

Error: Invariant Violation: ReactCompositeComponentInterface: You are attempting to define __get__ on your component more than once. This conflict may be due to a mixin.

First off, I do not believe this is a rewireify issue (rewirify has been solid), but from the error message this seems the most logical place for others to look for this issue.

About 1 out of 10 times and only on initial Karma startup, I get the following error and Karma hangs. It is very hard to troubleshoot the issue since it does not happen all the time. I am using:

"karma": "^0.12.21",
"karma-bro": "^0.6.2",
"karma-jasmine": "^0.2.2",
"react": "~0.11.0",
"reactify": "^0.14.0",
"rewireify": "~0.0.9",

Problem ES6 module syntax

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?

the "right" way of testing nested modules

So, I'm using React and React Router. React Router makes it very hard to test because you need a full router initialized and working to use any part of it so I thought rewireify would be perfect. I'm including it in my build like:

function startWatchify () {
  var bundle = new browserify(manifestFilePath, { ... });

  bundle.transform("rewireify");

  watchedBundle = watchify(bundle);

  watchedBundle.on('update', function() {
    bundleAndSave(watchedBundle);
  });

  bundleAndSave(watchedBundle);
};

I then have a Sidebar component which requires a NavItem. NavItem requires var Link = require('react-router').Link;

As it stands, doing this pretty much makes things implode for the reasons I said above. This is documented on their side and they are working on it I guess.

I figured since I don't need to unit test that Link works I can simply stub it out and make require('react-router') just return a stubbed class like

{
  Link: function () {
    // This really doesn't do anything
    return new StubbedOutReactComponent();
  }
}

From the Sidebar tests which requires Sidebar that requires NavItem which requires require('react-router').Link, how do I stub out that require('react-router').Link from the Sidebar tests? or, is that even possible? How would you suggest going about stubbing that out?

Slashes in windows

path.join returns single backslash, if you are interpolating into a string, then they become escape sequence in windows.

I was getting error like : ERROR [framework.browserify]: Error: Cannot find module 'c:WorkReposSample-ProjectBuildScriptsGulp

Use something like https://www.npmjs.org/package/slash to normalize this on all OS.

I added a replace clause as temporary workaround for me.

path.join((__dirname), "__get__").replace(/\\/g, "/")

Error message when calling __set__

I hope this is the right repo.

When I call __set__ on a module, to mock a function it requires from another module, I get the following error message:

PhantomJS 1.9.8 (Windows 7 0.0.0) ERROR
  TypeError: 'undefined' is not a function (evaluating 'function (revertArgs) {
          __set__.apply(null, revertArgs);
      }.bind(null, arguments.revertArgs)')

I've made a minimal reproduction repo here: https://github.com/jhorneman/karma-browserify-repro.

Just run npm install, then npm run test.

I'm using Karma, Jasmine, Browserify, and Rewireify, under Windows 7.

Please let me know if you need more information.

Sharing code between rewireify and rewire-global

I maintain rewire-global, which is very similar to rewireify except for node. Rewireify adds rewire to every module via a browserify transform. rewire-global adds rewire to every module by modifying node's internal require wrapper.

If you look at rewire-global's main file, you'll notice that things are pretty much identical to that of rewireify:
https://github.com/TheSavior/rewire-global/blob/master/index.js

I noticed this commit in rewireify that verifies that an object is extensible. Rewire-global would benefit from that.

I noticed this issue about rewireify not currently injecting the functions when module.exports is a function. Rewire-global currently does that.

It seems like it would be in both of our best interests to figure out how to pull out the necessary wrapping code into a common module and then support it being used via both browserify and node. Thoughts?

Rewireify exposes __get__ and __set__ via Object.keys

Currently with rewireify, __get__ and __set__ are part of the returned array when using Object.keys on a module that returns an object.

For example:

// foo.js

var Foo = {
  key: 'val'
};

module.exports = Foo;
var Foo = require('foo');
assert.sameMembers(Object.keys(Foo), ['key', '__get__', '__set__']); 

However, I don't want my code to see anything about __get__ or __set__, such that my assert would be:

assert.sameMembers(Object.keys(Foo), ['key']); 

I ran into this problem when building a port of rewireify for node, and used Object.defineProperty to fix it:
https://github.com/TheSavior/rewire-global/blob/master/index.js

Does not seem to work with source mapping

Thanks for porting this to browserify.

browserify -t [reactify --es6 --target es5] -t rewireify spec/$FILE -o build/$FILE --debug

Adding the --debug flag with rewireify throws parsing errors. I would love to have source maps also.

Rewire doesn't work when the module is a constructor function

Hi, First of all thanks for this great tool.

I have a constructor function declared in a module defined like this:

function f(){
    var privateFunction=function(){
        //do something
    }

    return {
        a:'some value'
    }
}
module.exports=f

and then I use it:

var obj=new f()

I want to use rewireify to test privateFunction, but the get method is only injected to f, no to its prototype, then I never have it in the created instances.

Will it make sense to have some kind of option indicating that the method should also be injected to the prototype, so the instances created with new also have the access functions?

Incompatibility with browserify-istanbul in karma

I get the following error when I try to use the rewireify and browserify-istanbul browserify transforms through karma:

$ karma start

/Users/Admin/code/bot/node_modules/karma-bro/node_modules/browserify/index.js:230
    opts._flags = '_flags' in opts ? opts._flags : self._options;
                              ^
TypeError: Cannot use 'in' operator to search for '_flags' in browserify-istanbul
  at Browserify.transform (/Users/Admin/code/bot/node_modules/karma-bro/node_modules/browserify/index.js:230:31)
  at /Users/Admin/code/bot/node_modules/karma-bro/lib/bro.js:144:19
  at Function.forEach (/Users/Admin/code/bot/node_modules/karma-bro/node_modules/lodash/dist/lodash.js:3297:15)
  at createBundle (/Users/Admin/code/bot/node_modules/karma-bro/lib/bro.js:138:7)
  at framework (/Users/Admin/code/bot/node_modules/karma-bro/lib/bro.js:93:9)
  at Array.invoke [as 0] (/Users/Admin/code/bot/node_modules/karma/node_modules/di/lib/injector.js:75:15)
  at [object Object].get (/Users/Admin/code/bot/node_modules/karma/node_modules/di/lib/injector.js:48:43)
  at /Users/Admin/code/bot/node_modules/karma/lib/server.js:31:14
  at Array.forEach (native)
  at start (/Users/Admin/code/bot/node_modules/karma/lib/server.js:30:21)
  at [object Object].invoke (/Users/Admin/code/bot/node_modules/karma/node_modules/di/lib/injector.js:75:15)
  at Object.exports.start (/Users/Admin/code/bot/node_modules/karma/lib/server.js:310:12)
  at Object.exports.run (/Users/Admin/code/bot/node_modules/karma/lib/cli.js:224:25)
  at requireCliAndRun (/usr/local/lib/node_modules/karma-cli/bin/karma:24:16)
  at /usr/local/lib/node_modules/karma-cli/bin/karma:56:12
  at /usr/local/lib/node_modules/karma-cli/node_modules/resolve/lib/async.js:44:21
  at /usr/local/lib/node_modules/karma-cli/node_modules/resolve/lib/async.js:119:35
  at /usr/local/lib/node_modules/karma-cli/node_modules/resolve/lib/async.js:91:39
  at /usr/local/lib/node_modules/karma-cli/node_modules/resolve/lib/async.js:60:30
  at /usr/local/lib/node_modules/karma-cli/node_modules/resolve/lib/async.js:20:18
  at Object.oncomplete (fs.js:108:15)

module.__set__(map) errors when using nested properties

Hi!

I'm trying to set a nested property passing a map as a parameter to __set__:

# module.coffee

privateModule = require './privateModule'

module.exports = ()->
  privateModule.func()
# moduleTest.coffee

module = require './module'

module.__set__({"privateModule.func": jasmine.createSpy()})

But it errors with: TypeError: Cannot read property 'func' of undefined

Any thoughts on this? Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.