rewiremock
Version:
Advanced dependency mocking device.
319 lines (282 loc) • 10.4 kB
JavaScript
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;