rewiremock
Version:
Advanced dependency mocking device.
380 lines (315 loc) • 9.65 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.cleanup = exports.removePlugin = exports.addPlugin = exports.mockModule = undefined;
var _promise = require('babel-runtime/core-js/promise');
var _promise2 = _interopRequireDefault(_promise);
var _keys = require('babel-runtime/core-js/object/keys');
var _keys2 = _interopRequireDefault(_keys);
var _assign = require('babel-runtime/core-js/object/assign');
var _assign2 = _interopRequireDefault(_assign);
var _module = require('./module');
var _module2 = _interopRequireDefault(_module);
var _wipeCache = require('./wipeCache');
var _wipeCache2 = _interopRequireDefault(_wipeCache);
var _scope = require('./scope');
var _scope2 = _interopRequireDefault(_scope);
var _globals = require('./globals');
var _plugins = require('./plugins');
var _mocks = require('./mocks');
var _mock = require('./mock');
var _mock2 = _interopRequireDefault(_mock);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var parentModule = (0, _module.getModuleParent)(module);
var mockScope = null;
var scope = function scope() {
return (0, _globals.setScope)(mockScope);
};
var updateScope = function updateScope() {
var parentScope = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
mockScope = (0, _scope2.default)(parentScope, parentModule);
scope();
};
updateScope();
/** main **/
/**
* @name rewiremock
* @param {String|Function} module name
* @return {ModuleMock}
*/
function mockModule(moduleName) {
scope();
if (typeof moduleName === 'function') {
return (0, _plugins.onMockCreate)(new _mock2.default((0, _mocks.getAsyncMock)(moduleName, parentModule)));
} else {
var name = (0, _plugins.convertName)(moduleName, parentModule);
(0, _mocks.resetMock)(name);
return (0, _plugins.onMockCreate)(new _mock2.default((0, _mocks.getMock)(name)));
}
}
mockModule.getMock = function (module) {
var moduleName = module;
if (typeof moduleName === 'function') {
moduleName = (0, _mocks.getAsyncModuleName)(moduleName, parentModule);
} else {
moduleName = (0, _plugins.convertName)(moduleName, parentModule);
}
var mock = (0, _mocks.getMock)(moduleName);
if (mock) {
return new _mock2.default(mock);
}
return null;
};
/**
* @name rewiremock.resolve
* @param {String} module name
* @return {String} converted module name
*/
mockModule.resolve = function (module) {
scope();
return (0, _plugins.convertName)(module, parentModule);
};
/** flags **/
/**
* Activates module isolation
* @param {Object} [options]
* @param {Boolean} [options.noAutoPassBy] excludes mocked modules to a isolation scope. Use it with mock.callThrough.
* @param {Boolean} [options.noParentPassBy] disable allowing any module, with allowed parent
*/
mockModule.isolation = function () {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
mockScope.isolation = (0, _assign2.default)({}, options);
return mockModule;
};
/**
* Deactivates isolation
*/
mockModule.withoutIsolation = function () {
mockScope.isolation = false;
return mockModule;
};
mockModule.forceCacheClear = function (mode) {
mockScope.forceCacheClear = mode !== undefined ? mode : true;
};
mockModule.setCacheControl = function (mode) {
mockScope.cacheControl = mode;
};
/**
* Adding new passby record
* @param {String|RegEx|Function} pattern
*/
mockModule.passBy = function (pattern) {
mockScope.passBy.push(pattern);
return mockModule;
};
mockModule.overrideEntryPoint = function (parent) {
mockScope.parentModule = parentModule = parent || (0, _module.getModuleParent)((0, _module.getModuleParent)(module));
};
/** interface **/
/**
* enabled rewiremock
*/
mockModule.enable = function () {
scope();
_module2.default.probeSyncModules();
_module2.default.overloadRequire();
storeCache();
if ((0, _globals.getScopeVariable)('cacheControl') !== false) {
(0, _wipeCache2.default)();
}
(0, _plugins.onEnable)((0, _mocks.getAllMocks)());
return mockModule;
};
/**
* disabled rewiremock
*/
mockModule.disable = function () {
scope();
_module2.default.restoreRequire();
(0, _plugins.onDisable)((0, _mocks.getAllMocks)());
mockModule.withoutIsolation();
mockModule.flush();
return mockModule;
};
/**
* Requires file with hooks
* @param {String|Function} file
* @param {Object|Function} overrides
*/
mockModule.proxy = function (file) {
var overrides = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var result = 0;
mockModule.inScope(function () {
var stubs = (typeof overrides === 'function' ? overrides(_mock2.default.inlineConstructor) : overrides) || {};
(0, _keys2.default)(stubs).forEach(function (key) {
return mockModule(key).from(stubs[key]);
});
mockModule.enable();
if (typeof file === 'string') {
result = mockModule.requireActual(file);
} else {
result = file();
}
mockModule.disable();
});
return result;
};
/**
* Imports file with hooks
* @param {Function} importFunction (use import)
* @param {Object|Function} overrides
* @return {Promise}
*/
mockModule.module = function (importFunction) {
var overrides = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
return mockModule.around(importFunction, function () {
var stubs = (typeof overrides === 'function' ? overrides(_mock2.default.inlineConstructor) : overrides) || {};
(0, _keys2.default)(stubs).forEach(function (key) {
return mockModule(key).from(stubs[key]);
});
});
};
/**
* Creates temporary executing scope. All mocks and plugins you will add in callback will be removed at exit.
* @param callback
*/
mockModule.inScope = function (callback) {
var currentScope = mockScope;
var error = void 0;
updateScope(currentScope);
try {
callback();
} catch (e) {
error = e;
}
mockScope = currentScope;
if (error) throw error;
return mockModule;
};
/**
* executes module in sandbox
* @param {Function} loader loader callback
* @param {Function} [createCallback] - optional callback to be executed before load.
* @return {Promise}
*/
mockModule.around = function (loader, createCallback) {
return new _promise2.default(function (resolve, reject) {
var currentScope = mockScope;
updateScope(currentScope);
var restore = function restore() {
mockModule.disable();
mockScope = currentScope;
};
_promise2.default.resolve(createCallback && createCallback(mockModule)).then(function () {
return _module2.default.probeAsyncModules();
}).then(function () {
return mockModule.enable();
}).then(function () {
return _promise2.default.resolve(loader()).then(function (mockedResult) {
restore();
resolve(mockedResult);
}, function (err) {
restore();
reject(err);
});
});
});
};
mockModule.stubFactory = function (factory) {
var currentScope = mockScope;
currentScope.options.stubFactory = factory;
};
var storeCache = function storeCache() {
mockScope.requireCache = mockScope.requireCache || (0, _assign2.default)({}, require.cache);
};
var restoreCache = function restoreCache() {
var oldCache = mockScope.requireCache;
var newCache = require.cache;
if (oldCache) {
(0, _keys2.default)(oldCache)
//.filter(key => !newCache[key])
.forEach(function (key) {
return newCache[key] = oldCache[key];
});
mockScope.requireCache = null;
}
};
var swapCache = function swapCache() {
var oldCache = mockScope.requireCache;
var newCache = require.cache;
if (oldCache) {
(0, _keys2.default)(newCache).filter(function (key) {
return !oldCache[key];
}).filter(function (key) {
return key.indexOf('.node') < 0;
}).forEach(function (key) {
return delete newCache[key];
});
(0, _keys2.default)(oldCache).forEach(function (key) {
return newCache[key] = oldCache[key];
});
mockScope.requireCache = null;
}
};
/**
* flushes all active overrides
*/
mockModule.flush = function () {
var forceCacheClear = (0, _globals.getScopeVariable)('forceCacheClear');
// flush away soiled modules
(0, _wipeCache2.default)(mockScope.mockedModules);
mockScope.mockedModules = {};
if (forceCacheClear) {
if (forceCacheClear !== 'nocache') {
// restore cache completely
swapCache();
}
} else {
// merge caches
restoreCache();
}
};
/**
* Low-level require
* @param {String} fileName
*/
mockModule.requireActual = function (fileName) {
return _module2.default.require(_module2.default.relativeFileName(fileName, parentModule), parentModule);
};
/**
* Low-level import
* @param {String} fileName
*/
mockModule.importActual = function (fileName) {
return _promise2.default.resolve(undefined.requireActual(fileName));
};
/**
* flushes anything
*/
mockModule.clear = function () {
updateScope();
scope();
mockModule.withoutIsolation();
mockModule.flush();
};
var cleanup = function cleanup() {
(0, _wipeCache.safelyRemoveCache)((0, _module.getModuleName)(module));
};
var addPlugin = function addPlugin(plugin) {
plugin.init();
scope();
(0, _plugins.addPlugin)(plugin);
};
var removePlugin = function removePlugin(plugin) {
scope();
(0, _plugins.removePlugin)(plugin);
};
mockModule.addPlugin = function (plugin) {
addPlugin(plugin);
return mockModule;
};
exports.mockModule = mockModule;
exports.addPlugin = addPlugin;
exports.removePlugin = removePlugin;
exports.cleanup = cleanup;