UNPKG

rewiremock

Version:

Advanced dependency mocking device.

380 lines (315 loc) 9.65 kB
'use strict'; 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;