Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/twbs/rewire.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes <mail@johannesewald.de>2012-06-04 02:23:27 +0400
committerJohannes <mail@johannesewald.de>2012-06-04 02:23:27 +0400
commitb4b2794f5a5e5977e048ff777ac53263144126e6 (patch)
tree11213db4acbb4bd220069bd426b83d9739339379
parentd4eea33555f4e67be674c046ff1d1a9a460af94a (diff)
changed repo-name to rewire
-rw-r--r--README.md65
-rw-r--r--lib/index.js4
-rw-r--r--lib/rewire.js (renamed from lib/trick.js)15
-rw-r--r--package.json6
-rw-r--r--test/debug.test.js11
-rw-r--r--test/rewire.test.js112
-rw-r--r--test/testModules/A/moduleA.js27
-rw-r--r--test/testModules/debuggerModule.js13
-rw-r--r--test/trick.test.js104
9 files changed, 229 insertions, 128 deletions
diff --git a/README.md b/README.md
index 74aed69..8462cc8 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,61 @@
-trick
-=====
-
-Dependency injection for node.js applications \ No newline at end of file
+rewire
+=====
+**Dependency injection for node.js applications**.
+
+rewire allows you to modify the behaviour of modules for better unit testing. You may
+
+- provide mocks for other modules
+- leak private variables
+- override variables within the module
+- inject scripts
+
+rewire does **not** load the file and eval it to emulate node's require mechanism. In fact it uses node's require to load the module. Thus your module behaves exactly the same in your test environment as under regular circumstances (except your modifications).
+
+Installation
+------------
+
+```npm install rewire```
+
+Examples
+--------
+
+```javascript
+var rewire = require("rewire"),
+ rewiredModule;
+
+// Default
+////////////////////////////////
+// rewire acts exactly like require when omitting all other params
+rewiredModule = rewire("./myModuleA.js");
+
+// Mocks
+////////////////////////////////
+var mockedModuleB = {},
+ mocks = {
+ "path/to/moduleB.js": mockedModuleB
+ };
+
+// the rewired module will now use your mock instead of moduleB.js.
+rewiredModule = rewire("./myModuleA.js", mocks);
+
+
+// Injections
+////////////////////////////////
+var injections = {
+ console: {
+ log: function () { /* be quiet */ }
+ },
+ process: { argv: ["someArgs"] },
+ __filename: "some/other/dir"
+ };
+
+// overrides all given variables within the module
+rewiredModule = rewire("./myModuleA.js", null, injections);
+// you can also pass a script to inject
+rewiredModule = rewire("./myModuleA.js", null, "console.log('hellooo');");
+
+
+// Leaks
+////////////////////////////////
+
+```
diff --git a/lib/index.js b/lib/index.js
index f8f57ca..097a7b8 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -1,6 +1,6 @@
"use strict"; // run code in ES5 strict mode
-var trick = require("./trick.js");
+var rewire = require("./rewire.js");
module.exports = function (request, mocks, injections, leaks, cache) {
delete require.cache[__filename]; // deleting self from module cache so the parent module is always up to date
@@ -9,5 +9,5 @@ module.exports = function (request, mocks, injections, leaks, cache) {
cache = true;
}
- return trick(module.parent, request, mocks, injections, leaks, cache);
+ return rewire(module.parent, request, mocks, injections, leaks, cache);
}; \ No newline at end of file
diff --git a/lib/trick.js b/lib/rewire.js
index 89cbe32..0f96e4d 100644
--- a/lib/trick.js
+++ b/lib/rewire.js
@@ -7,13 +7,13 @@ var Module = require("module"),
getInjectionSrc = require("./getInjectionSrc.js");
function restoreOriginalWrappers() {
- Module.wrapper[0] = nodeWrapper0;
Module.wrapper[1] = nodeWrapper1;
}
-function trick(parentModule, filename, mocks, injections, leaks, cache) {
+function rewire(parentModule, filename, mocks, injections, leaks, cache) {
var testModule,
- nodeRequire;
+ nodeRequire,
+ wrapperExtensions = "";
function requireTrick(path) {
restoreOriginalWrappers(); // we need to restore the wrappers now so we don't influence other modules
@@ -37,15 +37,16 @@ function trick(parentModule, filename, mocks, injections, leaks, cache) {
// Prepare module for injection
if (typeof injections === "object") {
- Module.wrapper[0] = nodeWrapper0 + getInjectionSrc(injections);
+ wrapperExtensions += getInjectionSrc(injections);
} else if (typeof injections === "string") {
- Module.wrapper[0] = nodeWrapper0 + injections;
+ wrapperExtensions += injections;
}
// Prepare module for leaking private vars
if (Array.isArray(leaks)) {
- Module.wrapper[1] = getLeakingSrc(leaks) + nodeWrapper1;
+ wrapperExtensions += getLeakingSrc(leaks);
}
+ Module.wrapper[1] = wrapperExtensions + nodeWrapper1;
// Mocking module.require-function
testModule.require = requireTrick;
@@ -61,4 +62,4 @@ function trick(parentModule, filename, mocks, injections, leaks, cache) {
return testModule.exports;
}
-module.exports = trick; \ No newline at end of file
+module.exports = rewire; \ No newline at end of file
diff --git a/package.json b/package.json
index 34a1448..9408fc2 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
{
- "name" : "trick",
+ "name" : "rewire",
"version" : "0.1.0",
"description" : "Dependency injection for node.js applications",
"keywords" : [
@@ -17,7 +17,7 @@
"main" : "lib/index.js",
"bugs" : {
"email" : "mail@johannesewald.de",
- "url" : "https://github.com/jhnns/trick/issues"
+ "url" : "https://github.com/jhnns/rewire/issues"
},
"licenses" : {
"type" : "MIT",
@@ -25,7 +25,7 @@
},
"repositories" : {
"type" : "git",
- "url" : "https://github.com/jhnns/trick"
+ "url" : "https://github.com/jhnns/rewire"
},
"engines" : {
"node" : "0.6.x"
diff --git a/test/debug.test.js b/test/debug.test.js
new file mode 100644
index 0000000..4a388b6
--- /dev/null
+++ b/test/debug.test.js
@@ -0,0 +1,11 @@
+"use strict"; // run code in ES5 strict mode
+
+var rewire = require("../lib/index.js");
+
+// add breakpoints in testModules/debuggerModule.js and debug this file with your IDE to
+// check if debugging works with rewire.
+var debuggerModule = rewire("./testModules/debuggerModule.js", null, {
+ someVar: "Look if you can see me in your IDE when holding at the breakpoints"
+});
+
+debuggerModule(); \ No newline at end of file
diff --git a/test/rewire.test.js b/test/rewire.test.js
new file mode 100644
index 0000000..41dff60
--- /dev/null
+++ b/test/rewire.test.js
@@ -0,0 +1,112 @@
+"use strict"; // run code in ES5 strict mode
+
+var path = require("path"),
+ expect = require("expect.js"),
+ rewire = require("../lib/index.js");
+
+var testModules = [
+ path.resolve(__dirname, "./testModules/index.js"),
+ path.resolve(__dirname, "./testModules/A/moduleA.js"),
+ path.resolve(__dirname, "./testModules/B/moduleB.js"),
+ path.resolve(__dirname, "./testModules/C/moduleC.js")
+ ];
+
+
+function cleanRequireCache() {
+ var i;
+
+ for (i = 0; i < testModules.length; i++) {
+ delete require.cache[testModules[i]];
+ }
+}
+
+describe("#rewire", function () {
+ beforeEach(cleanRequireCache); // ensuring a clean test environment
+ it("should work like require() when omitting all other params", function () {
+ expect(rewire("./testModules/A/moduleA.js")).to.be(require("./testModules/A/moduleA.js"));
+ });
+ it("should require all mocks", function () {
+ var rewired,
+ fsMock = {},
+ mocks = {},
+ moduleBMock = {},
+ moduleCMock = {},
+ toSrcMock = {},
+ indexMock = {};
+
+ mocks["fs"] = fsMock;
+ mocks[path.resolve(__dirname, "./testModules/B/moduleB.js")] = moduleBMock;
+ mocks["../C/moduleC.js"] = moduleCMock;
+ mocks["toSrc"] = toSrcMock;
+ mocks["../"] = indexMock;
+
+ rewired = rewire("./testModules/A/moduleA.js", mocks);
+ expect(rewired.fs).to.be(fsMock);
+ expect(rewired.b).to.be(moduleBMock);
+ expect(rewired.c).to.be(moduleCMock);
+ expect(rewired.toSrc).to.be(toSrcMock);
+ expect(rewired.index).to.be(indexMock);
+ });
+ it("should inject object modifications", function () {
+ var rewired,
+ injections = {
+ process: {
+ argv: ["arg1", "arg2", "arg3"]
+ },
+ console: 123
+ };
+
+ rewired = rewire("./testModules/A/moduleA.js", null, injections);
+ rewired.exportAll();
+ expect(rewired.process).not.to.be(process);
+ expect(process.argv).not.to.eql(injections.process.argv);
+ expect(rewired.process).to.eql(injections.process);
+ expect(rewired.console).to.be(123);
+ });
+ it("should inject custom scripts", function () {
+ var rewired,
+ script = "var console = 456;";
+
+ rewired = rewire("./testModules/A/moduleA.js", null, script);
+ rewired.exportAll();
+ expect(rewired.console).to.be(456);
+ });
+ it("should leak private variables", function () {
+ var rewired,
+ leaks = ["myPrivateVar"];
+
+ rewired = rewire("./testModules/A/moduleA.js", null, null, leaks);
+ expect(rewired.__.myPrivateVar).to.be("Hello I'm very private");
+ });
+ it("should leak private functions", function () {
+ var rewired,
+ leaks = ["myPrivateFunction"];
+
+ rewired = rewire("./testModules/A/moduleA.js", null, null, leaks);
+ expect(rewired.__.myPrivateFunction()).to.be("Hello I'm very private");
+ });
+ it("should leak nothing on demand", function () {
+ var rewired;
+
+ rewired = rewire("./testModules/A/moduleA.js");
+ expect(rewired.__).to.be(undefined);
+ });
+ it("should cache the rewired module", function () {
+ var rewired;
+
+ rewired = rewire("./testModules/B/moduleB.js");
+ rewired.requireIndex();
+ expect(rewired.index.b).to.be(rewired);
+ cleanRequireCache();
+ rewired = rewire("./testModules/B/moduleB.js", null, null, null, true);
+ rewired.requireIndex();
+ expect(rewired.index.b).to.be(rewired);
+ });
+ it("should not cache the rewired module on demand", function () {
+ var rewired;
+
+ rewired = rewire("./testModules/B/moduleB.js", null, null, null, false);
+ rewired.requireIndex();
+ expect(rewired.index.b).not.to.be(rewired);
+ });
+}); \ No newline at end of file
diff --git a/test/testModules/A/moduleA.js b/test/testModules/A/moduleA.js
index 1599f01..ffa3290 100644
--- a/test/testModules/A/moduleA.js
+++ b/test/testModules/A/moduleA.js
@@ -11,11 +11,22 @@ var path = require("path"),
var myPrivateVar = "Hello I'm very private";
-// expose all required modules to test for mocks
-exports.fs = fs;
-exports.b = b;
-exports.c = c;
-exports.toSrc = toSrc;
-exports.index = index;
-exports.process = process;
-exports.console = console; \ No newline at end of file
+function myPrivateFunction() {
+ return "Hello I'm very private";
+}
+
+function exportAll() {
+ // expose all required modules to test for mocks
+ exports.fs = fs;
+ exports.b = b;
+ exports.c = c;
+ exports.toSrc = toSrc;
+ exports.index = index;
+ exports.process = process;
+ exports.console = console;
+}
+
+exportAll();
+exports.exportAll = exportAll;
+
+
diff --git a/test/testModules/debuggerModule.js b/test/testModules/debuggerModule.js
new file mode 100644
index 0000000..926c607
--- /dev/null
+++ b/test/testModules/debuggerModule.js
@@ -0,0 +1,13 @@
+"use strict"; // run code in ES5 strict mode
+
+// Add a breakpoint on line 6 and on line 11 and debug "debug.test.js" to test if the IDE stops at these points.
+// Watch also the variable someVar that is injected by rewire. It will be undefined at this point because
+// all injections are executed at the end of the module.
+// It's already visible because of hoisting: http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-javascript-hoisting-explained/)
+var someNumber = 0;
+
+module.exports = function () {
+ // In this line someVar will be defined.
+ someNumber++;
+ someVar;
+}; \ No newline at end of file
diff --git a/test/trick.test.js b/test/trick.test.js
deleted file mode 100644
index 92055bc..0000000
--- a/test/trick.test.js
+++ /dev/null
@@ -1,104 +0,0 @@
-"use strict"; // run code in ES5 strict mode
-
-var path = require("path"),
- expect = require("expect.js"),
- trick = require("../lib/index.js");
-
-var testModules = [
- path.resolve(__dirname, "./testModules/index.js"),
- path.resolve(__dirname, "./testModules/A/moduleA.js"),
- path.resolve(__dirname, "./testModules/B/moduleB.js"),
- path.resolve(__dirname, "./testModules/C/moduleC.js")
- ];
-
-
-function cleanRequireCache() {
- var i;
-
- for (i = 0; i < testModules.length; i++) {
- delete require.cache[testModules[i]];
- }
-}
-
-describe("#trick", function () {
- beforeEach(cleanRequireCache); // ensuring a clean test environment
- it("should work like require() when omitting all other params", function () {
- expect(trick("./testModules/A/moduleA.js")).to.be(require("./testModules/A/moduleA.js"));
- });
- it("should require all mocks", function () {
- var tricked,
- fsMock = {},
- mocks = {},
- moduleBMock = {},
- moduleCMock = {},
- toSrcMock = {},
- indexMock = {};
-
- mocks["fs"] = fsMock;
- mocks[path.resolve(__dirname, "./testModules/B/moduleB.js")] = moduleBMock;
- mocks["../C/moduleC.js"] = moduleCMock;
- mocks["toSrc"] = toSrcMock;
- mocks["../"] = indexMock;
-
- tricked = trick("./testModules/A/moduleA.js", mocks);
- expect(tricked.fs).to.be(fsMock);
- expect(tricked.b).to.be(moduleBMock);
- expect(tricked.c).to.be(moduleCMock);
- expect(tricked.toSrc).to.be(toSrcMock);
- expect(tricked.index).to.be(indexMock);
- });
- it("should inject object modifications", function () {
- var tricked,
- injections = {
- process: {
- argv: ["arg1", "arg2", "arg3"]
- },
- console: 123
- };
-
- tricked = trick("./testModules/A/moduleA.js", null, injections);
- expect(tricked.process).not.to.be(process);
- expect(process.argv).not.to.eql(injections.process.argv);
- expect(tricked.process).to.eql(injections.process);
- expect(tricked.console).to.be(123);
- });
- it("should inject custom scripts", function () {
- var tricked,
- script = "var console = 456;";
-
- tricked = trick("./testModules/A/moduleA.js", null, script);
-
- expect(tricked.console).to.be(456);
- });
- it("should leak private variables", function () {
- var tricked,
- leaks = ["myPrivateVar"];
-
- tricked = trick("./testModules/A/moduleA.js", null, null, leaks);
- expect(tricked.__.myPrivateVar).to.be("Hello I'm very private");
- });
- it("should leak nothing on demand", function () {
- var tricked;
-
- tricked = trick("./testModules/A/moduleA.js");
- expect(tricked.__).to.be(undefined);
- });
- it("should cache the tricked module", function () {
- var tricked;
-
- tricked = trick("./testModules/B/moduleB.js");
- tricked.requireIndex();
- expect(tricked.index.b).to.be(tricked);
- cleanRequireCache();
- tricked = trick("./testModules/B/moduleB.js", null, null, null, true);
- tricked.requireIndex();
- expect(tricked.index.b).to.be(tricked);
- });
- it("should not cache the tricked module on demand", function () {
- var tricked;
-
- tricked = trick("./testModules/B/moduleB.js", null, null, null, false);
- tricked.requireIndex();
- expect(tricked.index.b).not.to.be(tricked);
- });
-}); \ No newline at end of file