jest-codemods
Version:
Codemods for migrating test files to Jest
258 lines (257 loc) • 10.3 kB
JavaScript
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
return cooked;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.addRequireOrImport = addRequireOrImport;
exports.addRequireOrImportOnceFactory = addRequireOrImportOnceFactory;
exports.findRequires = findRequires;
exports.findImports = findImports;
exports.hasRequireOrImport = hasRequireOrImport;
exports.getRequireOrImportName = getRequireOrImportName;
exports.removeDefaultImport = removeDefaultImport;
exports.removeRequireAndImport = removeRequireAndImport;
var recast_helpers_1 = require("./recast-helpers");
function addRequireOrImport(j, ast, localName, pkg) {
var statement = j.template.statement;
var requires = ast.find(j.CallExpression, {
callee: { name: 'require' },
});
var requireStatement;
if (requires.size()) {
requireStatement = statement(templateObject_1 || (templateObject_1 = __makeTemplateObject(["const ", " = require(", ");"], ["const ", " = require(", ");"])), localName, j.literal(pkg));
}
else {
requireStatement = j.importDeclaration([j.importDefaultSpecifier(j.identifier(localName))], j.literal(pkg));
}
ast.find(j.Program).get('body', 0).insertBefore(requireStatement);
}
function addRequireOrImportOnceFactory(j, ast) {
var pkgs = new Set([]);
return function (localName, pkg) {
if (!pkgs.has(pkg)) {
addRequireOrImport(j, ast, localName, pkg);
pkgs.add(pkg);
}
};
}
function findRequires(j, ast, pkg) {
return ast
.find(j.CallExpression, {
callee: { name: 'require' },
arguments: function (arg) { return arg[0].value === pkg; },
})
.filter(function (p) { return p.value.arguments.length === 1; });
}
function findImports(j, ast, pkg) {
return ast.find(j.ImportDeclaration, {
source: {
value: pkg,
},
});
}
/**
* Detects CommonJS and import statements for the given package.
* @return true if import were found, else false
*/
function hasRequireOrImport(j, ast, pkg) {
var requires = findRequires(j, ast, pkg).size();
var imports = findImports(j, ast, pkg).size();
return requires + imports > 0;
}
function findParentPathMemberRequire(path) {
if (path.parentPath && path.parentPath.value.type === 'MemberExpression') {
return path.parentPath.value.property;
}
return null;
}
/**
* Returns localName for any CommonJS or import statements for the given package.
* @return string if import were found, else undefined
*/
function getRequireOrImportName(j, ast, pkg) {
var localName = null;
findRequires(j, ast, pkg).forEach(function (p) {
var variableDeclarationPath = (0, recast_helpers_1.findParentVariableDeclaration)(p);
if (variableDeclarationPath) {
localName = variableDeclarationPath.value.id.name;
}
});
findImports(j, ast, pkg).forEach(function (p) {
var pathSpecifier = p.value.specifiers[0];
if (pathSpecifier && pathSpecifier.type === 'ImportDefaultSpecifier') {
localName = pathSpecifier.local.name;
}
});
return localName;
}
/**
* Detects and removes default import statements for given package.
* @return the local name for the default import or null
*/
function removeDefaultImport(j, ast, pkg) {
var getBodyNode = function () { return ast.find(j.Program).get('body', 0).node; };
var comments = getBodyNode().comments;
var localName = null;
findImports(j, ast, pkg).forEach(function (p) {
var pathSpecifier = p.value.specifiers[0];
if (pathSpecifier && pathSpecifier.type === 'ImportDefaultSpecifier') {
localName = pathSpecifier.local.name;
p.prune();
}
});
getBodyNode().comments = comments;
return localName;
}
function findVariableDeclarator(p) {
if (p.value.type === 'VariableDeclarator') {
return p;
}
return p.parentPath ? findVariableDeclarator(p.parentPath) : null;
}
/**
* Detects and removes CommonJS and import statements for given package.
* @return the import variable name or null if no import were found.
*/
function removeRequireAndImport(j, ast, pkg, specifier) {
var getBodyNode = function () { return ast.find(j.Program).get('body', 0).node; };
var comments = getBodyNode().comments;
var localName = null;
var importName = null;
findRequires(j, ast, pkg).forEach(function (p) {
var variableDeclarationPath = (0, recast_helpers_1.findParentVariableDeclaration)(p);
var parentMember = findParentPathMemberRequire(p);
// Examples:
// const chai = require('chai');
// const expect = require('chai').expect;
if (!specifier || (parentMember && parentMember.name === specifier)) {
if (variableDeclarationPath) {
localName = variableDeclarationPath.value.id.name;
variableDeclarationPath.prune();
}
else {
var expressionPath = (0, recast_helpers_1.findParentOfType)(p, 'ExpressionStatement');
if (expressionPath) {
expressionPath.prune();
}
else {
p.prune();
}
}
return;
}
// Examples:
// const { expect } = require('chai');
// const { expect: expct } = require('chai');
if (specifier &&
variableDeclarationPath &&
variableDeclarationPath.value &&
variableDeclarationPath.value.id.type === 'ObjectPattern') {
var properties = variableDeclarationPath.value.id.properties;
var index = properties.findIndex(function (prop) {
return prop.key.type === 'Identifier' && prop.key.name === specifier;
});
if (index !== undefined) {
var propertyPath = variableDeclarationPath.get('id', 'properties', index);
localName = propertyPath.value.value.name;
if (properties.length === 1) {
// Remove the variable declaration if there's only one property
// e.g. const { expect } = require('chai');
variableDeclarationPath.prune();
}
else {
// Only remove the property if other properties exist
// e.g. const { expect, other } = require('chai');
propertyPath.prune();
}
return;
}
}
/**
* Examples:
* const chai = require('chai');
* const expect = chai.expect;
*
* const chai = require('chai');
* const { expect } = chai;
*/
if (variableDeclarationPath && specifier) {
var memberUsagesOfPkg = ast.find(j.MemberExpression, {
object: function (node) {
return node &&
node.type === 'Identifier' &&
node.name === variableDeclarationPath.value.id.name;
},
});
var initUsagesOfPkg = ast.find(j.VariableDeclarator, {
init: function (node) {
return node &&
node.type === 'Identifier' &&
node.name === variableDeclarationPath.value.id.name;
},
});
var usagesOfPkg_1 = memberUsagesOfPkg.length + initUsagesOfPkg.length;
// const chai = require('chai');
// const { expect } = chai;
ast
.find(j.VariableDeclarator, {
id: function (node) { return node.type === 'ObjectPattern'; },
init: function (node) {
return node &&
node.type === 'Identifier' &&
node.name === variableDeclarationPath.value.id.name;
},
})
.forEach(function (p) {
var index = p.value.id.properties.findIndex(function (prop) { return prop.key.type === 'Identifier' && prop.key.name === specifier; });
if (index >= 0) {
var property = p.get('id', 'properties', index);
localName = property.value.value.name;
if (p.value.id.properties.length === 1) {
p.prune();
if (usagesOfPkg_1 <= 1) {
variableDeclarationPath.prune();
}
}
else {
property.prune();
}
}
});
// const chai = require('chai');
// const expect = chai.expect;
ast
.find(j.MemberExpression, {
object: function (node) {
return variableDeclarationPath.value &&
node.type === 'Identifier' &&
node.name === variableDeclarationPath.value.id.name;
},
property: function (node) { return node.type === 'Identifier' && node.name === specifier; },
})
.map(function (p) { return findVariableDeclarator(p); })
.filter(Boolean)
.forEach(function (p) {
localName = p.value.id.name;
p.prune();
if (usagesOfPkg_1 <= 1) {
variableDeclarationPath.prune();
}
});
}
});
findImports(j, ast, pkg).forEach(function (p) {
var pathSpecifier = p.value.specifiers[0];
importName = pathSpecifier && pathSpecifier.imported && pathSpecifier.imported.name;
if (!specifier || importName === specifier) {
if (pathSpecifier) {
localName = pathSpecifier.local.name;
}
p.prune();
}
});
getBodyNode().comments = comments;
return localName;
}
var templateObject_1;
;