mock-require
Advanced tools
Comparing version 2.0.2 to 3.0.0
65
index.js
@@ -1,18 +0,22 @@ | ||
var Module = require('module') | ||
, dirname = require('path').dirname | ||
, join = require('path').join | ||
, resolve = require('path').resolve | ||
, callerId = require('caller-id') | ||
, originalLoader = Module._load | ||
, mockExports = {} | ||
, pendingMockExports = {} | ||
; | ||
'use strict'; | ||
const Module = require('module'); | ||
const dirname = require('path').dirname; | ||
const join = require('path').join; | ||
const resolve = require('path').resolve; | ||
const getCallerFile = require('get-caller-file'); | ||
const originalLoader = Module._load; | ||
let mockExports = {}; | ||
let pendingMockExports = {}; | ||
Module._load = function(request, parent) { | ||
var fullFilePath = getFullPath(request, parent.filename); | ||
if (!parent) return originalLoader.apply(this, arguments); | ||
if (pendingMockExports.hasOwnProperty(fullFilePath)){ | ||
const fullFilePath = getFullPath(request, parent.filename); | ||
if (pendingMockExports.hasOwnProperty(fullFilePath)) { | ||
mockExports[fullFilePath] = typeof pendingMockExports[fullFilePath] === 'string' ? | ||
require(pendingMockExports[fullFilePath]) : | ||
pendingMockExports[fullFilePath]; | ||
require(pendingMockExports[fullFilePath]) : | ||
pendingMockExports[fullFilePath]; | ||
@@ -28,3 +32,3 @@ delete pendingMockExports[fullFilePath]; | ||
function startMocking(path, mockExport) { | ||
var calledFrom = callerId.getData().filePath; | ||
const calledFrom = getCallerFile(); | ||
@@ -39,4 +43,4 @@ if (typeof mockExport === 'string') { | ||
function stopMocking(path) { | ||
var calledFrom = callerId.getData().filePath; | ||
var fullPath = getFullPath(path, calledFrom); | ||
const calledFrom = getCallerFile(); | ||
const fullPath = getFullPath(path, calledFrom); | ||
delete pendingMockExports[fullPath]; | ||
@@ -52,3 +56,3 @@ delete mockExports[fullPath]; | ||
function reRequire(path) { | ||
var module = getFullPath(path, callerId.getData().filePath); | ||
const module = getFullPath(path, getCallerFile()); | ||
delete require.cache[require.resolve(module)]; | ||
@@ -62,6 +66,6 @@ return require(module); | ||
return Module.globalPaths | ||
.map(function(nodePath) { | ||
.map((nodePath) => { | ||
return resolve(process.cwd(), nodePath) + '/'; | ||
}) | ||
.some(function(fullNodePath) { | ||
.some((fullNodePath) => { | ||
return resolvedPath.indexOf(fullNodePath) === 0; | ||
@@ -72,11 +76,13 @@ }); | ||
function getFullPath(path, calledFrom) { | ||
var resolvedPath; | ||
let resolvedPath; | ||
try { | ||
resolvedPath = require.resolve(path); | ||
} catch(e) { } | ||
} catch (e) { | ||
// do nothing | ||
} | ||
var isLocalModule = /^\.{1,2}[/\\]?/.test(path); | ||
var isInPath = isInNodePath(resolvedPath); | ||
var isExternal = !isLocalModule && /[/\\]node_modules[/\\]/.test(resolvedPath); | ||
var isSystemModule = resolvedPath === path; | ||
const isLocalModule = /^\.{1,2}[/\\]?/.test(path); | ||
const isInPath = isInNodePath(resolvedPath); | ||
const isExternal = !isLocalModule && /[/\\]node_modules[/\\]/.test(resolvedPath); | ||
const isSystemModule = resolvedPath === path; | ||
@@ -91,13 +97,12 @@ if (isExternal || isSystemModule || isInPath) { | ||
var localModuleName = join(dirname(calledFrom), path); | ||
const localModuleName = join(dirname(calledFrom), path); | ||
try { | ||
return Module._resolveFilename(localModuleName); | ||
} catch (e) { | ||
if (isModuleNotFoundError(e)) { return localModuleName; } | ||
else { throw e; } | ||
if (isModuleNotFoundError(e)) { return localModuleName; } else { throw e; } | ||
} | ||
} | ||
function isModuleNotFoundError(e){ | ||
return e.code && e.code === 'MODULE_NOT_FOUND' | ||
function isModuleNotFoundError(e) { | ||
return e.code && e.code === 'MODULE_NOT_FOUND'; | ||
} | ||
@@ -104,0 +109,0 @@ |
{ | ||
"name": "mock-require", | ||
"version": "2.0.2", | ||
"version": "3.0.0", | ||
"description": "Simple, intuitive mocking of Node.js modules.", | ||
@@ -10,7 +10,12 @@ "main": "index.js", | ||
"dependencies": { | ||
"caller-id": "^0.1.0" | ||
"caller-id": "^0.1.0", | ||
"get-caller-file": "^1.0.2" | ||
}, | ||
"devDependencies": {}, | ||
"devDependencies": { | ||
"eslint": "^4.15.0", | ||
"mocha": "^4.1.0" | ||
}, | ||
"scripts": { | ||
"test": "NODE_PATH=test/node-path node test/runner" | ||
"lint": "eslint .", | ||
"test": "NODE_PATH=test/node-path mocha ./test/runner" | ||
}, | ||
@@ -39,4 +44,4 @@ "repository": { | ||
"engines": { | ||
"node": ">=0.10" | ||
"node": ">=4.3.0" | ||
} | ||
} |
@@ -0,3 +1,5 @@ | ||
'use strict'; | ||
module.exports = function() { | ||
return 'exported function'; | ||
}; |
@@ -0,6 +1,8 @@ | ||
'use strict'; | ||
module.exports = { | ||
mocked: false, | ||
fn: function() { | ||
fn() { | ||
return 'exported object'; | ||
} | ||
}; |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
module.exports = 'root'; |
@@ -1,3 +0,5 @@ | ||
var a = require('module-a') | ||
'use strict'; | ||
const a = require('module-a'); | ||
module.exports = { | ||
@@ -4,0 +6,0 @@ id: 'local-module-a', |
@@ -1,3 +0,5 @@ | ||
var a = require('./module-a') | ||
'use strict'; | ||
const a = require('./module-a'); | ||
module.exports = { | ||
@@ -4,0 +6,0 @@ id: 'local-module-b', |
@@ -1,3 +0,5 @@ | ||
var x = require('../x') | ||
'use strict'; | ||
const x = require('../x'); | ||
module.exports = { | ||
@@ -4,0 +6,0 @@ id: 'local-module-c', |
@@ -0,3 +1,5 @@ | ||
'use strict'; | ||
{ | ||
id: 'node-path-set' | ||
id: 'node-path-set'; | ||
} |
@@ -1,225 +0,195 @@ | ||
var assert = require('assert') | ||
, mock = require('../index') | ||
; | ||
'use strict'; | ||
(function shouldMockAndUnmock() { | ||
mock('./exported-fn', function() { | ||
return 'mocked fn'; | ||
const assert = require('assert'); | ||
const mock = require('..'); | ||
describe('Mock Require', () => { | ||
afterEach(() => { | ||
mock.stopAll(); | ||
}); | ||
mock.stop('./exported-fn'); | ||
it('should mock a required function', () => { | ||
mock('./exported-fn', () => { | ||
return 'mocked fn'; | ||
}); | ||
var fn = require('./exported-fn'); | ||
assert.equal(fn(), 'exported function'); | ||
})(); | ||
(function shouldMockRequiredFn() { | ||
mock('./exported-fn', function() { | ||
return 'mocked fn'; | ||
assert.equal(require('./exported-fn')(), 'mocked fn'); | ||
}); | ||
var fn = require('./exported-fn'); | ||
assert.equal(fn(), 'mocked fn'); | ||
it('should mock a required object', () => { | ||
mock('./exported-obj', { | ||
mocked: true, | ||
fn: function() { | ||
return 'mocked obj'; | ||
} | ||
}); | ||
mock.stop('./exported-fn'); | ||
let obj = require('./exported-obj'); | ||
assert.equal(obj.fn(), 'mocked obj'); | ||
assert.equal(obj.mocked, true); | ||
fn = require('./exported-fn'); | ||
assert.equal(fn(), 'exported function'); | ||
})(); | ||
mock.stop('./exported-obj'); | ||
(function shouldMockRequiredObj() { | ||
mock('./exported-obj', { | ||
mocked: true, | ||
fn: function() { | ||
return 'mocked obj'; | ||
} | ||
obj = require('./exported-obj'); | ||
assert.equal(obj.fn(), 'exported object'); | ||
assert.equal(obj.mocked, false); | ||
}); | ||
var obj = require('./exported-obj'); | ||
assert.equal(obj.fn(), 'mocked obj'); | ||
assert.equal(obj.mocked, true); | ||
it('should unmock', () => { | ||
mock('./exported-fn', () => { | ||
return 'mocked fn'; | ||
}); | ||
mock.stop('./exported-obj'); | ||
mock.stop('./exported-fn'); | ||
obj = require('./exported-obj'); | ||
assert.equal(obj.fn(), 'exported object'); | ||
assert.equal(obj.mocked, false); | ||
})(); | ||
const fn = require('./exported-fn'); | ||
assert.equal(fn(), 'exported function'); | ||
}); | ||
(function shouldMockRootLib() { | ||
mock('.', { mocked: true }); | ||
assert.equal(require('.').mocked, true); | ||
mock.stop('.'); | ||
})(); | ||
it('should mock a root file', () => { | ||
mock('.', { mocked: true }); | ||
assert.equal(require('.').mocked, true); | ||
}); | ||
(function shouldMockStandardLibs() { | ||
mock('fs', { mocked: true }); | ||
it('should mock a standard lib', () => { | ||
mock('fs', { mocked: true }); | ||
var fs = require('fs'); | ||
assert.equal(fs.mocked, true); | ||
mock.stop('fs'); | ||
})(); | ||
const fs = require('fs'); | ||
assert.equal(fs.mocked, true); | ||
}); | ||
(function shouldMockExternalLibs() { | ||
mock('caller-id', { mocked: true }); | ||
it('should mock an external lib', () => { | ||
mock('mocha', { mocked: true }); | ||
var callerId = require('caller-id'); | ||
assert.equal(callerId.mocked, true); | ||
mock.stop('caller-id'); | ||
})(); | ||
const mocha = require('mocha'); | ||
assert.equal(mocha.mocked, true); | ||
}); | ||
(function shouldRequireMockedLib() { | ||
mock('fs', 'path'); | ||
it('should one lib with another', () => { | ||
mock('fs', 'path'); | ||
assert.equal(require('fs'), require('path')); | ||
assert.equal(require('fs'), require('path')); | ||
mock.stop('fs'); | ||
mock('./exported-fn', './exported-obj'); | ||
assert.equal(require('./exported-fn'), require('./exported-obj')); | ||
}); | ||
mock('./exported-fn', './exported-obj'); | ||
assert.equal(require('./exported-fn'), require('./exported-obj')); | ||
mock.stop('./exported-fn'); | ||
})(); | ||
it('should support re-requiring', () => { | ||
assert.equal(mock.reRequire('.'), 'root'); | ||
}); | ||
(function shouldReRequireMockedRootLib() { | ||
assert.equal(mock.reRequire('.'), 'root'); | ||
})(); | ||
it('should cascade mocks', () => { | ||
mock('path', { mocked: true }); | ||
mock('fs', 'path'); | ||
(function mocksShouldCascade() { | ||
mock('path', { mocked: true }); | ||
mock('fs', 'path'); | ||
const fs = require('fs'); | ||
assert.equal(fs.mocked, true); | ||
}); | ||
var fs = require('fs'); | ||
assert.equal(fs.mocked, true); | ||
mock.stop('fs'); | ||
mock.stop('path'); | ||
})(); | ||
it('should never require the real lib when mocking it', () => { | ||
mock('./throw-exception', {}); | ||
require('./throw-exception'); | ||
}); | ||
(function mocksShouldNeverRequireTheOriginal() { | ||
mock('./throw-exception', {}); | ||
require('./throw-exception'); | ||
mock.stop('./throw-exception'); | ||
})(); | ||
it('should mock libs required elsewhere', () => { | ||
mock('./throw-exception', {}); | ||
require('./throw-exception-runner'); | ||
}); | ||
(function mocksShouldWorkWhenRequiredFromOtherFile() { | ||
mock('./throw-exception', {}); | ||
require('./throw-exception-runner'); | ||
mock.stop('./throw-exception'); | ||
})(); | ||
it('should only load the mocked lib when it is required', () => { | ||
mock('./throw-exception', './throw-exception-when-required'); | ||
try { | ||
require('./throw-exception-runner'); | ||
throw new Error('this line should never be executed.'); | ||
} catch (error) { | ||
assert.equal(error.message, 'this should run when required'); | ||
} | ||
}); | ||
(function shouldLoadMockedLibOnlyWhenRequired() { | ||
mock('./throw-exception', './throw-exception-when-required'); | ||
try{ | ||
require('./throw-exception-runner') | ||
} | ||
catch (error) { | ||
assert.equal(e.message, 'this should run when required') | ||
} | ||
mock.stopAll(); | ||
})(); | ||
it('should stop all mocks', () => { | ||
mock('fs', {}); | ||
mock('path', {}); | ||
const fsMock = require('fs'); | ||
const pathMock = require('path'); | ||
(function shouldUnregisterAllMocks() { | ||
mock('fs', {}); | ||
mock('path', {}); | ||
var fsMock = require('fs'); | ||
var pathMock = require('path'); | ||
mock.stopAll(); | ||
mock.stopAll(); | ||
assert.notEqual(require('fs'), fsMock); | ||
assert.notEqual(require('path'), pathMock); | ||
}); | ||
assert.notEqual(require('fs'), fsMock); | ||
assert.notEqual(require('path'), pathMock); | ||
})(); | ||
it('should mock a module that does not exist', () => { | ||
mock('a', { id: 'a' }); | ||
(function shouldRegisterMockForExternalModuleThatIsNotFound() { | ||
mock('a', {id: 'a'}); | ||
assert.equal(require('a').id, 'a'); | ||
}); | ||
assert.equal(require('a').id, 'a'); | ||
it('should mock multiple modules that do not exist', () => { | ||
mock('a', { id: 'a' }); | ||
mock('b', { id: 'b' }); | ||
mock('c', { id: 'c' }); | ||
mock.stopAll(); | ||
})(); | ||
assert.equal(require('a').id, 'a'); | ||
assert.equal(require('b').id, 'b'); | ||
assert.equal(require('c').id, 'c'); | ||
}); | ||
(function shouldRegisterMultipleMocksForExternalModulesThatAreNotFound() { | ||
mock('a', {id: 'a'}); | ||
mock('b', {id: 'b'}); | ||
mock('c', {id: 'c'}); | ||
it('should mock a local file that does not exist', () => { | ||
mock('./a', { id: 'a' }); | ||
assert.equal(require('./a').id, 'a'); | ||
assert.equal(require('a').id, 'a'); | ||
assert.equal(require('b').id, 'b'); | ||
assert.equal(require('c').id, 'c'); | ||
mock('../a', { id: 'a' }); | ||
assert.equal(require('../a').id, 'a'); | ||
}); | ||
mock.stopAll(); | ||
})(); | ||
it('should mock a local file required elsewhere', () => { | ||
mock('./x', { id: 'x' }); | ||
assert.equal(require('./nested/module-c').dependentOn.id, 'x'); | ||
}); | ||
(function shouldRegisterMockForLocalModuleThatIsNotFound() { | ||
mock('./a', {id: 'a'}); | ||
it('should mock multiple local files that do not exist', () => { | ||
mock('./a', { id: 'a' }); | ||
mock('./b', { id: 'b' }); | ||
mock('./c', { id: 'c' }); | ||
assert.equal(require('./a').id, 'a'); | ||
assert.equal(require('./a').id, 'a'); | ||
assert.equal(require('./b').id, 'b'); | ||
assert.equal(require('./c').id, 'c'); | ||
}); | ||
mock.stopAll(); | ||
})(); | ||
it('should unmock a module that is not found', () => { | ||
const moduleName = 'module-that-is-not-installed'; | ||
(function shouldRegisterMockForLocalModuleThatIsNotFound_2() { | ||
mock('../a', {id: 'a'}); | ||
mock(moduleName, { mocked: true }); | ||
mock.stop(moduleName); | ||
assert.equal(require('../a').id, 'a'); | ||
try { | ||
require(moduleName); | ||
throw new Error('this line should never be executed.'); | ||
} catch (e) { | ||
assert.equal(e.code, 'MODULE_NOT_FOUND'); | ||
} | ||
}); | ||
mock.stopAll(); | ||
})(); | ||
it('should differentiate between local files and external modules with the same name', () => { | ||
mock('module-a', { id: 'external-module-a' }); | ||
(function shouldRegisterMockForLocalModuleThatIsNotFoundAtCorrectPath() { | ||
mock('./x', {id: 'x'}); | ||
const b = require('./module-b'); | ||
assert.equal(require('./nested/module-c').dependentOn.id, 'x'); | ||
assert.equal(b.dependentOn.id, 'local-module-a'); | ||
assert.equal(b.dependentOn.dependentOn.id, 'external-module-a'); | ||
}); | ||
mock.stopAll(); | ||
})(); | ||
it('should mock files in the node path by the full path', () => { | ||
assert.equal(process.env.NODE_PATH, 'test/node-path'); | ||
(function shouldRegisterMultipleMocksForLocalModulesThatAreNotFound() { | ||
mock('./a', {id: 'a'}); | ||
mock('./b', {id: 'b'}); | ||
mock('./c', {id: 'c'}); | ||
mock('in-node-path', { id: 'in-node-path' }); | ||
assert.equal(require('./a').id, 'a'); | ||
assert.equal(require('./b').id, 'b'); | ||
assert.equal(require('./c').id, 'c'); | ||
const b = require('in-node-path'); | ||
const c = require('./node-path/in-node-path'); | ||
mock.stopAll(); | ||
})(); | ||
assert.equal(b.id, 'in-node-path'); | ||
assert.equal(c.id, 'in-node-path'); | ||
(function shouldUnRegisterMockForModuleThatIsNotFound() { | ||
var moduleName = 'module-that-is-not-installed'; | ||
mock(moduleName, {mocked: true}); | ||
mock.stop(moduleName); | ||
try{ | ||
require(moduleName) | ||
} catch (e) { | ||
assert.equal(e.code, 'MODULE_NOT_FOUND') | ||
} | ||
})(); | ||
(function shouldLoadMockedExternalModuleWhenLocalModuleHasSameName() { | ||
mock('module-a', {id: 'external-module-a'}); | ||
var b = require('./module-b') | ||
assert.equal(b.dependentOn.id, 'local-module-a') | ||
assert.equal(b.dependentOn.dependentOn.id, 'external-module-a') | ||
mock.stopAll(); | ||
})(); | ||
(function shouldMockFilesInNodePathByFullPath() { | ||
mock('in-node-path', {id: 'in-node-path'}); | ||
var b = require('in-node-path') | ||
var c = require('./node-path/in-node-path'); | ||
assert.equal(b.id, 'in-node-path'); | ||
assert.equal(c.id, 'in-node-path'); | ||
assert.equal(b, c); | ||
mock.stopAll(); | ||
})(); | ||
console.log('All tests pass!'); | ||
assert.equal(b, c); | ||
}); | ||
}); |
@@ -0,1 +1,4 @@ | ||
'use strict'; | ||
require('./throw-exception'); | ||
delete require.cache[__filename]; |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
throw new Error('this should run when required'); |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
throw new Error('this should never run'); |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
47806
20
2
2
274
13
1
+ Addedget-caller-file@^1.0.2
+ Addedget-caller-file@1.0.3(transitive)