UNPKG

rewiremock

Version:

Advanced dependency mocking device.

319 lines (282 loc) 10.4 kB
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } import { relative } from 'path'; import Module, { originalLoader } from './module'; import { autoMock, shouldMock } from './plugins'; import { getMock } from './mocks'; import getScope, { collectScopeVariable, getScopeOption, getScopeVariable } from './globals'; import { moduleCompare, pickModuleName, getModuleName, getModuleParent } from './module'; import asyncModules from './asyncModules'; import ModuleLoader from './getModule'; import matchOriginFabric from 'compare-module-exports'; import { NO } from "./plugins/_common"; import { safelyRemoveCache } from "./wipeCache"; var matchOrigin = matchOriginFabric('rewiremock'); var thisModule = module; var patternMatch = function patternMatch(fileName) { return function (pattern) { if (typeof pattern == 'function') { return pattern(fileName); } return fileName.match(pattern); }; }; export var requireModule = function requireModule(name, parentModule) { if (typeof __webpack_require__ !== 'undefined') { return __webpack_require__(name); } else { //return Module._load(name); return parentModule ? ModuleLoader._load(name, parentModule) : require(name); } }; var testPassby = function testPassby(request, module) { var _getScope = getScope(), parentModule = _getScope.parentModule, mockedModules = _getScope.mockedModules; var passBy = collectScopeVariable('passBy'); var isolation = getScopeVariable('isolation'); // was called from test if (moduleCompare(module, parentModule)) { //if (module === parentModule || module == module.parent) { return true; } // if parent is in the pass list - pass everything var fileName = Module._resolveFilename(request, module); var m = module; var test = function test(fileName) { return ( // parent was mocked !isolation.noAutoPassBy && mockedModules[fileName] || // parent is in pass list passBy.filter(patternMatch(fileName)).length ); }; if (!isolation.noParentPassBy) { while (m && !moduleCompare(m, parentModule)) { if (test(fileName)) { return true; } fileName = getModuleName(m); m = getModuleParent(m); } } return test(fileName); }; function mockResult(name, mock, dataFactory) { var factory = function factory() { var data = dataFactory(); if (mock.matchOrigin) { var matchResult = matchOrigin(mock.original, data, name, '%mock%', { noFunctionCompare: true }); if (matchResult) { // eslint-disable-next-line no-console matchResult.forEach(function (line) { return console.error(line); }); throw new Error('Rewiremock: provided mocks does not match ' + name); } } if (data && !data.default) { if (['object', 'function'].indexOf(typeof data === 'undefined' ? 'undefined' : _typeof(data)) >= 0) { Object.defineProperty(data, 'default', { enumerable: false, value: data }); } } return data; }; if (mock.flag_dynamic) { var origin = factory(); if (['object', 'function'].indexOf(typeof origin === 'undefined' ? 'undefined' : _typeof(origin)) >= 0) { return new Proxy(origin, { get: function get(target, prop) { return factory()[prop]; } }); } } return factory(); } function standardStubFactory(name, object, deeperMock) { if (typeof object === 'function') { return function () {}; } if ((typeof object === 'undefined' ? 'undefined' : _typeof(object)) === 'object') { return deeperMock(deeperMock); } return object; } function mockThought(stubFactory, mockOriginal) { var name = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; if (typeof mockOriginal === 'function') { return stubFactory(name || 'default', mockOriginal); } if ((typeof mockOriginal === 'undefined' ? 'undefined' : _typeof(mockOriginal)) === 'object') { var deeperMock = function deeperMock(key, value) { return mockThought(stubFactory, value, name ? name + '.' + key : key); }; if (Array.isArray(mockOriginal)) { return mockOriginal.map(function (x, i) { return deeperMock(i, x); }); } else { return Object.keys(mockOriginal).map(function (key) { return { key: key, value: deeperMock(key, mockOriginal[key]) }; }).reduce(function (acc, x) { return Object.assign(acc, _defineProperty({}, x.key, x.value)); }, {}); } } return mockOriginal; } function monkeyPatchPath(addr) { var path = addr.split('/'); if (path[0] === '..') { path[0] = '.'; return path.join('/'); } return addr; } function asyncTest() { var asyncModulesLeft = asyncModules.hasAsyncModules(); if (asyncModulesLeft) { /* eslint-disable no-console */ console.error('Rewiremock: listed async modules should finish loading first. Use async API of rewiremock.', asyncModulesLeft.map(function (module) { return module.creator; })); /* eslint-enable */ throw new Error('Rewiremock: listed async modules should finish loading first. Use async API of rewiremock.'); } } function tryOr(fn, failBack) { try { return fn(); } catch (e) { // probably file not found } return failBack; } function protoCopy(source, override) { var dest = Object.assign({}, override); Object.setPrototypeOf(dest, source); return dest; } function restoreProperties(dest, source) { var values = Object.getOwnPropertyDescriptors(source); Object.keys(values).forEach(function (key) { if (!Object.getOwnPropertyDescriptor(dest, key)) { Object.defineProperty(dest, key, values[key]); } }); return dest; } function restoreESModuleState(dest, original) { if (original && original.__esModule) { try { Object.defineProperty(dest, "__esModule", { value: true }); } catch (e) { // eslint-disable-next-line no-console console.error(e); } } return dest; } function mockLoader(request, parent, isMain) { var _getScope2 = getScope(), parentModule = _getScope2.parentModule, mockedModules = _getScope2.mockedModules; var isolation = getScopeVariable('isolation'); asyncTest(); var baseRequest = tryOr(function () { return Module._resolveFilename(request, parent); }, request); var shortRequest = monkeyPatchPath(relative(getModuleName(parent), request)); if (moduleCompare(parent, parentModule) || moduleCompare(parent, thisModule)) { safelyRemoveCache(baseRequest); mockedModules[baseRequest] = true; } var mock = getMock(baseRequest) || getMock(request) || getMock(shortRequest) || autoMock(baseRequest); if (mock) { mock.wasRequired = true; var shouldResult = {}; if (mock.alwaysMock || shouldMock(mock, request, parent, parentModule, shouldResult)) { // this file fill be not cached, but it`s opener - will. And we have to remember it mockedModules[getModuleName(parent)] = true; mock.usedAs = mock.usedAs || []; mock.usedAs.push(baseRequest); mockedModules[baseRequest] = true; if (mock.allowCallThrough || mock.matchOrigin || mock.mockThrough) { if (!mock.original) { mock.original = originalLoader(request, parent, isMain); } } if (mock.mockThrough) { var factory = mock.mockThrough === true ? getScopeOption('stubFactory') : mock.mockThrough; mock.override = mockThought(factory || standardStubFactory, mock.original); return mockResult(request, mock, function () { return restoreESModuleState(Object.assign({}, mock.override, mock.value), mock.original); }); } if (mock.overrideBy) { if (!mock.override) { if (typeof mock.overrideBy === 'string') { mock.override = originalLoader(pickModuleName(mock.overrideBy, parent), parent, isMain); } else { mock.override = mock.overrideBy({ name: request, fullName: baseRequest, parent: parent, original: mock.original, requireActual: function requireActual(name) { return originalLoader(pickModuleName(name, parent), parent, isMain); } }); } } return mockResult(request, mock, function () { return mock.override; }); } if (mock.allowCallThrough) { if (typeof mock.original === 'function') { if (_typeof(mock.value) === 'object' && Object.keys(mock.value).length === 0) { return mockResult(request, mock, function () { return mock.original; }); } else { throw new Error('rewiremock: trying to merge Functional base with callThrough mock at ' + request + '. Use overrideBy instead.'); } } return mockResult(request, mock, function () { return restoreProperties(protoCopy(mock.original, mock.value), mock.original); }); } return mockResult(request, mock, function () { return mock.value; }); } else { // console.error('reject', baseRequest, parent.id, parent.parent.id); mock.rejected = mock.rejected || []; if (shouldResult.plugins) { mock.rejected.push({ parent: parent, plugins: shouldResult.plugins.filter(function (p, index) { return shouldResult.values[index] === NO; }).map(function (p) { return p.name; }) }); } // why you shouldn't? } } if (isolation && !mockedModules[baseRequest]) { if (!testPassby(request, parent)) { throw new Error('rewiremock: isolation breach by [' + request + ']. Requested from ', getModuleName(parent)); } } return originalLoader(request, parent, isMain); } export default mockLoader;