Skip to content
This repository has been archived by the owner on Apr 30, 2024. It is now read-only.

Implemented resolving of relative module names to absolute paths #9

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 43 additions & 11 deletions mockery.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,14 @@
*/

var m = require('module'),
requireLike = require('require-like'),
registeredMocks = {},
registeredSubstitutes = {},
registeredAllowables = {},
originalLoader = null,
warnIfUnregistered = true;
resolve = null,
warnIfUnregistered = true,
resolveLikeFile = false;

/*
* The perils of using internal functions. The Node-internal _resolveFilename
Expand All @@ -62,41 +65,63 @@ function resolveFilename(request, parent) {
* since it will replace that when mockery is enabled.
*/
function hookedLoader(request, parent, isMain) {
var subst, allow, file;
var subst, allow, file, cachedEntry;

if (!originalLoader) {
throw new Error("Loader has not been hooked");
}

if (registeredMocks.hasOwnProperty(request)) {
return registeredMocks[request];
} else if (registeredSubstitutes.hasOwnProperty(request)) {
subst = registeredSubstitutes[request];
if (resolveLikeFile) {
cachedEntry = file = resolveFilename(request, parent);
} else {
cachedEntry = request;
}
if (registeredMocks.hasOwnProperty(cachedEntry)) {
return registeredMocks[cachedEntry];
} else if (registeredSubstitutes.hasOwnProperty(cachedEntry)) {
subst = registeredSubstitutes[cachedEntry];
if (!subst.module && subst.name) {
subst.module = originalLoader(subst.name, parent, isMain);
}
if (!subst.module) {
throw new Error("Misconfigured substitute for '" + request + "'");
throw new Error("Misconfigured substitute for '" + cachedEntry + "'");
}
return subst.module;
} else {
if (registeredAllowables.hasOwnProperty(request)) {
allow = registeredAllowables[request];
if (registeredAllowables.hasOwnProperty(cachedEntry)) {
allow = registeredAllowables[cachedEntry];
if (allow.unhook) {
file = resolveFilename(request, parent);
if (!file) {
file = resolveFilename(request, parent);
}
if (file.indexOf('/') !== -1 && allow.paths.indexOf(file) === -1) {
allow.paths.push(file);
}
}
} else {
if (warnIfUnregistered) {
console.warn("WARNING: loading non-allowed module: " + request);
console.warn("WARNING: loading non-allowed module: " + cachedEntry);
}
}
return originalLoader(request, parent, isMain);
}
}

function resolveLike(file) {
var resolver;
resolveLikeFile = file;
if (resolveLikeFile) {
resolver = requireLike(resolveLikeFile);
resolve = function(mod) {
return resolver.resolve(mod);
}
} else {
resolve = function(mod) {
return mod;
}
}
}

/*
* Enables mockery by hooking subsequent 'require' invocations. Note that *all*
* 'require' invocations will be hooked until 'disable' is called. Calling this
Expand Down Expand Up @@ -142,6 +167,7 @@ function warnOnUnregistered(enable) {
* for anything not mocked and subsequently invoked.
*/
function registerMock(mod, mock) {
mod = resolve(mod);
if (registeredMocks.hasOwnProperty(mod)) {
console.warn("WARNING: Replacing existing mock for module: " + mod);
}
Expand All @@ -154,6 +180,7 @@ function registerMock(mod, mock) {
* falling back to the original 'require' behaviour).
*/
function deregisterMock(mod) {
mod = resolve(mod);
if (registeredMocks.hasOwnProperty(mod)) {
delete registeredMocks[mod];
}
Expand All @@ -166,6 +193,7 @@ function deregisterMock(mod) {
* a mock implementation is itself implemented as a module.
*/
function registerSubstitute(mod, subst) {
mod = resolve(mod);
if (registeredSubstitutes.hasOwnProperty(mod)) {
console.warn("WARNING: Replacing existing substitute for module: " + mod);
}
Expand All @@ -180,6 +208,7 @@ function registerSubstitute(mod, subst) {
* default, means falling back to the original 'require' behaviour).
*/
function deregisterSubstitute(mod) {
mod = resolve(mod);
if (registeredSubstitutes.hasOwnProperty(mod)) {
delete registeredSubstitutes[mod];
}
Expand All @@ -195,6 +224,7 @@ function deregisterSubstitute(mod) {
* it is deregistered.
*/
function registerAllowable(mod, unhook) {
mod = resolve(mod);
registeredAllowables[mod] = {
unhook: !!unhook,
paths: []
Expand All @@ -207,6 +237,7 @@ function registerAllowable(mod, unhook) {
* mock or substitute is registered for that module.
*/
function deregisterAllowable(mod) {
mod = resolve(mod);
if (registeredAllowables.hasOwnProperty(mod)) {
var allow = registeredAllowables[mod];
if (allow.unhook) {
Expand Down Expand Up @@ -249,3 +280,4 @@ exports.deregisterMock = deregisterMock;
exports.deregisterSubstitute = deregisterSubstitute;
exports.deregisterAllowable = deregisterAllowable;
exports.deregisterAll = deregisterAll;
exports.resolveLike = resolveLike;
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
"engines": {
"node": ">=0.4.5"
},
"dependencies": {},
"dependencies": {
"require-like": "0.1.x"
},
"devDependencies": {
"nodeunit" : "0.6.x",
"sinon" : "1.2.x"
Expand Down