UNPKG

jest-codemods

Version:

Codemods for migrating test files to Jest

258 lines (257 loc) 10.3 kB
"use strict"; 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;