react-magnetic-di
Version:
Context driven dependency injection
41 lines (38 loc) • 2.32 kB
JavaScript
const {
isMatchingAny
} = require('./utils');
function processInjectable(t, path, state, opts) {
var _state$injectIdentifi, _configPath$node$prop;
const [depPath,, configPath] = path.get('arguments');
if (!depPath || !(state != null && state.injectIdentifier) || path.get('callee').node.name !== ((_state$injectIdentifi = state.injectIdentifier) == null ? void 0 : _state$injectIdentifi.name)) {
return;
}
// check if third argument is not an object with module: false
const moduleFlag = configPath == null || (_configPath$node$prop = configPath.node.properties) == null || (_configPath$node$prop = _configPath$node$prop.find(n => {
var _n$key;
return ((_n$key = n.key) == null ? void 0 : _n$key.name) === 'module';
})) == null || (_configPath$node$prop = _configPath$node$prop.value) == null ? void 0 : _configPath$node$prop.value;
const depName = depPath.node.name;
const importSource = state.imports.specifiers.get(depName);
// There are several conditions under which we should mock:
// - if the import source matches any defaultMockedModules regexp
// and not consuming multiple exports or module flag is false
// - if injectable is called with explicit module: true
const isSourceAllowed = isMatchingAny(opts.defaultMockedModules.include, importSource) && !isMatchingAny(opts.defaultMockedModules.exclude, importSource);
if (!isSourceAllowed && !moduleFlag || moduleFlag === false) return;
const allSpecifiers = state.imports.sources.get(importSource);
const remainingSpecifiers = moduleFlag ? [] : allSpecifiers == null ? void 0 : allSpecifiers.filter(s => s !== depName);
state.imports.sources.set(importSource, remainingSpecifiers);
if ((remainingSpecifiers == null ? void 0 : remainingSpecifiers.length) !== 0 || (allSpecifiers == null ? void 0 : allSpecifiers.length) === 0) {
return;
}
const statement = t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('jest'), t.identifier('mock')), [t.stringLiteral(importSource)]));
// add statement var to programPath body after all imports but before variables
state.programPath.get('body').some((n, i) => {
if (!t.isImportDeclaration(n)) {
state.programPath.get('body')[i].insertBefore(statement);
return true;
}
});
}
module.exports = processInjectable;