Skip to content

Commit

Permalink
Fix problems when global objects like JSON, etc. have been rewired
Browse files Browse the repository at this point in the history
Fixes #40
  • Loading branch information
jhnns committed Feb 23, 2015
1 parent 52e914d commit e70efd1
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 14 deletions.
28 changes: 21 additions & 7 deletions lib/__set__.js
Expand Up @@ -12,19 +12,30 @@
function __set__() {
arguments.varName = arguments[0];
arguments.varValue = arguments[1];
// Saving references to global objects and functions. Thus a test may even change these variables
// without interfering with rewire().
// @see https://github.com/jhnns/rewire/issues/40
arguments.refs = arguments[2] || {
isArray: Array.isArray,
TypeError: TypeError,
stringify: JSON.stringify
// We can't save eval() because eval() is a *special* global function
// That's why it can't be re-assigned in strict mode
//eval: eval
};
arguments.src = "";
arguments.revertArgs = [];

if (typeof arguments[0] === "object" && arguments.length === 1) {
if (typeof arguments[0] === "object") {
arguments.env = arguments.varName;
if (!arguments.env || Array.isArray(arguments.env)) {
throw new TypeError("__set__ expects an object as env");
if (!arguments.env || arguments.refs.isArray(arguments.env)) {
throw new arguments.refs.TypeError("__set__ expects an object as env");
}
arguments.revertArgs[0] = {};
for (arguments.varName in arguments.env) {
if (arguments.env.hasOwnProperty(arguments.varName)) {
arguments.varValue = arguments.env[arguments.varName];
arguments.src += arguments.varName + " = arguments.env[" + JSON.stringify(arguments.varName) + "]; ";
arguments.src += arguments.varName + " = arguments.env[" + arguments.refs.stringify(arguments.varName) + "]; ";
try {
// Allow tests to mock implicit globals
// @see https://github.com/jhnns/rewire/issues/35
Expand All @@ -34,9 +45,9 @@ function __set__() {
}
}
}
} else if (typeof arguments.varName === "string" && arguments.length === 2) {
} else if (typeof arguments.varName === "string") {
if (!arguments.varName) {
throw new TypeError("__set__ expects a non-empty string as a variable name");
throw new arguments.refs.TypeError("__set__ expects a non-empty string as a variable name");
}
arguments.src = arguments.varName + " = arguments.varValue;";
try {
Expand All @@ -47,9 +58,12 @@ function __set__() {
arguments.revertArgs = [arguments.varName, undefined];
}
} else {
throw new TypeError("__set__ expects an environment object or a non-empty string as a variable name");
throw new arguments.refs.TypeError("__set__ expects an environment object or a non-empty string as a variable name");
}

// Passing our saved references on to the revert function
arguments.revertArgs[2] = arguments.refs;

eval(arguments.src);

return function (revertArgs) {
Expand Down
8 changes: 1 addition & 7 deletions test/__set__.test.js
Expand Up @@ -121,11 +121,5 @@ describe("__set__", function () {
expect(function () {
moduleFake.__set__(function () {});
}).to.throwException(expectTypeError);
expect(function () {
moduleFake.__set__({}, true); // misfitting number of params
}).to.throwException(expectTypeError);
expect(function () {
moduleFake.__set__("someVar"); // misfitting number of params
}).to.throwException(expectTypeError);
});
});
});
13 changes: 13 additions & 0 deletions test/testModules/sharedTestCases.js
Expand Up @@ -337,4 +337,17 @@ describe("rewire " + (typeof testEnv === "undefined"? "(node)": "(" + testEnv +
}
});

it("should be possible to mock and revert JSON.parse (see #40)", function () {
var moduleA = rewire("./moduleA.js"),
revert;

revert = moduleA.__set__({
JSON: {
parse: function () { return true; }
}
});

revert();
});

});

0 comments on commit e70efd1

Please sign in to comment.