diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/README.md b/README.md new file mode 100644 index 0000000..6beb638 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# Rerequire + +Dependency injection for Node.js modules. This module works the same as require but you can mock modules and globals. + +```js +var rerequire = require('rerequire'); + +rerequire(/* file to module you want to test */, /* module mocks */, /* global mocks */); +``` + +## Example + +```js +var test_file = rerequire('./test_files', { + 'http': 'http mock', // Mock global module + './mod': 'mock mod', // Mock local module +}, { + 'Date': 'mock date', // Mock gloval +}); +``` diff --git a/index.js b/index.js new file mode 100644 index 0000000..cdd45ae --- /dev/null +++ b/index.js @@ -0,0 +1,51 @@ +var cache = {}; +var fs = require('fs'); +var path = require('path'); +var vm = require('vm'); +var resolve = require('resolve'); + +var rerequire = function (file, mocks, globals) { + + mocks = mocks || {}; + + if (module.parent) { + var absolute_path = resolve.sync(file, { basedir: path.dirname(module.parent.id) }); + } + + var default_globals = { + + require: function (mod) { + var modulePath = resolve.sync(mod, { basedir: path.dirname(absolute_path) }); + return mocks[mod] || require(modulePath); + }, + + module: { + exports: {} + }, + + console: console, + + }; + + // Extend globals + + for (var i in globals) { + if (globals.hasOwnProperty(i)) { + default_globals[i] = globals[i]; + } + } + + // Cache file content + + var content = cache[file] || (function () { + cache[file] = fs.readFileSync(absolute_path, 'utf8'); + return cache[file]; + }()); + + vm.runInNewContext(content, default_globals); + + return default_globals.module.exports; + +}; + +module.exports = rerequire; diff --git a/package.json b/package.json new file mode 100644 index 0000000..70d1286 --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "name": "rerequire", + "version": "1.0.0", + "description": "Depdency injection", + "main": "index.js", + "repository": "git@github.com:Enome/rerequire.git", + "author": "Geert Pasteels", + "license": "BSD", + "dependencies": { "resolve": "~0.3.1" } +} diff --git a/specs/index.js b/specs/index.js new file mode 100644 index 0000000..ad8fe97 --- /dev/null +++ b/specs/index.js @@ -0,0 +1,69 @@ +var rerequire = require('../index'); + +describe('rerequire', function () { + + it('can require a file without an extension', function () { + var test_file = rerequire('./test_files/index'); + }); + + it('can require an index file', function () { + var test_file = rerequire('./test_files'); + }); + + + it('can require a file with an extension', function () { + var test_file = rerequire('./test_files/index.js'); + }); + + it('can mock mock module from nodes_modules', function () { + + var test_file = rerequire('./test_files/index', { + 'http': 'http mock' + }); + + test_file.http.should.eql('http mock'); + + }); + + it('can mock a local module', function () { + + var test_file = rerequire('./test_files/index', { + './mod': 'mock mod' + }); + + test_file.mod.should.eql('mock mod'); + + }); + + it('can mock a global', function () { + + var test_file = rerequire('./test_files/index', {}, { + 'Date': 'mock date' + }); + + test_file.date.should.eql('mock date'); + + }); + + it('can combine modules and globals', function () { + + var test_file = rerequire('./test_files', { + 'http': 'http mock', + './mod': 'mock mod', + }, { + 'Date': 'mock date', + }); + + // Wrap result because it doesnt have should + + ({ test_file: test_file }).should.eql({ + test_file: { + http: 'http mock', + mod: 'mock mod', + date: 'mock date', + } + }); + + }); + +}); diff --git a/specs/test_files/index.js b/specs/test_files/index.js new file mode 100644 index 0000000..f02907d --- /dev/null +++ b/specs/test_files/index.js @@ -0,0 +1,10 @@ +var http = require('http'); +var mod = require('./mod'); + +var test_files = { + http: http, + mod: mod, + date: Date, +}; + +module.exports = test_files; diff --git a/specs/test_files/mod.js b/specs/test_files/mod.js new file mode 100644 index 0000000..1c6cece --- /dev/null +++ b/specs/test_files/mod.js @@ -0,0 +1 @@ +module.exports = 'Original mod';