pax_global_header00006660000000000000000000000064127244231210014510gustar00rootroot0000000000000052 comment=a4803ca6aa4cb99c10630257e3ce3b1656a1c216 require-inject-a4803ca6aa4cb99c10630257e3ce3b1656a1c216/000077500000000000000000000000001272442312100213265ustar00rootroot00000000000000require-inject-a4803ca6aa4cb99c10630257e3ce3b1656a1c216/.gitignore000066400000000000000000000000341272442312100233130ustar00rootroot00000000000000*~ DEADJOE .#* node_modules require-inject-a4803ca6aa4cb99c10630257e3ce3b1656a1c216/CHANGELOG.md000066400000000000000000000026071272442312100231440ustar00rootroot00000000000000## v1.4.0 (2016-06-03) Add `requireInject.withEmptyCache` and `requireInject.installGlobally.andClearCache` to support loading modules to be injected with an empty cache. This can be useful when your test shares dependencies with the module to be mocked and you need to mock a transitive dependency of one of those dependencies. That is: ``` Test → A → B ModuleToTest → A → MockedB ``` If we we didn't clear the cache then `ModuleToTest` would get the already cached version of `A` and the `MockedB` would never be injected. By clearing the cache first it means that `ModuleToTest` will get it's own copy of `A` which will then pick up any mocks we defined. Previously to achieve this you would need to have provided a mock for `A`, which, if that isn't what you were testing, could be frustrating busy work. ## v1.3.1 (2016-03-04) Properly support relative module paths. Previously you could use them, but they would be relative to where `require-inject` was installed. Now they're relative to your test script. (I failed to notice this for so long because, through sheer coicidence, the relative path from my own test scripts was the same as the one from `require-inject`, but that wouldn't ordinarily be the case.) Many, many thanks to [@jcollado](https://github.com/jcollado) who provided the patch, with tests and was kind enough to convince me that this really wasn't working as intended. require-inject-a4803ca6aa4cb99c10630257e3ce3b1656a1c216/LICENSE000066400000000000000000000013171272442312100223350ustar00rootroot00000000000000Copyright (c) 2015, Rebecca Turner Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. require-inject-a4803ca6aa4cb99c10630257e3ce3b1656a1c216/README.md000066400000000000000000000054041272442312100226100ustar00rootroot00000000000000require-inject -------------- A simple mock injector compatible needing no instrumentation in the libraries being tested ### Example var requireInject = require('require-inject'); var mymod = requireInject('mymod', { 'fs' => { stat: function (file,cb) { switch (file) { case 'testfile1': return cb(null,{}) case 'testfile2': return cb(new Error('ENOENT')) } } } }) var myglobal = requireInject.installGlobally('myglobal', { … }) ### Usage in your tests * **`var mymod = requireInject( module, mocks )`** *module* is the name of the module you want to require. This is what you'd pass to `require` to load the module from your script. This means that for relative paths, the path should be relative to your test script, not to the thing you're injecting dependencies into. *mocks* is an object with keys that are the names of the modules you want to mock and values of the mock version of the objects. **requireInject** makes it so that when *module* is required, any of its calls to require for modules inclued in *mocks* will return the mocked version. It takes care to not impact any other uses of *module*, any calls to require for it will get a version without mocks. * **`var mymod = requireInject.withClearCache(module, mocks)`** As with `requireInject` but your require cache will be cleared before requring the module to have mocks injected into it. This can be useful when your test shares dependencies with the module to be mocked and you need to mock a transitive dependency of one of those dependencies. That is: ``` Test → A → B ModuleToTest → A → MockedB ``` If we we didn't clear the cache then `ModuleToTest` would get the already cached version of `A` and the `MockedB` would never be injected. By clearing the cache first it means that `ModuleToTest` will get it's own copy of `A` which will then pick up any mocks we defined. Previously to achieve this you would need to have provided a mock for `A`, which, if that isn't what you were testing, could be frustrating busy work. * **`var myglobal = requireInject.installGlobally( module, mocks)`** As with `requireInject`, except that the module and its mocks are left in the require cache and any future requires will end up using them too. This is helpful particularly in the case of things that defer loading (that is, do async loading). * **`var myglobal = requireInject.installGlobally.andClearCache(module, mocks)`** As with `requireInject.installGlobally` but clear the cache first as with `requireInject.withClearCache`. Because this globally clears the cache it means that any requires after this point will get fresh copies of their required modules, even if you required them previously. require-inject-a4803ca6aa4cb99c10630257e3ce3b1656a1c216/index.js000066400000000000000000000045041272442312100227760ustar00rootroot00000000000000'use strict' var path = require('path') var caller = require('caller') exports = module.exports = function (toLoad, mocks) { return requireInject(toLoad, mocks) } exports.withEmptyCache = function (toLoad, mocks) { return requireInject(toLoad, mocks, true) } exports.installGlobally = installGlobally exports.installGlobally.andClearCache = function (toLoad, mocks) { var callerFilename = getCallerFilename() Object.keys(require.cache).forEach(function (name) { if (name !== callerFilename) delete require.cache[name] }) return installGlobally(toLoad, mocks) } var requireInject = function (toLoad, mocks, withEmptyCache) { // Copy the existing cache var originalCache = {} Object.keys(require.cache).forEach(function (name) { originalCache[name] = require.cache[name] }) var mocked = withEmptyCache ? installGlobally.andClearCache(toLoad, mocks) : installGlobally(toLoad, mocks) // restore the cache, we can't just assign originalCache to require.cache as the require // object is unique to each module, even though require.cache is shared Object.keys(require.cache).forEach(function (name) { delete require.cache[name] }) Object.keys(originalCache).forEach(function (name) { require.cache[name] = originalCache[name] }) return mocked } function resolve (callerFilename, name) { if (/^[.][.]?\//.test(name)) { name = path.resolve(path.dirname(callerFilename), name) } return require.resolve(name) } function getCallerFilename () { var callerFilename for (var ii = 1; ii <= 10; ++ii) { callerFilename = caller(ii) if (callerFilename !== module.filename) return callerFilename } throw new Error("Couldn't find caller that wasn't " + module.filename + ' in most recent 10 stackframes') } function installGlobally (toLoad, mocks) { var callerFilename = getCallerFilename() // Inject all of our mocks Object.keys(mocks).forEach(function (name) { var namePath = resolve(callerFilename, name) if (mocks[name] == null) { delete require.cache[namePath] } else { require.cache[namePath] = {exports: mocks[name]} } }) var toLoadPath = resolve(callerFilename, toLoad) // remove any unmocked version previously loaded delete require.cache[toLoadPath] // load our new version using our mocks return require.cache[callerFilename].require(toLoadPath) } require-inject-a4803ca6aa4cb99c10630257e3ce3b1656a1c216/package.json000066400000000000000000000012371272442312100236170ustar00rootroot00000000000000{ "name": "require-inject", "version": "1.4.0", "description": "A simple mock injector compatible needing no instrumentation in the libraries being tested", "main": "index.js", "scripts": { "test": "standard && tap test/*.js" }, "author": "Rebecca Turner (http://re-becca.org)", "keywords": [ "mock", "mocks", "injection", "dependency", "require" ], "repository": { "type": "git", "url": "git@github.com:iarna/require-inject.git" }, "license": "ISC", "devDependencies": { "standard": "^7.1.2", "tacks": "1.0.11", "tap": "^2.2.0" }, "dependencies": { "caller": "^1.0.1" } } require-inject-a4803ca6aa4cb99c10630257e3ce3b1656a1c216/test/000077500000000000000000000000001272442312100223055ustar00rootroot00000000000000require-inject-a4803ca6aa4cb99c10630257e3ce3b1656a1c216/test/injection-leaking-1.js000066400000000000000000000024461272442312100264010ustar00rootroot00000000000000'use strict' var test = require('tap').test var requireInject = require('../index') var path = require('path') var Tacks = require('tacks') var File = Tacks.File var Dir = Tacks.Dir var fixturepath = path.resolve(__dirname, 'lib') var fixture = new Tacks( Dir({ 'a.js': File( "'use strict'\n" + "var b = require('./b')\n" + 'module.exports = function (infile, outfile, cb) {\n' + ' b(infile, outfile, cb)\n' + '}\n' ), 'b.js': File( "'use strict'\n" + "var fs = require('fs')\n" + 'module.exports = function (infile, outfile, cb) {\n' + ' fs.rename(infile, outfile, cb)\n' + '}\n' ) }) ) test('setup', function (t) { setup() t.done() }) test('injection leaking at a distance', function (t) { t.plan(2) var first = requireInject('./lib/a', { 'fs': { rename: function (infile, outfile, cb) { cb() } } }) first('in', 'out', function (err) { t.notOk(err, 'should be able to rename a file') }) var second = require('./lib/a') second('in', 'out', function (err) { t.ok(err, 'shouldn\'t be able to rename now') }) }) test('cleanup', function (t) { cleanup() t.done() }) function setup () { cleanup() fixture.create(fixturepath) } function cleanup () { fixture.remove(fixturepath) } require-inject-a4803ca6aa4cb99c10630257e3ce3b1656a1c216/test/injection-leaking-2.js000066400000000000000000000024461272442312100264020ustar00rootroot00000000000000'use strict' var test = require('tap').test var requireInject = require('../index') var path = require('path') var Tacks = require('tacks') var File = Tacks.File var Dir = Tacks.Dir var fixturepath = path.resolve(__dirname, 'lib') var fixture = new Tacks( Dir({ 'b.js': File( "'use strict'\n" + "var fs = require('fs')\n" + 'module.exports = function (infile, outfile, cb) {\n' + ' fs.rename(infile, outfile, cb)\n' + '}\n' ), 'c.js': File( "'use strict'\n" + "var b = require('./b')\n" + 'module.exports = function (infile, outfile, cb) {\n' + ' b(infile, outfile, cb)\n' + '}\n' ) }) ) test('setup', function (t) { setup() t.done() }) test('injection leaking at a distance', function (t) { t.plan(2) var first = requireInject('./lib/b', { 'fs': { rename: function (infile, outfile, cb) { cb() } } }) first('in', 'out', function (err) { t.notOk(err, 'should be able to rename a file') }) var second = require('./lib/c') second('in', 'out', function (err) { t.ok(err, 'shouldn\'t be able to rename now') }) }) test('cleanup', function (t) { cleanup() t.done() }) function setup () { cleanup() fixture.create(fixturepath) } function cleanup () { fixture.remove(fixturepath) } require-inject-a4803ca6aa4cb99c10630257e3ce3b1656a1c216/test/injection-missing-1.js000066400000000000000000000035301272442312100264330ustar00rootroot00000000000000'use strict' var test = require('tap').test var requireInject = require('../index') var path = require('path') var Tacks = require('tacks') var File = Tacks.File var Dir = Tacks.Dir var fixturepath = path.resolve(__dirname, 'lib') var fixture = new Tacks( Dir({ 'a.js': File( "'use strict'\n" + "var b = require('./b')\n" + 'module.exports = function(infile, outfile, cb) {\n' + ' b(infile, outfile, cb)\n' + '}\n' ), 'b.js': File( "'use strict'\n" + "var fs = require('fs')\n" + 'module.exports = function(infile, outfile, cb) {\n' + ' fs.rename(infile, outfile, cb)\n' + '}\n' ), 'd.js': File( "'use strict'\n" + "var b = require('./b')\n" + "var e = require('./e')\n" + 'module.exports.b = function(infile, outfile, cb) {\n' + ' b(infile, outfile, cb)\n' + '}\n' + 'module.exports.e = function(infile, outfile, cb) {\n' + ' e(infile, outfile, cb)\n' + '}\n' ), 'e.js': File( "'use strict'\n" + "var fs = require('fs')\n" + 'module.exports = function(infile, outfile, cb) {\n' + ' fs.rename(infile, outfile, cb)\n' + '}\n' ) }) ) test('setup', function (t) { setup() t.done() }) test('injection leaking at a distance', function (t) { t.plan(2) var first = require('./lib/a') first('in', 'out', function (err) { t.ok(err, "shouldn't be able to rename") }) var second = requireInject.withEmptyCache('./lib/a', { 'fs': { rename: function (infile, outfile, cb) { cb() } } }) second('in', 'out', function (err) { t.notOk(err, 'should be able to rename a file now') }) }) test('cleanup', function (t) { cleanup() t.done() }) function setup () { cleanup() fixture.create(fixturepath) } function cleanup () { fixture.remove(fixturepath) } require-inject-a4803ca6aa4cb99c10630257e3ce3b1656a1c216/test/injection-missing-2.js000066400000000000000000000035221272442312100264350ustar00rootroot00000000000000'use strict' var test = require('tap').test var requireInject = require('../index') var path = require('path') var Tacks = require('tacks') var File = Tacks.File var Dir = Tacks.Dir var fixturepath = path.resolve(__dirname, 'lib') var fixture = new Tacks( Dir({ 'b.js': File( "'use strict'\n" + "var fs = require('fs')\n" + 'module.exports = function (infile, outfile, cb) {\n' + ' fs.rename(infile, outfile, cb)\n' + '}\n' ), 'd.js': File( "'use strict'\n" + "var b = require('./b')\n" + "var e = require('./e')\n" + 'module.exports.b = function (infile, outfile, cb) {\n' + ' b(infile, outfile, cb)\n' + '}\n' + 'module.exports.e = function (infile, outfile, cb) {\n' + ' e(infile, outfile, cb)\n' + '}\n' ), 'e.js': File( "'use strict'\n" + "var fs = require('fs')\n" + 'module.exports = function (infile, outfile, cb) {\n' + ' fs.rename(infile, outfile, cb)\n' + '}\n' ) }) ) test('setup', function (t) { setup() t.done() }) test('injection leaking at a distance', function (t) { t.plan(4) var first = require('./lib/d') first.b('in', 'out', function (err) { t.ok(err, "shouldn't be able to rename") }) first.e('in', 'out', function (err) { t.ok(err, "shouldn't be able to rename") }) var second = requireInject.withEmptyCache('./lib/d', { 'fs': { rename: function (infile, outfile, cb) { cb() } } }) second.b('in', 'out', function (err) { t.notOk(err, 'should be able to rename a file now') }) second.e('in', 'out', function (err) { t.notOk(err, 'should be able to rename a file now') }) }) test('cleanup', function (t) { cleanup() t.done() }) function setup () { cleanup() fixture.create(fixturepath) } function cleanup () { fixture.remove(fixturepath) } require-inject-a4803ca6aa4cb99c10630257e3ce3b1656a1c216/test/injection-paths.js000066400000000000000000000027041272442312100257450ustar00rootroot00000000000000'use strict' var path = require('path') var test = require('tap').test var Tacks = require('tacks') var File = Tacks.File var Dir = Tacks.Dir var requireInject = require('../index') var testdir = path.join(__dirname, path.basename(__filename, '.js')) var adir = path.join(testdir, 'a') var bdir = path.join(testdir, 'b') var brelative = './' + path.relative(__dirname, bdir) var fixture = new Tacks( Dir({ 'a.js': File( "'use strict';\n" + "var b = require('./b');\n" + 'module.exports = function(infile, outfile, cb) {\n' + ' b(infile, outfile, cb);\n' + '};\n' ), 'b.js': File( "'use strict';\n" + "var fs = require('fs');\n" + 'module.exports = function(infile, outfile, cb) {\n' + ' fs.rename(infile, outfile, cb)\n' + '};\n' ) }) ) test('setup', function (t) { fixture.create(testdir) t.end() }) test('mock with absolute path', function (t) { t.plan(1) var a = requireInject(adir, { [bdir]: function (infile, outfile, cb) { cb() } }) a('in', 'out', function (err) { t.notOk(err, 'should be able to rename a file') }) }) test('mock with relative path', function (t) { t.plan(1) var a = requireInject(adir, { [brelative]: function (infile, outfile, cb) { cb() } }) a('in', 'out', function (err) { t.notOk(err, 'should be able to rename a file') }) }) test('cleanup', function (t) { fixture.remove(testdir) t.end() })