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:
-rw-r--r--README.md21
-rw-r--r--lib/__get__.js16
-rw-r--r--lib/__set__.js16
-rw-r--r--lib/browserify/browserInit.js44
-rw-r--r--lib/browserify/browserifyMiddleware.js79
-rw-r--r--lib/browserify/browserifyRewire.js97
-rw-r--r--lib/browserify/getRewireRequires.js16
-rw-r--r--lib/detectStrictMode.js12
-rw-r--r--lib/getImportGlobalsSrc.js2
-rw-r--r--lib/index.js35
-rw-r--r--lib/internalRewire.js (renamed from lib/rewire.js)36
-rw-r--r--package.json7
-rw-r--r--test/__get__.test.js2
-rw-r--r--test/__set__.test.js2
-rw-r--r--test/browser/index.html9
-rw-r--r--test/browserify.browserifyRewire.test.js126
-rw-r--r--test/browserify.getRewireRequires.test.js19
-rw-r--r--test/debug.test.js2
-rw-r--r--test/detectStrictMode.test.js13
-rw-r--r--test/getImportGlobalsSrc.test.js2
-rw-r--r--test/internalRewire.test.js11
-rw-r--r--test/rewire.test.js155
-rw-r--r--test/testHelpers/createFakePackageJSON.js11
-rw-r--r--test/testHelpers/removeFakePackageJSON.js9
-rw-r--r--test/testModules/moduleA.js13
-rw-r--r--test/testModules/moduleB.js36
-rw-r--r--test/testModules/sharedTestCases.js169
-rw-r--r--test/testModules/strictModule.js7
28 files changed, 713 insertions, 254 deletions
diff --git a/README.md b/README.md
index a498e5d..f3c059b 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@ rewire does **not** load the file and eval the contents to emulate node's requir
**Debugging is fully supported.**
-[![Build Status](https://secure.travis-ci.org/jhnns/rewire.png?branch=master)](http://travis-ci.org/jhnns/rewire)
+Furthermore rewire comes also with support for [browserify](https://github.com/substack/node-browserify). Thus you can mock your modules in the browser as well.
<br />
@@ -22,7 +22,16 @@ Installation
`npm install rewire`
**For older node versions:**<br />
-rewire is tested with node 0.7.x. I recommend to run the unit tests via `mocha` in the rewire-folder before using rewire with older node versions.
+rewire is tested with node 0.6.x - 0.7.x. I recommend to run the unit tests via `mocha` in the rewire-folder before using rewire with older node versions.
+
+**Use with [browserify](https://github.com/substack/node-browserify):**<br />
+
+```javascript
+// debug=true splits the source in seperate files in chrome's developer tools
+var b = require("browserify")({debug: true});
+
+b.use(require("rewire").browserify);
+```
<br />
@@ -34,8 +43,7 @@ var rewire = require("rewire");
// rewire acts exactly like require.
-var myRewiredModule = rewire("../lib/myModule.js");
-myRewiredModule === require("../lib/myModule.js"); // = true
+var myModule = rewire("../lib/myModule.js");
// Your module will now export a special setter and getter for private variables.
@@ -67,8 +75,8 @@ myModule.__set__({
});
-// You may also override globals. These changes are only within the module,
-// so you don't have to be afraid that other modules are influenced by your mock.
+// You may also override globals. These changes are only within the module, so
+// you don't have to be concerned that other modules are influenced by your mock.
myModule.__set__({
console: {
log: function () { /* be quiet */ }
@@ -91,6 +99,7 @@ assert.ok(myModule.__get__("currentState") === "idle");
// You can also disable caching when loading the rewired module. All
// subsequent calls of require() will than return the original module again.
+rewire("./myModule.js") === require("./myModule.js"); // = true
rewire("./myModule.js", false) === require("./myModule.js"); // = false
diff --git a/lib/__get__.js b/lib/__get__.js
index f6212d9..d8cdfe7 100644
--- a/lib/__get__.js
+++ b/lib/__get__.js
@@ -1,17 +1,21 @@
-"use strict"; // run code in ES5 strict mode
-
/**
* This function will be stringified and then injected into every rewired module.
* Then you can leak private variables by calling myModule.__get__("myPrivateVar");
*
+ * All variables within this function are namespaced in the arguments array because every
+ * var declaration could possibly clash with a variable in the module scope.
+ *
* @param {!String} name name of the variable to retrieve
* @throws {TypeError}
* @return {*}
*/
-module.exports = function __get__(name) {
- if (typeof name !== "string" || name.length === 0) {
+function __get__() {
+ arguments.varName = arguments[0];
+ if (typeof arguments.varName !== "string" || arguments.varName.length === 0) {
throw new TypeError("__get__ expects a non-empty string");
}
- return eval(name);
-}; \ No newline at end of file
+ return eval(arguments.varName);
+}
+
+module.exports = __get__; \ No newline at end of file
diff --git a/lib/__set__.js b/lib/__set__.js
index 219b381..79175ed 100644
--- a/lib/__set__.js
+++ b/lib/__set__.js
@@ -1,5 +1,3 @@
-"use strict"; // run code in ES5 strict mode
-
/**
* This function will be stringified and then injected into every rewired module.
* Then you can set private variables by calling myModule.__set__("myPrivateVar", newValue);
@@ -10,14 +8,16 @@
* @param {!String|!Object} varName name of the variable to set
* @param {String} varValue new value
* @throws {TypeError}
+ * @throws {ReferenceError} When the variable is unknown
* @return {*}
*/
-module.exports = function __set__() {
+function __set__() {
arguments.varName = arguments[0];
arguments.varValue = arguments[1];
arguments.src = "";
- arguments.checkExistsSrc = function (varName) {
- return "if (typeof " + varName + " === 'undefined') { throw new ReferenceError('" + varName + " is not defined');} ";
+ arguments.checkExistsSrc = function (varName, varValue) {
+ return "if (typeof " + varName + " === 'undefined') { throw new ReferenceError('Cannot __set__(" + varName + ", " + varValue + "): " +
+ varName + " is not declared within the module.'); } ";
};
if (typeof arguments[0] === "object") {
@@ -34,10 +34,12 @@ module.exports = function __set__() {
if (!arguments.varName) {
throw new TypeError("__set__ expects a non-empty string as a variable name");
}
- arguments.src = arguments.checkExistsSrc(arguments.varName) + arguments.varName + " = arguments.varValue;";
+ arguments.src = arguments.checkExistsSrc(arguments.varName, arguments.varValue) + arguments.varName + " = arguments.varValue;";
} else {
throw new TypeError("__set__ expects an environment object or a non-empty string as a variable name");
}
eval(arguments.src);
-}; \ No newline at end of file
+}
+
+module.exports = __set__; \ No newline at end of file
diff --git a/lib/browserify/browserInit.js b/lib/browserify/browserInit.js
new file mode 100644
index 0000000..02fd9c1
--- /dev/null
+++ b/lib/browserify/browserInit.js
@@ -0,0 +1,44 @@
+/**
+ * This code gets injected at the end of the browserify bundle via b.append().
+ */
+
+if (typeof window.browserifyRequire !== "undefined") {
+ throw new Error("Naming collision detected: window.browserifyRequire seems to be occupied.");
+}
+
+// Saves the browserifyRequire under a new name. Necessary to call the original browserifyRequire within
+// a module where the variable name "require" is overridden by the module's internal require.
+window.browserifyRequire = require;
+
+/**
+ * Provides a special require-proxy. Every module calls window.browserifyRequire.getProxy(require, __filename) at the
+ * beginning and overrides its own require with this proxy.
+ *
+ * This is necessary to call rewire() with the original __filename. Thus you can use rewire() like require().
+ *
+ * @param {!Function} internalRequire the module's own require
+ * @param {String} filename the __filename of the module
+ * @return {Function} requireProxy
+ */
+window.browserifyRequire.getProxy = function (internalRequire, filename) {
+ var rewireModule = internalRequire("rewire"),
+ key;
+
+ function rewireProxy(path, cache) {
+ return rewireModule(filename, path, cache);
+ }
+
+ for (key in rewireModule) {
+ if (rewireModule.hasOwnProperty(key)) {
+ rewireProxy[key] = rewireModule[key];
+ }
+ }
+
+ return function requireProxy(path) {
+ if (path === "rewire") {
+ return rewireProxy;
+ } else {
+ return internalRequire(path);
+ }
+ };
+}; \ No newline at end of file
diff --git a/lib/browserify/browserifyMiddleware.js b/lib/browserify/browserifyMiddleware.js
new file mode 100644
index 0000000..d62352e
--- /dev/null
+++ b/lib/browserify/browserifyMiddleware.js
@@ -0,0 +1,79 @@
+var setterSrc = require("../__set__.js").toString(),
+ getterSrc = require("../__get__.js").toString(),
+ fs = require("fs"),
+ path = require("path"),
+ getImportGlobalsSrc = require("../getImportGlobalsSrc.js"),
+ getRewireRequires = require("./getRewireRequires.js"),
+ detectStrictMode = require("../detectStrictMode.js"),
+
+ browserInit = fs.readFileSync(__dirname + "/browserInit.js", "utf8"),
+ importGlobalsSrc = getImportGlobalsSrc(),
+ injectionSrc = getInjectionSrc().replace(/\s+/g, " "); // strip out unnecessary spaces to be unobtrusive in the debug view
+
+/**
+ * Returns a string that gets injected at the beginning of every module. Its purpose is to
+ *
+ * - register the setters and getters according to the module's filename
+ * - override the internal require with a require proxy.
+ *
+ * @return {String}
+ */
+function getInjectionSrc() {
+ // Registers the setters and getters of every module according to their filename. The setters and getters must be
+ // injected as string here to gain access to the private scope of the module.
+ return 'require("rewire").register(__filename, ' + setterSrc + ', ' + getterSrc + ');' +
+ // Overrides the module internal require with a require proxy. This proxy is necessary to call rewire with the
+ // module's filename at the first parameter to resolve the path. This way rewire() works exactly like require().
+ 'require = window.browserifyRequire.getProxy(require, __filename);';
+}
+
+function browserifyMiddleware(b) {
+ function injectRewire(src, filename) {
+ var rewireRequires,
+ strictMode = "";
+
+ // Search for all rewire() statements an return the required path.
+ rewireRequires = getRewireRequires(src);
+
+ // Add all modules that are loaded by rewire() manually to browserify because browserify's
+ // require-sniffing doesn't work here.
+ rewireRequires.forEach(function forEachRewireRequire(requirePath) {
+ // Resolve absolute paths
+ if (requirePath.charAt(0) === ".") {
+ requirePath = path.resolve(path.dirname(filename), requirePath);
+ }
+ b.require(requirePath);
+ });
+
+ // If the module uses strict mode we must ensure that "use strict" stays at the beginning of the module.
+ if (detectStrictMode(src) === true) {
+ strictMode = ' "use strict"; ';
+ }
+
+ // Convert back slashes to normal slashes.
+ filename = filename.replace(/\\/g, "/");
+
+ // We don't want to inject this code at the beginning of a rewire/lib-module. Otherwise
+ // it would cause a black hole that devours our universe.
+ if (filename.indexOf("/rewire/lib") === -1) {
+ src =
+ strictMode + // either '' or ' "use strict"; '
+ "/* this line was injected by rewire() */" +
+ "var global = window; " + // window is our new global object
+ importGlobalsSrc +
+ injectionSrc + "\n" +
+ src;
+ }
+
+ return src;
+ }
+
+ // Register file handler
+ b.register(".js", injectRewire);
+ // Append rewire initialization at the end of the bundle
+ b.append(browserInit);
+
+ return b;
+}
+
+module.exports = browserifyMiddleware; \ No newline at end of file
diff --git a/lib/browserify/browserifyRewire.js b/lib/browserify/browserifyRewire.js
new file mode 100644
index 0000000..d70f31e
--- /dev/null
+++ b/lib/browserify/browserifyRewire.js
@@ -0,0 +1,97 @@
+var pathUtil = require("path"),
+ browserifyRequire = window.browserifyRequire;
+
+// Saves all setters and getters for every module according to its filename
+var registry = {},
+// Cache for all rewired modules so it can be reset anytime
+ rewiredModules = [];
+
+/**
+ * Executes the given module and adds a special setter and getter that allow you to set and get private variables.
+ * The parentModulePath is usually set by the requireProxy.
+ *
+ * @param {!String} parentModulePath __filename of the module, that wants to rewire() another module.
+ * @param {!String} targetPath path to the module that shall be rewired
+ * @param {Boolean=true} cache indicates whether the rewired module should be cached or not
+ * @return {Object}
+ */
+function browserifyRewire(parentModulePath, targetPath, cache) {
+ var originalModule,
+ rewiredModule = {},
+ registeredTargetModule;
+
+ // Default cache to true
+ if (cache === undefined) {
+ cache = true;
+ }
+
+ // Make absolute paths
+ if (targetPath.charAt(0) === ".") {
+ targetPath = pathUtil.resolve(pathUtil.dirname(parentModulePath), targetPath);
+ }
+
+ // Normalize path with file extensions
+ targetPath = require.resolve(targetPath);
+
+ // Deleting module from cache to trigger execution again
+ delete browserifyRequire.modules[targetPath]._cached;
+
+ // Require module to trigger rewire.register() if it hasnt been required yet
+ // Putting (require) within brackets is a hack to disable browserifys require sniffing
+ // @see https://github.com/substack/node-browserify/issues/132#issuecomment-5281470
+ originalModule = (require)(targetPath);
+
+ // Copy all exported values to our rewired module
+ for (var key in originalModule) {
+ if (originalModule.hasOwnProperty(key)) {
+ rewiredModule[key] = originalModule[key];
+ }
+ }
+
+ // If caching is enabled we store the rewiredModule in the cache
+ if (cache) {
+ browserifyRequire.modules[targetPath]._cached = rewiredModule;
+ }
+
+ // Get registry entry of the target module
+ registeredTargetModule = registry[targetPath];
+
+ // Apply setter and getters
+ rewiredModule.__set__ = registeredTargetModule.setter;
+ rewiredModule.__get__ = registeredTargetModule.getter;
+
+ // Store rewired modules for rewire.reset()
+ rewiredModules.push(targetPath);
+
+ return rewiredModule;
+}
+
+/**
+ * Registers the setter and getter of every module according to its filename
+ *
+ * @param {!String} filename the absolute path to the module (module id)
+ * @param {!Function} setter
+ * @param {!Function} getter
+ */
+browserifyRewire.register = function (filename, setter, getter) {
+ registry[filename] = {
+ setter: setter,
+ getter: getter
+ };
+};
+
+/**
+ * Deletes all rewired modules from the cache
+ */
+browserifyRewire.reset = function () {
+ var modules = browserifyRequire.modules,
+ i;
+
+ for (i = 0; i < rewiredModules.length; i++) {
+ delete modules[rewiredModules[i]]._cached;
+ }
+
+ rewiredModules = [];
+};
+
+module.exports = browserifyRewire; \ No newline at end of file
diff --git a/lib/browserify/getRewireRequires.js b/lib/browserify/getRewireRequires.js
new file mode 100644
index 0000000..c8b0f01
--- /dev/null
+++ b/lib/browserify/getRewireRequires.js
@@ -0,0 +1,16 @@
+function getRewireRequires(src) {
+ var result = [],
+ regExp = /[^a-zA-Z0-9_]rewire\(["'](.+?)["']\)/g,
+ match;
+
+ src = " " + src; // ensure that rewire() is not at index 0 otherwise the regexp won't work in this case
+ match = regExp.exec(src);
+ while (match !== null) {
+ result.push(match[1]);
+ match = regExp.exec(src);
+ }
+
+ return result;
+}
+
+module.exports = getRewireRequires; \ No newline at end of file
diff --git a/lib/detectStrictMode.js b/lib/detectStrictMode.js
new file mode 100644
index 0000000..347c455
--- /dev/null
+++ b/lib/detectStrictMode.js
@@ -0,0 +1,12 @@
+/**
+ * Returns true if the source code is intended to run in strict mode. Does not detect
+ * "use strict" if it occurs in a nested function.
+ *
+ * @param {!String} src
+ * @return {Boolean}
+ */
+function detectStrictMode(src) {
+ return (/^\s*"use strict";/g).test(src);
+}
+
+module.exports = detectStrictMode; \ No newline at end of file
diff --git a/lib/getImportGlobalsSrc.js b/lib/getImportGlobalsSrc.js
index 1bcfed4..dc40a4b 100644
--- a/lib/getImportGlobalsSrc.js
+++ b/lib/getImportGlobalsSrc.js
@@ -1,5 +1,3 @@
-"use strict"; // run code in ES5 strict mode
-
/**
* Declares all globals with a var and assigns the global object. Thus you're able to
* override globals without changing the global object itself.
diff --git a/lib/index.js b/lib/index.js
index a6dbcd6..491599a 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -1,28 +1,33 @@
-"use strict"; // run code in ES5 strict mode
-
-var rewireModule = require("./rewire.js");
+var rewireModule;
/**
- * This function is needed to determine the calling parent module.
- * Thus rewire acts exactly the same like require() in the test module.
+ * Adds a special setter and getter to the module located at filename. After the module has been rewired, you can
+ * call myModule.__set__(name, value) and myModule.__get__(name) to manipulate private variables.
*
- * @param {!String} request Path to the module that shall be rewired. Use it exactly like require().
- * @param {Object} mocks An object with mocks. Keys should be the exactly same like they're required in the target module. So if you write require("../../myModules/myModuleA.js") you need to pass {"../../myModules/myModuleA.js": myModuleAMock}.
- * @param {Object} injections If you pass an object, all keys of the object will be vars within the module. You can also eval a string. Please note: All scripts are injected at the end of the module. So if there is any code in your module that is executed during require(), your injected variables will be undefined at this point. For example: passing {console: {...}} will cause all calls of console.log() to throw an exception if they're executed during require().
- * @param {Array} leaks An array with variable names that should be exported. These variables are accessible via myModule.__
+ * @param {!String} filename Path to the module that shall be rewired. Use it exactly like require().
* @param {Boolean} cache Indicates whether the rewired module should be cached by node so subsequent calls of require() will return the rewired module. Subsequent calls of rewire() will always overwrite the cache.
* @return {*} the rewired module
*/
-function rewire(request, cache) {
- delete require.cache[__filename]; // deleting self from module cache so the parent module is always up to date
-
+function rewire(filename, cache) {
if (cache === undefined) {
cache = true;
}
- return rewireModule(module.parent, request, cache);
+ return rewireModule(module.parent, filename, cache);
}
-rewire.reset = rewireModule.reset;
+// Conditional require for different environments
+if (process.title === "browser") {
+ module.exports = require("./browserify/browserifyRewire.js");
+} else {
+ delete require.cache[__filename]; // deleting self from module cache so the parent module is always up to date
-module.exports = rewire; \ No newline at end of file
+ // Putting (require) within brackets is a hack to disable browserify's require sniffing
+ // @see https://github.com/substack/node-browserify/issues/132#issuecomment-5281470
+ rewireModule = (require)("./internalRewire.js");
+
+ rewire.reset = rewireModule.reset;
+ rewire.browserify = (require)("./browserify/browserifyMiddleware.js");
+
+ module.exports = rewire;
+}
diff --git a/lib/rewire.js b/lib/internalRewire.js
index ae23fb1..b4c8e62 100644
--- a/lib/rewire.js
+++ b/lib/internalRewire.js
@@ -1,9 +1,9 @@
-"use strict"; // run code in ES5 strict mode
-
var Module = require("module"),
+ fs = require("fs"),
__get__ = require("./__get__.js"),
__set__ = require("./__set__.js"),
getImportGlobalsSrc = require("./getImportGlobalsSrc.js"),
+ detectStrictMode = require("./detectStrictMode.js"),
moduleWrapper0 = Module.wrapper[0], // caching original wrapper
moduleWrapper1 = Module.wrapper[1], // caching original wrapper
@@ -17,11 +17,12 @@ function restoreOriginalWrappers() {
/**
* Does actual rewiring the module. For further documentation @see index.js
*/
-function rewire(parentModule, filename, cache) {
+function internalRewire(parentModulePath, targetPath, cache) {
var testModule,
nodeRequire,
prepend,
- append;
+ append,
+ src;
/**
* Proxies the first require call in order to draw back all changes.
@@ -36,21 +37,21 @@ function rewire(parentModule, filename, cache) {
}
// Checking params
- if (typeof filename !== "string") {
+ if (typeof targetPath !== "string") {
throw new TypeError("Filename must be a string");
}
// Resolve full filename relative to the parent module
- filename = Module._resolveFilename(filename, parentModule);
+ targetPath = Module._resolveFilename(targetPath, parentModulePath);
// Special support for older node versions that returned an array on Module._resolveFilename
// @see https://github.com/joyent/node/blob/865b077819a9271a29f982faaef99dc635b57fbc/lib/module.js#L319
- if (Array.isArray(filename)) {
- filename = filename[1];
+ if (Array.isArray(targetPath)) {
+ targetPath = targetPath[1];
}
// Create testModule as it would be created by require()
- testModule = new Module(filename, parentModule);
+ testModule = new Module(targetPath, parentModulePath);
// Patching requireProxy
nodeRequire = testModule.require;
@@ -63,7 +64,14 @@ function rewire(parentModule, filename, cache) {
append = "module.exports.__set__ = " + __set__.toString() + "; ";
append += "module.exports.__get__ = " + __get__.toString() + "; ";
- // Apply prepend and append
+ // Check if the module uses the strict mode.
+ // If so we must ensure that "use strict"; stays at the beginning of the module.
+ src = fs.readFileSync(targetPath, "utf8");
+ if (detectStrictMode(src) === true) {
+ prepend = ' "use strict"; ' + prepend;
+ }
+
+ // Apply prepend and appends
Module.wrapper[0] = moduleWrapper0 + prepend;
Module.wrapper[1] = append + moduleWrapper1;
@@ -74,8 +82,8 @@ function rewire(parentModule, filename, cache) {
// Store the rewired module in the cache when enabled
if (cache) {
- rewiredModules.push(filename); // save in private cache for .reset()
- require.cache[filename] = testModule;
+ rewiredModules.push(targetPath); // save in private cache for .reset()
+ require.cache[targetPath] = testModule;
}
// This is only necessary if nothing has been required within the module
@@ -87,7 +95,7 @@ function rewire(parentModule, filename, cache) {
/**
* Deletes all rewired modules from the cache
*/
-rewire.reset = function () {
+internalRewire.reset = function () {
var i;
for (i = 0; i < rewiredModules.length; i++) {
@@ -97,4 +105,4 @@ rewire.reset = function () {
rewiredModules = [];
};
-module.exports = rewire; \ No newline at end of file
+module.exports = internalRewire; \ No newline at end of file
diff --git a/package.json b/package.json
index fc41074..c05ab1a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name" : "rewire",
- "version" : "0.2.2",
+ "version" : "0.3.0",
"description" : "Dependency injection for node.js applications",
"keywords" : [
"dependency",
@@ -31,9 +31,10 @@
},
"devDependencies": {
"mocha": "1.2.x",
- "expect.js": "0.1.x"
+ "expect.js": "0.1.x",
+ "browserify": "1.13.x"
},
"scripts" : {
- "test" : "mocha"
+ "test" : "mocha -R spec"
}
} \ No newline at end of file
diff --git a/test/__get__.test.js b/test/__get__.test.js
index 6506e84..53e909c 100644
--- a/test/__get__.test.js
+++ b/test/__get__.test.js
@@ -1,5 +1,3 @@
-"use strict"; // run code in ES5 strict mode
-
var expect = require("expect.js"),
vm = require("vm"),
__get__ = require("../lib/__get__.js"),
diff --git a/test/__set__.test.js b/test/__set__.test.js
index e1565c7..28e3e8d 100644
--- a/test/__set__.test.js
+++ b/test/__set__.test.js
@@ -1,5 +1,3 @@
-"use strict"; // run code in ES5 strict mode
-
var expect = require("expect.js"),
__set__ = require("../lib/__set__.js"),
vm = require("vm"),
diff --git a/test/browser/index.html b/test/browser/index.html
new file mode 100644
index 0000000..46d63d9
--- /dev/null
+++ b/test/browser/index.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<head>
+ <link rel="stylesheet" href="../../node_modules/mocha/mocha.css" />
+ <script src="../../node_modules/mocha/mocha.js" type="text/javascript"></script>
+ <script src="browseroutput.js" type="text/javascript"></script>
+</head>
+<body>
+ <div id="mocha"></div>
+</body> \ No newline at end of file
diff --git a/test/browserify.browserifyRewire.test.js b/test/browserify.browserifyRewire.test.js
new file mode 100644
index 0000000..43c7082
--- /dev/null
+++ b/test/browserify.browserifyRewire.test.js
@@ -0,0 +1,126 @@
+var vm = require("vm"),
+ fs = require("fs"),
+ pathUtil = require("path"),
+ expect = require("expect.js"),
+ browserify = require("browserify");
+
+/**
+ * Executes the source in a context that pretends to be a browser
+ * @param {!String} src
+ */
+function runInFakeBrowserContext(src, filename) {
+ vm.runInNewContext(src, {
+ window: {
+ console: console,
+ describe: describe,
+ it: it,
+ before: before,
+ after: after,
+ beforeEach: beforeEach,
+ afterEach: afterEach,
+ setTimeout: setTimeout
+ },
+ console: console
+ }, filename);
+}
+
+describe("browserifyRewire", function () {
+ before(require("./testHelpers/createFakePackageJSON.js"));
+ after(require("./testHelpers/removeFakePackageJSON.js"));
+ it("should attach __set__ and __get__ to the exports-obj", function (done) {
+ var context,
+ exportsObj = {},
+ returnedObj,
+ browserifyRewire;
+
+ // Register with fake objects
+ // Using null for objects that are not involved in this particular test
+ function moduleA() {
+ "use strict";
+
+ browserifyRewire.register("/a.js", null, null);
+ returnedObj = browserifyRewire("/a.js", "/b.js");
+ }
+
+ function moduleB() {
+ "use strict";
+ browserifyRewire.register("/b.js", setter, getter);
+
+ return exportsObj;
+ }
+
+ function fakeResolve() {
+ return "/b.js";
+ }
+
+ function fakeRequire(requirePath) {
+ if (requirePath === "path") {
+ return pathUtil;
+ } else {
+ return moduleB();
+ }
+ }
+ fakeRequire.resolve = fakeResolve;
+
+ function setter() {}
+ function getter() {}
+
+ context = {
+ require: fakeRequire,
+ module: {},
+ console: console,
+ window: {
+ browserifyRequire: {
+ modules: {
+ "/b.js": {
+ _cached : {}
+ }
+ }
+ }
+ }
+ };
+
+ fs.readFile(pathUtil.resolve(__dirname, "../lib/browserify/browserifyRewire.js"), "utf8", function onBrowserifyRewireRead(err, src) {
+ vm.runInNewContext(src, context);
+ browserifyRewire = context.module.exports;
+
+ moduleA();
+
+ expect(returnedObj).not.to.be(exportsObj);
+ expect(returnedObj.__set__).to.be(setter);
+ expect(returnedObj.__get__).to.be(getter);
+ expect(context.window.browserifyRequire.modules["/b.js"]._cached).to.be(returnedObj);
+
+ done();
+ });
+ });
+ it("should run all sharedTestCases without exception", function (done) {
+ var b = browserify({debug: true}),
+ middleware = require("rewire").browserify,
+ browserOutput = __dirname + "/browser/browseroutput.js",
+ browserBundle,
+ vmBundle;
+
+ b.use(middleware);
+ b.require(__dirname + "/testModules/sharedTestCases.js");
+ vmBundle = b.bundle();
+ browserBundle = vmBundle;
+
+ // Setup for mocha
+ browserBundle += 'window.onload = function () {' +
+ 'mocha.setup("bdd");' +
+ 'window.browserifyRequire("/test/testModules/sharedTestCases.js");' +
+ 'mocha.run();' +
+ '};';
+
+ vmBundle += 'window.browserifyRequire("/test/testModules/sharedTestCases.js");';
+
+ // Output for browser-testing
+ fs.mkdir(__dirname + "/browser", function onMkDir() {
+ fs.writeFile(browserOutput, browserBundle, "utf8", done);
+
+ // This should throw no exception.
+ runInFakeBrowserContext(vmBundle, browserOutput);
+ });
+ });
+}); \ No newline at end of file
diff --git a/test/browserify.getRewireRequires.test.js b/test/browserify.getRewireRequires.test.js
new file mode 100644
index 0000000..98673cc
--- /dev/null
+++ b/test/browserify.getRewireRequires.test.js
@@ -0,0 +1,19 @@
+var expect = require("expect.js"),
+ getRewireRequires = require("../lib/browserify/getRewireRequires.js");
+
+describe("getRewireRequires", function () {
+ it("should detect a single rewire()", function () {
+ var src = "rewire('aaa/bbb/ccc.js');";
+
+ expect(getRewireRequires(src)).to.eql(["aaa/bbb/ccc.js"]);
+ });
+ it("should detect multiple rewire()", function () {
+ var src = "var aaa = rewire('aaa/bbb/ccc.js'); var bbb = rewire('bbb/ccc/ddd.js');";
+
+ expect(getRewireRequires(src)).to.eql(["aaa/bbb/ccc.js", "bbb/ccc/ddd.js"]);
+
+ src = "rewire('aaa/bbb/ccc.js'); rewire('bbb/ccc/ddd.js');";
+
+ expect(getRewireRequires(src)).to.eql(["aaa/bbb/ccc.js", "bbb/ccc/ddd.js"]);
+ });
+}); \ No newline at end of file
diff --git a/test/debug.test.js b/test/debug.test.js
index acd16ee..0ffbacf 100644
--- a/test/debug.test.js
+++ b/test/debug.test.js
@@ -1,5 +1,3 @@
-"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
diff --git a/test/detectStrictMode.test.js b/test/detectStrictMode.test.js
new file mode 100644
index 0000000..a154471
--- /dev/null
+++ b/test/detectStrictMode.test.js
@@ -0,0 +1,13 @@
+var expect = require("expect.js"),
+ detectStrictMode = require("../lib/detectStrictMode.js");
+
+describe("detectStrictMode", function () {
+ it("should detect \"use strict\"; at the beginning of a string and ignore all whitespace before", function () {
+ expect(detectStrictMode('"use strict";')).to.be(true);
+ expect(detectStrictMode(' "use strict";')).to.be(true);
+ expect(detectStrictMode(' \n "use strict";')).to.be(true);
+ });
+ it("should not detect \"use strict\"; if it occurs in some nested function", function () {
+ expect(detectStrictMode('function () {"use strict";}')).to.be(false);
+ });
+}); \ No newline at end of file
diff --git a/test/getImportGlobalsSrc.test.js b/test/getImportGlobalsSrc.test.js
index b6f8576..065bd59 100644
--- a/test/getImportGlobalsSrc.test.js
+++ b/test/getImportGlobalsSrc.test.js
@@ -1,5 +1,3 @@
-"use strict"; // run code in ES5 strict mode
-
var expect = require("expect.js"),
vm = require("vm"),
getImportGlobalsSrc = require("../lib/getImportGlobalsSrc.js");
diff --git a/test/internalRewire.test.js b/test/internalRewire.test.js
new file mode 100644
index 0000000..23d0193
--- /dev/null
+++ b/test/internalRewire.test.js
@@ -0,0 +1,11 @@
+// Don't run code in ES5 strict mode.
+// In case this module was in strict mode, all other modules called by this would also be strict.
+// But when testing if the strict mode is preserved, we must ensure that this module is NOT strict.
+
+describe("internalRewire (node.js)", function () {
+ before(require("./testHelpers/createFakePackageJSON.js"));
+ after(require("./testHelpers/removeFakePackageJSON.js"));
+ it("should pass all shared test cases", function () {
+ require("./testModules/sharedTestCases.js");
+ });
+}); \ No newline at end of file
diff --git a/test/rewire.test.js b/test/rewire.test.js
deleted file mode 100644
index 1e40041..0000000
--- a/test/rewire.test.js
+++ /dev/null
@@ -1,155 +0,0 @@
-"use strict"; // run code in ES5 strict mode
-
-var path = require("path"),
- expect = require("expect.js"),
- rewire = require("../lib/index.js");
-
-var testModules = {
- A: path.resolve(__dirname, "./testModules/moduleA.js"),
- B: path.resolve(__dirname, "./testModules/moduleB.js"),
- someOtherModule: path.resolve(__dirname, "./testModules/someOtherModule.js"),
- emptyModule: path.resolve(__dirname, "./testModules/emptyModule.js")
- };
-
-function cleanRequireCache() {
- var moduleName,
- modulePath;
-
- for (moduleName in testModules) {
- if (testModules.hasOwnProperty(moduleName)) {
- modulePath = testModules[moduleName];
- delete require.cache[modulePath];
- }
- }
-}
-
-describe("rewire", function () {
- beforeEach(cleanRequireCache); // ensuring a clean test environment
- it("should work like require()", function () {
- expect(rewire("./testModules/moduleA.js")).to.be(require("./testModules/moduleA.js"));
- cleanRequireCache();
- expect(rewire("../test/testModules/moduleA.js")).to.be(require("../test/testModules/moduleA.js"));
- cleanRequireCache();
- expect(rewire(testModules.A)).to.be(require(testModules.A));
- });
- it("should modify the module so it provides a __set__ - function", function () {
- expect(rewire(testModules.A).__set__).to.be.a(Function);
- expect(rewire(testModules.B).__set__).to.be.a(Function);
- });
- it("should modify the module so it provides a __get__ - function", function () {
- expect(rewire(testModules.A).__get__).to.be.a(Function);
- expect(rewire(testModules.B).__get__).to.be.a(Function);
- });
- it("should not influence other modules", function () {
- var rewiredModuleA = rewire(testModules.A);
-
- expect(require(testModules.someOtherModule).__set__).to.be(undefined);
- expect(require(testModules.someOtherModule).__get__).to.be(undefined);
- expect(require("fs").__set__).to.be(undefined);
- expect(require("fs").__get__).to.be(undefined);
- });
- it("should not influence global objects by default", function () {
- expect(function () {
- rewire(testModules.A).checkSomeGlobals();
- rewire(testModules.B).checkSomeGlobals();
- }).to.not.throwException();
- });
- it("should provide the ability to set private vars", function () {
- var rewiredModuleA = rewire(testModules.A),
- newObj = {};
-
- expect(rewiredModuleA.getMyNumber()).to.be(0);
- rewiredModuleA.__set__("myNumber", 2);
- expect(rewiredModuleA.getMyNumber()).to.be(2);
- rewiredModuleA.__set__("myObj", newObj);
- expect(rewiredModuleA.getMyObj()).to.be(newObj);
- rewiredModuleA.__set__("env", "ENVENV");
- });
- it("should provide the ability to get private vars", function () {
- var rewiredModuleA = rewire(testModules.A);
-
- expect(rewiredModuleA.__get__("myNumber")).to.be(rewiredModuleA.getMyNumber());
- expect(rewiredModuleA.__get__("myObj")).to.be(rewiredModuleA.getMyObj());
- });
- it("should provide the ability to inject mocks", function (done) {
- var rewiredModuleA = rewire(testModules.A),
- mockedFs = {
- readFileSync: function (file) {
- expect(file).to.be("bla.txt");
- done();
- }
- };
-
- rewiredModuleA.__set__("fs", mockedFs);
- rewiredModuleA.readFileSync();
- });
- it("should not influence other modules when injecting mocks", function () {
- var rewiredModuleA = rewire(testModules.A),
- someOtherModule,
- mockedFs = {};
-
- rewiredModuleA.__set__("fs", mockedFs);
- someOtherModule = require(testModules.someOtherModule);
- expect(someOtherModule.fs).not.to.be(mockedFs);
- });
- it("should provide the ability to mock global objects just within the module", function () {
- var rewiredModuleA = rewire(testModules.A),
- rewiredModuleB = rewire(testModules.B),
- consoleMock = {},
- processMock = {},
- newFilename = "myFile.js";
-
- rewiredModuleA.__set__({
- console: consoleMock,
- process: processMock
- });
- rewiredModuleA.__set__("__filename", newFilename);
- rewiredModuleB.__set__({
- console: consoleMock,
- process: processMock
- });
- rewiredModuleB.__set__("__filename", newFilename);
- expect(rewiredModuleA.getConsole()).to.be(consoleMock);
- expect(rewiredModuleB.getConsole()).to.be(consoleMock);
- expect(console).not.to.be(consoleMock);
- expect(rewiredModuleA.getProcess()).to.be(processMock);
- expect(rewiredModuleB.getProcess()).to.be(processMock);
- expect(process).not.to.be(processMock);
- expect(rewiredModuleA.getFilename()).to.be(newFilename);
- expect(rewiredModuleB.getFilename()).to.be(newFilename);
- });
- it("should cache the rewired module", function () {
- var rewired;
-
- rewired = rewire(testModules.someOtherModule);
- expect(require(testModules.A).someOtherModule).to.be(rewired);
- cleanRequireCache();
- rewired = rewire(testModules.someOtherModule, true);
- expect(require(testModules.A).someOtherModule).to.be(rewired);
- });
- it("should not cache the rewired module on demand", function () {
- var rewired;
-
- rewired = rewire(testModules.someOtherModule, false);
- expect(require(testModules.A).someOtherModule).not.to.be(rewired);
- });
- it("should not influence the original node require if nothing has been required within the rewired module", function () {
- rewire(testModules.emptyModule); // nothing happens here because emptyModule doesn't require anything
- expect(require(testModules.A).__set__).to.be(undefined); // if restoring the original node require didn't worked, the module would have a setter
- });
- it("subsequent calls of rewire should always return a new instance", function () {
- expect(rewire(testModules.A)).not.to.be(rewire(testModules.A));
- });
- describe("#reset", function () {
- it("should remove all rewired modules from cache", function () {
- var rewiredModuleA = rewire(testModules.A),
- rewiredModuleB = rewire(testModules.B);
-
- expect(require(testModules.A)).to.be(rewiredModuleA);
- expect(require(testModules.B)).to.be(rewiredModuleB);
- rewire.reset();
- expect(require(testModules.A)).not.to.be(rewiredModuleA);
- expect(require(testModules.B)).not.to.be(rewiredModuleB);
- });
- });
-}); \ No newline at end of file
diff --git a/test/testHelpers/createFakePackageJSON.js b/test/testHelpers/createFakePackageJSON.js
new file mode 100644
index 0000000..dbda04f
--- /dev/null
+++ b/test/testHelpers/createFakePackageJSON.js
@@ -0,0 +1,11 @@
+var fs = require("fs"),
+ pathUtil = require("path"),
+ nodeModulesDir = pathUtil.resolve(__dirname, "../../node_modules");
+
+module.exports = function createFakePackageJSON(done) {
+ var fakePackageJSON = '{ "main": "../../lib/index.js" }';
+
+ fs.mkdir(nodeModulesDir + "/rewire", function onMkDir() {
+ fs.writeFile(nodeModulesDir + "/rewire/package.json", fakePackageJSON, "utf8", done);
+ });
+}; \ No newline at end of file
diff --git a/test/testHelpers/removeFakePackageJSON.js b/test/testHelpers/removeFakePackageJSON.js
new file mode 100644
index 0000000..676339e
--- /dev/null
+++ b/test/testHelpers/removeFakePackageJSON.js
@@ -0,0 +1,9 @@
+var fs = require("fs"),
+ pathUtil = require("path"),
+ nodeModulesDir = pathUtil.resolve(__dirname, "../../node_modules");
+
+module.exports = function removeFakePackageJSON(done) {
+ fs.unlink(nodeModulesDir + "/rewire/package.json", function onPackageJSONUnlink() {
+ fs.rmdir(nodeModulesDir + "/rewire", done);
+ });
+}; \ No newline at end of file
diff --git a/test/testModules/moduleA.js b/test/testModules/moduleA.js
index 87f4949..6e655ab 100644
--- a/test/testModules/moduleA.js
+++ b/test/testModules/moduleA.js
@@ -29,17 +29,11 @@ function readFileSync() {
function checkSomeGlobals() {
if (typeof global === "undefined") {
- //throw new ReferenceError("global is undefined");
- }
- if (typeof process === "undefined") {
- throw new ReferenceError("process is undefined");
+ throw new ReferenceError("global is undefined");
}
if (typeof console === "undefined") {
throw new ReferenceError("console is undefined");
}
- if (typeof Buffer === "undefined") {
- throw new ReferenceError("Buffer is undefined");
- }
if (typeof __filename === "undefined") {
throw new ReferenceError("__filename is undefined");
}
@@ -55,10 +49,6 @@ function getConsole() {
return console;
}
-function getProcess() {
- return process;
-}
-
function getFilename() {
return __filename;
}
@@ -71,6 +61,5 @@ exports.getMyObj = getMyObj;
exports.readFileSync = readFileSync;
exports.checkSomeGlobals = checkSomeGlobals;
exports.getConsole = getConsole;
-exports.getProcess = getProcess;
exports.getFilename = getFilename;
exports.someOtherModule = someOtherModule; \ No newline at end of file
diff --git a/test/testModules/moduleB.js b/test/testModules/moduleB.js
index c9fec13..6e655ab 100644
--- a/test/testModules/moduleB.js
+++ b/test/testModules/moduleB.js
@@ -3,6 +3,7 @@
var someOtherModule = require("./someOtherModule.js"),
myNumber = 0, // copy by value
myObj = {}, // copy by reference
+ env = "bla",
fs = require("fs");
// We need getters and setters for private vars to check if our injected setters and getters actual work
@@ -30,15 +31,9 @@ function checkSomeGlobals() {
if (typeof global === "undefined") {
throw new ReferenceError("global is undefined");
}
- if (typeof process === "undefined") {
- throw new ReferenceError("process is undefined");
- }
if (typeof console === "undefined") {
throw new ReferenceError("console is undefined");
}
- if (typeof Buffer === "undefined") {
- throw new ReferenceError("Buffer is undefined");
- }
if (typeof __filename === "undefined") {
throw new ReferenceError("__filename is undefined");
}
@@ -54,28 +49,17 @@ function getConsole() {
return console;
}
-function getProcess() {
- return process;
-}
-
function getFilename() {
return __filename;
}
-function main() {
-
-}
-
-main.setMyNumber = setMyNumber;
-main.getMyNumber = getMyNumber;
-main.setMyObj = setMyObj;
-main.getMyObj = getMyObj;
-main.readFileSync = readFileSync;
-main.checkSomeGlobals = checkSomeGlobals;
-main.getConsole = getConsole;
-main.getProcess = getProcess;
-main.getFilename = getFilename;
-main.someOtherModule = someOtherModule;
-
// different styles of exports in moduleA.js and moduleB.js
-module.exports = main;
+exports.setMyNumber = setMyNumber;
+exports.getMyNumber = getMyNumber;
+exports.setMyObj = setMyObj;
+exports.getMyObj = getMyObj;
+exports.readFileSync = readFileSync;
+exports.checkSomeGlobals = checkSomeGlobals;
+exports.getConsole = getConsole;
+exports.getFilename = getFilename;
+exports.someOtherModule = someOtherModule; \ No newline at end of file
diff --git a/test/testModules/sharedTestCases.js b/test/testModules/sharedTestCases.js
new file mode 100644
index 0000000..b705e40
--- /dev/null
+++ b/test/testModules/sharedTestCases.js
@@ -0,0 +1,169 @@
+// Don't run code in ES5 strict mode.
+// In case this module was in strict mode, all other modules called by this would also be strict.
+// But when testing if the strict mode is preserved, we must ensure that this module is NOT strict.
+
+var path = require("path"),
+ expect = require("expect.js"),
+ rewire = require("rewire");
+
+var testModules = {
+ A: path.resolve(__dirname, "./moduleA.js"),
+ B: path.resolve(__dirname, "./moduleB.js"),
+ someOtherModule: path.resolve(__dirname, "./someOtherModule.js"),
+ emptyModule: path.resolve(__dirname, "./emptyModule.js"),
+ strictModule: path.resolve(__dirname, "./strictModule.js")
+ };
+
+
+function checkForTypeError(err) {
+ expect(err.constructor).to.be(TypeError);
+}
+
+function cleanRequireCache() {
+ var moduleName,
+ modulePath;
+
+ for (moduleName in testModules) {
+ if (testModules.hasOwnProperty(moduleName)) {
+ modulePath = testModules[moduleName];
+ if (typeof window === "undefined") {
+ delete require.cache[modulePath];
+ } else {
+ if (typeof window.browserifyRequire.modules[modulePath]._cached === "object") {
+ delete window.browserifyRequire.modules[modulePath]._cached;
+ }
+ }
+ }
+ }
+}
+
+describe("rewire " + (typeof window === "undefined"? "(node.js)": "(browser)"), function () {
+ beforeEach(cleanRequireCache); // ensuring a clean test environment
+ it("should work like require()", function () {
+ expect(rewire("./moduleA.js")).to.be(require("./moduleA.js"));
+ cleanRequireCache();
+ expect(rewire("../testModules/moduleA.js")).to.be(require("../testModules/moduleA.js"));
+ cleanRequireCache();
+ expect(rewire("./moduleA.js")).to.be(require("./moduleA.js"));
+ });
+ it("should modify the module so it provides a __set__ - function", function () {
+ expect(rewire("./moduleA.js").__set__).to.be.a(Function);
+ expect(rewire("./moduleB.js").__set__).to.be.a(Function);
+ });
+ it("should modify the module so it provides a __get__ - function", function () {
+ expect(rewire("./moduleA.js").__get__).to.be.a(Function);
+ expect(rewire("./moduleB.js").__get__).to.be.a(Function);
+ });
+ it("should not influence other modules", function () {
+ var rewiredModuleA = rewire("./moduleA.js");
+
+ expect(require("./someOtherModule.js").__set__).to.be(undefined);
+ expect(require("./someOtherModule.js").__get__).to.be(undefined);
+ expect(require("fs").__set__).to.be(undefined);
+ expect(require("fs").__get__).to.be(undefined);
+ });
+ it("should not influence global objects by default", function () {
+ // This should throw no exception
+ rewire("./moduleA.js").checkSomeGlobals();
+ rewire("./moduleB.js").checkSomeGlobals();
+ });
+ it("should provide the ability to set private vars", function () {
+ var rewiredModuleA = rewire("./moduleA.js"),
+ newObj = {};
+
+ expect(rewiredModuleA.getMyNumber()).to.be(0);
+ rewiredModuleA.__set__("myNumber", 2);
+ expect(rewiredModuleA.getMyNumber()).to.be(2);
+ rewiredModuleA.__set__("myObj", newObj);
+ expect(rewiredModuleA.getMyObj()).to.be(newObj);
+ rewiredModuleA.__set__("env", "ENVENV");
+ });
+ it("should provide the ability to get private vars", function () {
+ var rewiredModuleA = rewire("./moduleA.js");
+
+ expect(rewiredModuleA.__get__("myNumber")).to.be(rewiredModuleA.getMyNumber());
+ expect(rewiredModuleA.__get__("myObj")).to.be(rewiredModuleA.getMyObj());
+ });
+ it("should provide the ability to inject mocks", function (done) {
+ var rewiredModuleA = rewire("./moduleA.js"),
+ mockedFs = {
+ readFileSync: function (file) {
+ expect(file).to.be("bla.txt");
+ done();
+ }
+ };
+
+ rewiredModuleA.__set__("fs", mockedFs);
+ rewiredModuleA.readFileSync();
+ });
+ it("should not influence other modules when injecting mocks", function () {
+ var rewiredModuleA = rewire("./moduleA.js"),
+ someOtherModule,
+ mockedFs = {};
+
+ rewiredModuleA.__set__("fs", mockedFs);
+ someOtherModule = require("./someOtherModule.js");
+ expect(someOtherModule.fs).not.to.be(mockedFs);
+ });
+ it("should provide the ability to mock global objects just within the module", function () {
+ var rewiredModuleA = rewire("./moduleA.js"),
+ rewiredModuleB = rewire("./moduleB.js"),
+ consoleMock = {},
+ newFilename = "myFile.js";
+
+ rewiredModuleA.__set__({
+ console: consoleMock
+ });
+ rewiredModuleA.__set__("__filename", newFilename);
+ rewiredModuleB.__set__({
+ console: consoleMock
+ });
+ rewiredModuleB.__set__("__filename", newFilename);
+ expect(rewiredModuleA.getConsole()).to.be(consoleMock);
+ expect(rewiredModuleB.getConsole()).to.be(consoleMock);
+ expect(console).not.to.be(consoleMock);
+ expect(rewiredModuleA.getFilename()).to.be(newFilename);
+ expect(rewiredModuleB.getFilename()).to.be(newFilename);
+ });
+ it("should cache the rewired module", function () {
+ var rewired;
+
+ rewired = rewire("./someOtherModule.js");
+ expect(require("./moduleA.js").someOtherModule).to.be(rewired);
+ cleanRequireCache();
+ rewired = rewire("./someOtherModule.js", true);
+ expect(require("./moduleA.js").someOtherModule).to.be(rewired);
+ });
+ it("should not cache the rewired module on demand", function () {
+ var rewired;
+
+ rewired = rewire("./someOtherModule.js", false);
+ expect(require("./moduleA.js").someOtherModule).not.to.be(rewired);
+ });
+ it("should not influence the original node require if nothing has been required within the rewired module", function () {
+ rewire("./emptyModule.js"); // nothing happens here because emptyModule doesn't require anything
+ expect(require("./moduleA.js").__set__).to.be(undefined); // if restoring the original node require didn't worked, the module would have a setter
+ });
+ it("subsequent calls of rewire should always return a new instance", function () {
+ expect(rewire("./moduleA.js")).not.to.be(rewire("./moduleA.js"));
+ });
+ it("should preserve the strict mode", function () {
+ var strictModule = rewire("./strictModule.js");
+
+ expect(function () {
+ strictModule.doSomethingUnstrict();
+ }).to.throwException(checkForTypeError);
+ });
+ describe("#reset", function () {
+ it("should remove all rewired modules from cache", function () {
+ var rewiredModuleA = rewire("./moduleA.js"),
+ rewiredModuleB = rewire("./moduleB.js");
+
+ expect(require("./moduleA.js")).to.be(rewiredModuleA);
+ expect(require("./moduleB.js")).to.be(rewiredModuleB);
+ rewire.reset();
+ expect(require("./moduleA.js")).not.to.be(rewiredModuleA);
+ expect(require("./moduleB.js")).not.to.be(rewiredModuleB);
+ });
+ });
+}); \ No newline at end of file
diff --git a/test/testModules/strictModule.js b/test/testModules/strictModule.js
new file mode 100644
index 0000000..140dd2a
--- /dev/null
+++ b/test/testModules/strictModule.js
@@ -0,0 +1,7 @@
+"use strict"; // run code in ES5 strict mode
+
+function doSomethingUnstrict() {
+ var caller = arguments.callee.caller; // this should throw an error as a proof that strict mode is on
+}
+
+exports.doSomethingUnstrict = doSomethingUnstrict; \ No newline at end of file