Skip to content
Browse files

adds global overrides

- adding tests for new feature
- removing compat mode and showing upgrade nag when used and revs version number
- only run the build on node versions supported by travis
  • Loading branch information...
1 parent a54fbfe commit a627b297aaa74cc950d4ac24651ce4128ad850e0 @achingbrain achingbrain committed with Thorsten Lorenz Apr 8, 2014
View
4 .gitignore
@@ -19,4 +19,6 @@ npm-debug.log
spikes
*.idea
-*.iml
+*.iml
+.DS_Store
+coverage
View
7 .travis.yml
@@ -1,6 +1,5 @@
language: node_js
node_js:
- - 0.6
- - 0.7
- - 0.8
- - 0.9
+ - "0.6"
+ - "0.8"
+ - "0.10"
View
127 README.md
@@ -10,7 +10,7 @@ v2](https://github.com/substack/browserify).
# Features
-- **no changes to your code** are necessary
+- **no changes to your code** are necessary
- non overriden methods of a module behave like the original
- mocking framework agnostic, if it can stub a function then it works with proxyquire
- "use strict" compliant
@@ -22,11 +22,11 @@ v2](https://github.com/substack/browserify).
```javascript
var path = require('path');
-module.exports.extnameAllCaps = function (file) {
+module.exports.extnameAllCaps = function (file) {
return path.extname(file).toUpperCase();
};
-module.exports.basenameAllCaps = function (file) {
+module.exports.basenameAllCaps = function (file) {
return path.basename(file).toUpperCase();
};
```
@@ -78,7 +78,7 @@ Two simple steps to override require in your tests:
- **request**: path to the module to be tested e.g., `../lib/foo`
- **stubs**: key/value pairs of the form `{ modulePath: stub, ... }`
- - module paths are relative to the tested module **not** the test file
+ - module paths are relative to the tested module **not** the test file
- therefore specify it exactly as in the require statement inside the tested file
- values themselves are key/value pairs of functions/properties and the appropriate override
@@ -130,13 +130,108 @@ var foo = proxyquire
'./bar' : { toAtm: function (val) { ... } }
// for 'path' module they will be made
- , path: {
- extname: function (file) { ... }
+ , path: {
+ extname: function (file) { ... }
, '@noCallThru': false
}
});
```
+### Globally override require
+
+Use the `@global` property to override every `require` of a module, even transitively.
+
+```javascript
+// foo.js
+var bar = require('bar');
+
+module.exports = function() {
+ bar();
+}
+
+// bar.js
+var baz = require('baz');
+
+module.exports = function() {
+ baz.method();
+}
+
+// baz.js
+module.exports = {
+ method: function() {
+ console.info('hello');
+ }
+}
+
+// test.js
+var stubs = {
+ 'baz': {
+ method: function(val) {
+ console.info('goodbye');
+ },
+ '@global': true
+ }
+};
+
+var proxyquire = require('proxyquire');
+
+var foo = proxyquire('foo', stubs);
+foo(); // 'goodbye' is printed to stdout
+```
+
+There is one important caveat with global overrides:
+
+*Any module setup code will be re-executed.*
+
+This is because node.js caches the return value of `require`
+
+Say you have a module, C, that you wish to stub. You require module A which contains `require('B')`. Module B in turn contains `require('C')`. If module B has already been required elsewhere then when module A receives the cached version of module B and proxyquire has no opportunity to inject the stub for C.
+
+Proxyquire works around this problem by ignoring the module cache when any module stubs are specified as `@global`.
+
+This can cause unexpected behaviour. If module B looked like this:
+
+```javascript
+var fs = require('fs')
+ , C = require('C');
+
+// will get executed twice
+var file = fs.openSync('/tmp/foo.txt', 'w');
+
+module.exports = function() {
+ return new C(file);
+};
+```
+
+The file at `/tmp/foo.txt` could be created and/or truncated more than once.
+
+### Globally overriding require at runtime
+
+Say you have a module that looks like this:
+
+```javascript
+module.exports = function() {
+ var d = require('d');
+ d.method();
+};
+```
+The invocation of `require('d')` will happen at runtime and not when the containing module is requested via `require`. If you want to globally override `d` above, use the `@runtimeGlobal` property:
+
+```javascript
+var stubs = {
+ 'd': {
+ method: function(val) {
+ console.info('hello world');
+ },
+ '@runtimeGlobal': true
+ }
+};
+```
+
+This will cause module setup code to be re-excuted just like `@global`, but with the difference that it will happen every time the module is requested via `require` at runtime as no module will ever be cached.
+
+This can cause subtle bugs so if you can guarantee that your modules will not vary their `require` behaviour at runtime, use `@global` instead.
+
### All together, now
```javascript
@@ -154,7 +249,7 @@ var foo2 = proxyquire('./foo', stubs);
### Forcing proxyquire to reload modules
In most situations it is fine to have proxyquire behave exactly like nodejs `require`, i.e. modules that are loaded once
-get pulled from the cache the next time.
+get pulled from the cache the next time.
For some tests however you need to ensure that the module gets loaded fresh everytime, i.e. if that causes initializing
some dependency or some module state.
@@ -238,25 +333,20 @@ barStub.toAtm = function (val) { return -1 * val; /* or now */ };
// Resolve foo and override multiple of its dependencies in one step - oh my!
var foo = proxyquire('./foo', {
- './bar' : {
- toAtm: function (val) { return 0; /* wonder what happens now */ }
+ './bar' : {
+ toAtm: function (val) { return 0; /* wonder what happens now */ }
}
- , path : {
- extname: function (file) { return 'exterminate the name of ' + file; }
+ , path : {
+ extname: function (file) { return 'exterminate the name of ' + file; }
}
});
```
# Backwards Compatibility for proxyquire v0.3.x
-To upgrade your project from v0.3.x to v0.4.x, a nifty compat function has been included.
-
-Simply do a global find and replace for `require('proxyquire')` and change them to `require('proxyquire').compat()`.
+Compatibility mode with proxyquire v0.3.x has been removed.
-This returns an object that wraps the result of `proxyquire()` that provides exactly the same API as v0.3.x.
-
-If your test scripts relied on the fact that v0.3.x stored `noCallThru` in the module scope, you can use
-`require('proxyquire').compat(true)` to use a global compat object, instead.
+You should update your code to use the newer API but if you can't, pin the version of proxyquire in your package.json file to ~0.6 in order to continue using the older style.
# More Examples
@@ -267,4 +357,3 @@ look through the [tests](https://github.com/thlorenz/proxyquire/blob/master/test
- test async APIs synchronously: [examples/async](https://github.com/thlorenz/proxyquire/tree/master/examples/async).
- using proxyquire with [Sinon.JS](http://sinonjs.org/): [examples/sinon](https://github.com/thlorenz/proxyquire/tree/master/examples/sinon).
-
View
7 index.js
@@ -1,10 +1,11 @@
'use strict';
-var Proxyquire = require('./lib/proxyquire')
- , compat = require('./lib/compat');
+var Proxyquire = require('./lib/proxyquire');
// delete this module from the cache to force re-require in order to allow resolving test module via parent.module
delete require.cache[require.resolve(__filename)];
module.exports = new Proxyquire(module.parent);
-module.exports.compat = function (useGlobal) { return compat(module.parent, useGlobal); };
+module.exports.compat = function() {
+ throw new Error("Proxyquire compat mode has been removed. Please update your code to use the new API or pin the version in your package.json file to ~0.6");
+};
View
86 lib/compat.js
@@ -1,86 +0,0 @@
-'use strict';
-
-var Proxyquire = require('./proxyquire')
- , ProxyquireError = require('./proxyquire-error')
- , is = require('./is');
-
-//
-// Compatibility Support 0.3.x
-//
-
-function validateArgments(mdl, test__dirname, stubs) {
- if (!mdl)
- throw new ProxyquireError(
- 'Missing argument: "mdl". Need it know to which module to require.'
- );
-
- if (!test__dirname)
- throw new ProxyquireError(
- 'Missing argument: "__dirname" of test file. Need it to resolve module relative to test directory.'
- );
-
- if (!stubs)
- throw new ProxyquireError(
- 'Missing argument: "stubs". If no stubbing is needed for [' + mdl + '], use regular require instead.'
- );
-
- if (!is.String(mdl))
- throw new ProxyquireError(
- 'Invalid argument: "mdl". Needs to be a string that contains path to module to be resolved.'
- );
-
- if (!is.String(test__dirname))
- throw new ProxyquireError(
- 'Invalid argument: "__dirname" of test file. Needs to be a string that contains path to test file resolving the module.'
- );
-
- if (!is.Object(stubs))
- throw new ProxyquireError(
- 'Invalid argument: "stubs". Needs to be an object containing overrides e.g., {"path": { extname: function () { ... } } }.'
- );
-}
-
-function CompatProxyquire() {}
-
-CompatProxyquire.prototype = Object.create(Proxyquire.prototype);
-CompatProxyquire.prototype.constructor = CompatProxyquire;
-
-CompatProxyquire.prototype._parent = null;
-
-CompatProxyquire.prototype.load = function(mdl, parent, stubs) {
- this._parent = parent;
-
- try {
- return Proxyquire.prototype.load.call(this, mdl, stubs);
- } finally {
- this._parent = null;
- }
-};
-
-var globalCompatProxyquire = globalCompatProxyquire || new CompatProxyquire();
-
-function compat(parent, useGlobal) {
- var pq = useGlobal ? globalCompatProxyquire : new CompatProxyquire();
-
- var compat_ = function (mdl, test__dirname, stubs) {
- validateArgments.apply(null, arguments);
- return pq.load(mdl, parent, stubs);
- };
-
- compat_.resolve = compat_;
-
- compat_.tmpDir = function () {};
-
- compat_.noCallThru = function (flag) {
- if (flag !== false)
- pq.noCallThru();
- else
- pq.callThru();
-
- return compat_;
- };
-
- return compat_;
-}
-
-module.exports = compat;
View
152 lib/proxyquire.js
@@ -5,6 +5,7 @@ var path = require('path')
, Module = require('module')
, ProxyquireError = require('./proxyquire-error')
, is = require('./is')
+ , assert = require('assert')
;
function fillMissingKeys(mdl, original) {
@@ -114,60 +115,131 @@ Proxyquire.prototype.preserveCache = function() {
Proxyquire.prototype.load = function (request, stubs) {
validateArguments(request, stubs);
- // Find the ID (location) of the SUT, relative to the parent
- var id = Module._resolveFilename(request, this._parent);
-
- // Temporarily delete the SUT from the require cache, if it exists.
- var cached = Module._cache[id];
- if (cached) delete Module._cache[id];
+ // Find out if any of the passed stubs are global overrides
+ for (var key in stubs) {
+ if (stubs[key].hasOwnProperty('@global')) {
+ this._containsGlobal = true;
+ }
- // Override the core require function for the SUT's file extension.
- var extname = path.extname(id);
- var ext_super = require.extensions[extname];
+ if (stubs[key].hasOwnProperty('@runtimeGlobal')) {
+ this._containsGlobal = true;
+ this._containsRuntimeGlobal = true;
+ }
+ }
- var self = this;
- require.extensions[extname] = function ext(module, filename) {
- // NOTE: This function is for requiring the SUT
+ // Ignore the module cache when return the requested module
+ return this._withoutCache(this._parent, stubs, request, this._parent.require.bind(this._parent, request));
+};
- // require_super is the normal require for the SUT.
- var require_super = module.require.bind(module);
- require_super.extensions = require.extensions;
- require_super.extensions[extname] = ext_super;
- require_super.main = process.mainModule;
+// This replaces a module's require function
+Proxyquire.prototype._require = function(module, stubs, path) {
+ assert(typeof path === 'string', 'path must be a string');
+ assert(path, 'missing path');
- module.require = function (request) {
- // NOTE: This function is for requiring dependencies for the SUT
+ if (stubs.hasOwnProperty(path)) {
+ var stub = stubs[path];
- // If the request string isn't stubbed, just do the usual thing.
- if (!stubs.hasOwnProperty(request)) return require_super(request);
+ if (stub.hasOwnProperty('@noCallThru') ? !stub['@noCallThru'] : !this._noCallThru) {
+ fillMissingKeys(stub, Module._load(path, module));
+ }
- var stub = stubs[request];
+ // We are top level or this stub is marked as global
+ if (module.parent == this._parent || stub.hasOwnProperty('@global') || stub.hasOwnProperty('@runtimeGlobal')) {
+ return stub;
+ }
+ }
- if (stub.hasOwnProperty('@noCallThru') ? !stub['@noCallThru'] : !self._noCallThru)
- fillMissingKeys(stub, require_super(request));
+ // Only ignore the cache if we have global stubs
+ if (this._containsRuntimeGlobal) {
+ return this._withoutCache(module, stubs, path, Module._load.bind(Module, path, module));
+ } else {
+ return Module._load(path, module);
+ }
+};
- return stub;
- };
+Proxyquire.prototype._withoutCache = function(module, stubs, path, func) {
+ // Temporarily disable the cache - either per-module or globally if we have global stubs
+ var restoreCache = this._disableCache(module, path);
- // Now that we've overridden the SUT's require, we can proceed as usual.
- return ext_super(module, filename);
- };
+ // Override all require extension handlers
+ var restoreExtensionHandlers = this._overrideExtensionHandlers(module, stubs);
try {
- return this._parent.require(request);
+ // Execute the function that needs the module cache disabled
+ return func();
} finally {
- if (self._preserveCache && cached) {
- if (cached)
- Module._cache[id] = cached;
- else
- delete Module._cache[id];
-
- if (ext_super)
- require.extensions[extname] = ext_super;
+ // Restore the cache if we are preserving it
+ if (this._preserveCache) {
+ restoreCache();
}
- else
- delete require.cache[id];
+
+ // Finally restore the original extension handlers
+ restoreExtensionHandlers();
}
};
+Proxyquire.prototype._disableCache = function(module, path) {
+ if (this._containsGlobal) {
+ // empty the require cache because if we are stubbing C but requiring A,
+ // and if A requires B and B requires C, then B and C might be cached already
+ // and we'll never get the chance to return our stub
+ return this._disableGlobalCache();
+ }
+
+ // Temporarily delete the SUT from the require cache
+ return this._disableModuleCache(path, module);
+};
+
+Proxyquire.prototype._disableGlobalCache = function() {
+ var cache = require.cache;
+ require.cache = Module._cache = {};
+
+ // Return a function that will undo what we just did
+ return function() {
+ require.cache = Module._cache = cache;
+ };
+};
+
+Proxyquire.prototype._disableModuleCache = function(path, module) {
+ // Find the ID (location) of the SUT, relative to the parent
+ var id = Module._resolveFilename(path, module);
+
+ var cached = Module._cache[id];
+ delete Module._cache[id];
+
+ // Return a function that will undo what we just did
+ return function() {
+ if (cached) {
+ Module._cache[id] = cached;
+ }
+ };
+};
+
+Proxyquire.prototype._overrideExtensionHandlers = function(module, stubs) {
+ var originalExtensions = {};
+ var self = this;
+
+ Object.keys(require.extensions).forEach(function(extension) {
+ // Store the original so we can restore it later
+ if (!originalExtensions[extension]) {
+ originalExtensions[extension] = require.extensions[extension];
+ }
+
+ // Override the default handler for the requested file extension
+ require.extensions[extension] = function(module, filename) {
+ // Override the require method for this module
+ module.require = self._require.bind(self, module, stubs);
+
+ return originalExtensions[extension](module, filename);
+ };
+ });
+
+ // Return a function that will undo what we just did
+ return function() {
+ Object.keys(originalExtensions).forEach(function(extension) {
+ require.extensions[extension] = originalExtensions[extension];
+ });
+ };
+};
+
module.exports = Proxyquire;
View
8 package.json
@@ -1,6 +1,6 @@
{
"name": "proxyquire",
- "version": "0.6.0",
+ "version": "1.0.0",
"description": "Proxies nodejs require in order to allow overriding dependencies during testing.",
"main": "index.js",
"scripts": {
@@ -29,8 +29,8 @@
}
],
"devDependencies": {
- "mocha": "1.3.x",
- "should": "0.6.x",
- "sinon": "~1.4.2"
+ "mocha": "~1.18",
+ "should": "~3.3",
+ "sinon": "~1.9"
}
}
View
29 test/compat/compat-globals.js
@@ -1,29 +0,0 @@
-/*jshint asi:true*/
-/*global describe before beforeEach it */
-"use strict";
-
-var assert = require('assert');
-
-var file = '/folder/test.ext';
-
-describe('When using global compat', function () {
- it('should persist noCallThru between requires', function () {
- var g1 = require('../..').compat(true).noCallThru();
- var g2 = require('../..').compat(true);
-
- var foo = g2('./samples/foo', __dirname, { path:{} });
- assert.throws(foo.bigBas);
- })
-
- it('does not persist noCallThru to non-global compats', function () {
- var g1 = require('../..').compat(true).noCallThru();
- var g2 = require('../..').compat();
-
- var foo = g2('./samples/foo', __dirname, {
- path: {
- extname:function (file) { return 'override ' + file; }
- }
- });
- assert.equal(foo.bigBas(file), 'TEST.EXT');
- })
-})
View
12 test/compat/proxyquire-api.js
@@ -1,12 +0,0 @@
-/*jshint asi:true*/
-/*global describe before beforeEach it */
-'use strict';
-
-var assert = require('assert')
- , proxyquire = require('../..').compat();
-
-describe('api', function () {
- it('proxyquire function is the same as proxyquire.resolve function', function () {
- assert.equal(proxyquire, proxyquire.resolve)
- })
-})
View
83 test/compat/proxyquire-argumentvalidation.js
@@ -1,83 +0,0 @@
-/*jshint asi:true*/
-/*global describe before beforeEach it */
-"use strict";
-
-var assert = require('assert')
- , proxyquire = require('../..').compat()
- ;
-
-describe('Illegal parameters to resolve give meaningful errors', function () {
- var bar = { bar: function () { return 'bar'; } }
- , exception
- ;
-
- function throws(action, regex) {
- assert.throws(action, function (err) {
- return err.name === 'ProxyquireError' && regex.test(err.message);
- });
- }
-
- describe('when I pass no module', function () {
- function act () {
- proxyquire(undefined, __dirname);
- }
-
- it('throws an exception explaining that module needs to be passed', function () {
- throws(act, /missing argument: "mdl"/i);
- })
-
- })
-
- describe('when I pass an object as module', function () {
-
- function act () {
- proxyquire({ }, __dirname, { './bar': bar });
- }
-
- it('throws an exception explaining that module needs to be a string', function () {
- throws(act, /invalid argument: "mdl".+needs to be a string/i);
- })
- })
-
- describe('when I pass no test__dirname', function () {
- function act () {
- proxyquire('module');
- }
-
- it('throws an exception explaining that resolve without stubs makes no sense', function () {
- throws(act, /missing argument: "__dirname" of test file/i);
- })
- })
-
- describe('when I pass an object as test__dirname', function () {
-
- function act () {
- proxyquire('./samples/foo', { }, { './bar': bar });
- }
-
- it('throws an exception explaining that test__dirname needs to be a string', function () {
- throws(act, /invalid argument: "__dirname" of test file.+needs to be a string/i);
- })
- })
-
- describe('when I pass no stubs', function () {
- function act () {
- proxyquire('./samples/foo', __dirname);
- }
-
- it('throws an exception explaining that resolve without stubs makes no sense', function () {
- throws(act, /missing argument: "stubs".+use regular require instead/i);
- })
-
- })
-
- describe('when I pass a string as stubs', function () {
- function act () {
- proxyquire('./samples/foo', __dirname, 'stubs');
- }
-
- it('throws an exception explaining that stubs need to be an object', function () {
- throws(act, /invalid argument: "stubs".+needs to be an object/i);
- })
- })
-})
View
45 test/compat/proxyquire-independence.js
@@ -1,45 +0,0 @@
-/*jshint asi:true*/
-/*global describe before beforeEach it */
-"use strict";
-
-var assert = require('assert')
- , proxyquire = require('../..').compat()
- ;
-
-describe('Multiple requires of same module don\'t affect each other', function () {
- describe('Given I require foo stubbed with bar1 as foo1 and foo stubbed with bar2 as foo2', function () {
- var foo1
- , foo2
- , bar1 = { bar: function () { return 'bar1'; } }
- , bar2 = { bar: function () { return 'bar2'; } }
- ;
-
- before(function () {
- foo1 = proxyquire('./samples/foo', __dirname, { './bar': bar1 });
- foo2 = proxyquire('./samples/foo', __dirname, { './bar': bar2 });
- })
-
- it('foo1.bigBar() == "BAR1"', function () {
- assert.equal(foo1.bigBar(), 'BAR1');
- })
-
- it('foo2.bigBar() == "BAR2"', function () {
- assert.equal(foo2.bigBar(), 'BAR2');
- })
-
- describe('and I change bar1.bar() to return barone', function () {
- before(function () {
- bar1.bar = function () { return 'barone'; };
- })
-
- it('foo1.bigBar() == "BARONE"', function () {
- assert.equal(foo1.bigBar(), 'BARONE');
- })
-
- it('foo2.bigBar() == "BAR2"', function () {
- assert.equal(foo2.bigBar(), 'BAR2');
- })
-
- })
- })
-})
View
30 test/compat/proxyquire-notexisting.js
@@ -1,30 +0,0 @@
-'use strict';
-/*jshint asi:true*/
-/*global describe before beforeEach it */
-
-var assert = require('assert')
- , proxyquire = require('../..').compat()
- , path = require('path')
- , fooPath = path.join(__dirname, './samples/notexisting/foo.js')
-
-describe('When resolving foo that requires stubbed /not/existing/bar.json', function () {
-
- it('throws an error', function () {
- assert.throws(function () {
- proxyquire(fooPath, __dirname, {
- '/not/existing/bar.json': { config: 'bar\'s config' }
- })
- })
- })
-})
-
-describe('When resolving foo that requires stubbed /not/existing/bar.json with noCallThru', function () {
- var foo;
-
- it('resolves foo with stubbed bar', function () {
- foo = proxyquire(fooPath, __dirname, {
- '/not/existing/bar.json': { config: 'bar\'s config', '@noCallThru': true }
- })
- assert.equal(foo.config, 'bar\'s config')
- })
-})
View
193 test/compat/proxyquire.js
@@ -1,193 +0,0 @@
-/*jshint asi:true*/
-/*global describe before beforeEach it */
-"use strict";
-
-var assert = require('assert')
- , proxyquire = require('../..').compat()
- , stats = require('./samples/stats')
- ;
-
-describe('Given foo requires the bar and path modules and bar.bar() returns "bar"', function () {
- var file = '/folder/test.ext'
- , foo
- , foober
- , barber = { bar: function () { return 'barber'; } }
- ;
-
- describe('When I resolve foo with no overrides to bar as foo and resolve foo with barber stub as foober.', function () {
- before(function () {
- stats.reset();
- foo = proxyquire('./samples/foo', __dirname, { './bar': { /* no overrides */ } });
- foober = proxyquire('./samples/foo', __dirname, { './bar': barber });
- })
-
- it('foo is required 2 times', function () {
- assert.equal(stats.fooRequires(), 2);
- })
-
- describe('foo\'s bar is unchanged', function () {
- it('foo.bigBar() == "BAR"', function () {
- assert.equal(foo.bigBar(), 'BAR');
- })
- })
-
- describe('only stubbed modules have overrides in foober', function () {
-
- it('foober.bigBar() == "BARBER"', function () {
- assert.equal(foober.bigBar(), 'BARBER');
- })
-
- it('foober.bigExt("/folder/test.ext") == ".EXT"', function () {
- assert.equal(foober.bigExt(file), '.EXT');
- })
-
- it('foober.bigBas("/folder/test.ext") == "TEST.EXT"', function () {
- assert.equal(foober.bigBas(file), 'TEST.EXT');
- })
-
- })
-
- describe('when I override keys of stubs after resolve', function () {
-
- before(function () {
- barber.bar = function () { return 'friseur'; }
- barber.rab = function () { return 'rabarber'; }
- });
-
- it('overrides behavior when module is required inside function call', function () {
- assert.equal(foober.bigBar(), 'FRISEUR');
- })
-
- it('overrides behavior when module is required on top of file', function () {
- assert.equal(foober.bigRab(), 'RABARBER');
- })
-
-
- describe('and then delete overrides of stubs after resolve', function () {
-
- beforeEach(function () {
- barber.bar = undefined;
- barber.rab = undefined;
- })
-
- it('reverts to original behavior when module is required inside function call', function () {
- assert.equal(foober.bigBar(), 'BAR');
- })
-
- it('doesn\'t properly revert to original behavior when module is required on top of file ', function () {
- assert.throws(foober.bigRab);
- })
-
- })
- })
- })
-
- describe('When foo.bigExt() returns capitalized path.extname and foo.bigBas() returns capitalized path.basename', function () {
- describe('and path.extname(file) is stubbed to return "override " + file', function () {
-
- describe('and callThru was not changed globally or for path module', function () {
- before(function () {
- foo = proxyquire('./samples/foo', __dirname, {
- path: {
- extname: function (file) { return 'override ' + file; }
- }
- });
- })
-
- it('foo.bigExt(file) == "OVERRIDE /FOLDER/TEST.EXT"', function () {
- assert.equal(foo.bigExt(file), 'OVERRIDE /FOLDER/TEST.EXT');
- })
-
- it('foo.bigBas(file) == "TEST.EXT"', function () {
- assert.equal(foo.bigBas(file), 'TEST.EXT');
- })
- })
-
- describe('and callThru is turned off for path module', function () {
- before(function () {
- foo = proxyquire('./samples/foo', __dirname, {
- path: {
- extname: function (file) { return 'override ' + file; }
- , '@noCallThru': true
- }
- });
- })
-
- it('foo.bigExt(file) == "OVERRIDE /FOLDER/TEST.EXT"', function () {
- assert.equal(foo.bigExt(file), 'OVERRIDE /FOLDER/TEST.EXT');
- })
-
- it('foo.bigBas(file) throws', function () {
- assert.throws(foo.bigBas);
- })
-
- })
-
- describe('and callThru was turned off globally', function () {
- before(function () {
- proxyquire.noCallThru();
- })
-
- describe('and not changed for path module', function () {
- before(function () {
- foo = proxyquire('./samples/foo', __dirname, {
- path: {
- extname: function (file) { return 'override ' + file; }
- }
- });
- })
-
- it('foo.bigExt(file) == "OVERRIDE /FOLDER/TEST.EXT"', function () {
- assert.equal(foo.bigExt(file), 'OVERRIDE /FOLDER/TEST.EXT');
- })
-
- it('foo.bigBas(file) throws', function () {
- assert.throws(foo.bigBas);
- })
- })
-
- describe('and turned back on for path module', function () {
- before(function () {
- foo = proxyquire('./samples/foo', __dirname, {
- path: {
- extname: function (file) { return 'override ' + file; }
- , '@noCallThru': false
- }
- });
- })
-
- it('foo.bigExt(file) == "OVERRIDE /FOLDER/TEST.EXT"', function () {
- assert.equal(foo.bigExt(file), 'OVERRIDE /FOLDER/TEST.EXT');
- })
-
- it('foo.bigBas(file) == "TEST.EXT"', function () {
- assert.equal(foo.bigBas(file), 'TEST.EXT');
- })
- })
-
- describe('and turned back on globally', function () {
- before(function () {
- foo = proxyquire
- .noCallThru(false)
- .resolve('./samples/foo', __dirname, {
- path: {
- extname: function (file) { return 'override ' + file; }
- }
- });
- })
-
- it('foo.bigExt(file) == "OVERRIDE /FOLDER/TEST.EXT"', function () {
- assert.equal(foo.bigExt(file), 'OVERRIDE /FOLDER/TEST.EXT');
- })
-
- it('foo.bigBas(file) == "TEST.EXT"', function () {
- assert.equal(foo.bigBas(file), 'TEST.EXT');
- })
- })
- })
- })
- })
-})
-
-
-
View
10 test/compat/samples/bar.js
@@ -1,10 +0,0 @@
-function bar () {
- return 'bar';
-}
-
-function rab () {
- return 'rab';
-}
-
-module.exports = { bar : bar, rab: rab };
-
View
31 test/compat/samples/foo.js
@@ -1,31 +0,0 @@
-var stats = require('./stats')
- , bar = require('./bar')
- , path = require('path')
- ;
-
-stats.incFooRequires();
-
-function bigBar () {
- // inline require
- return require('./bar').bar().toUpperCase();
-}
-
-function bigRab () {
- // module wide require
- return bar.rab().toUpperCase();
-}
-
-function bigExt (file) {
- return path.extname(file).toUpperCase();
-}
-
-function bigBas (file) {
- return path.basename(file).toUpperCase();
-}
-
-module.exports = {
- bigBar: bigBar
- , bigRab: bigRab
- , bigExt: bigExt
- , bigBas: bigBas
-};
View
5 test/compat/samples/notexisting/foo.js
@@ -1,5 +0,0 @@
-var bar = require('/not/existing/bar.json');
-
-module.exports = {
- config: bar.config
-};
View
6 test/compat/samples/stats.js
@@ -1,6 +0,0 @@
-var fooRequires = 0;
-module.exports = {
- fooRequires: function () { return fooRequires; }
- , incFooRequires: function () { fooRequires++; }
- , reset: function () { fooRequires = 0; }
-};
View
6 test/compat/samples/windowspaths.js
@@ -1,6 +0,0 @@
-module.exports.__dirname = __dirname;
-module.exports.__filename = __filename;
-module.exports.testRequire = function() {
- var bar = require('./bar');
- return bar.bar();
-};
View
3 test/mocha.opts
@@ -2,5 +2,4 @@
--reporter spec
--ui bdd
--growl
-test
-test/compat
+test
View
12 test/proxyquire-compat.js
@@ -0,0 +1,12 @@
+'use strict';
+/*jshint asi:true */
+/*global describe, before, beforeEach, it */
+
+var proxyquire = require('..');
+
+describe('when I try to use compat mode', function () {
+
+ it('should let me know that I need to fix my code or downgrade', function () {
+ proxyquire.compat.should.throw(/compat mode has been removed/);
+ });
+});
View
42 test/proxyquire-global.js
@@ -0,0 +1,42 @@
+/*jshint asi:true*/
+/*global describe, before, beforeEach, it */
+'use strict';
+
+var assert = require('assert')
+ , realFoo = require('./samples/global/foo');
+
+var proxyquire = require('..');
+
+describe('global', function () {
+ it('should override require globally', function () {
+ var stubs = {
+ './baz': {
+ method: function() {
+ return true;
+ },
+ '@global': true
+ }
+ };
+
+ var proxiedFoo = proxyquire('./samples/global/foo', stubs);
+
+ assert.equal(realFoo(), false);
+ assert.equal(proxiedFoo(), true);
+ });
+
+ it('should override require globally even when require\'s execution is deferred', function () {
+ var stubs = {
+ './baz': {
+ method: function() {
+ return true;
+ },
+ '@runtimeGlobal': true
+ }
+ };
+
+ var proxiedFoo = proxyquire('./samples/global/foo-deferred', stubs);
+
+ assert.equal(realFoo(), false);
+ assert.equal(proxiedFoo(), true);
+ });
+});
View
5 test/samples/global/bar.js
@@ -0,0 +1,5 @@
+var baz = require('./baz');
+
+module.exports = function() {
+ return baz.method();
+}
View
5 test/samples/global/baz.js
@@ -0,0 +1,5 @@
+module.exports = {
+ method: function() {
+ return false;
+ }
+}
View
6 test/samples/global/foo-deferred.js
@@ -0,0 +1,6 @@
+
+module.exports = function() {
+ var bar = require('./bar');
+
+ return bar();
+}
View
5 test/samples/global/foo.js
@@ -0,0 +1,5 @@
+var bar = require('./bar');
+
+module.exports = function() {
+ return bar();
+}

0 comments on commit a627b29

Please sign in to comment.
Something went wrong with that request. Please try again.