UNPKG

jest-codemods

Version:

Codemods for migrating test files to Jest

212 lines (211 loc) 9.35 kB
"use strict"; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var consts_1 = require("../utils/consts"); var finale_1 = __importDefault(require("../utils/finale")); var imports_1 = require("../utils/imports"); var logger_1 = __importDefault(require("../utils/logger")); var recast_helpers_1 = require("../utils/recast-helpers"); var tape_ava_helpers_1 = require("../utils/tape-ava-helpers"); var SPECIAL_THROWS_CASE = '(special throws case)'; var SPECIAL_BOOL = '(special bool case)'; var SPECIAL_PLAN_CASE = '(special plan case)'; var tPropertiesMap = { ok: 'toBeTruthy', truthy: 'toBeTruthy', falsy: 'toBeFalsy', notOk: 'toBeFalsy', true: SPECIAL_BOOL, false: SPECIAL_BOOL, is: 'toBe', not: 'not.toBe', same: 'toEqual', deepEqual: 'toEqual', notSame: 'not.toEqual', notDeepEqual: 'not.toEqual', throws: SPECIAL_THROWS_CASE, notThrows: SPECIAL_THROWS_CASE, regex: 'toMatch', notRegex: 'not.toMatch', ifError: 'toBeFalsy', error: 'toBeFalsy', plan: SPECIAL_PLAN_CASE, snapshot: 'toMatchSnapshot', }; var tPropertiesNotMapped = new Set(['end', 'fail', 'pass']); var avaToJestMethods = { before: 'beforeAll', after: 'afterAll', beforeEach: 'beforeEach', afterEach: 'afterEach', only: 'test.only', skip: 'test.skip', failing: 'test.skip', todo: 'test.todo', }; var avaToJest = function (fileInfo, api, options) { var j = api.jscodeshift; var ast = j(fileInfo.source); var testFunctionName = (0, imports_1.removeRequireAndImport)(j, ast, 'ava'); if (!testFunctionName && !options.skipImportDetection) { // No AVA require/import were found return fileInfo.source; } var logWarning = function (msg, node) { return (0, logger_1.default)(fileInfo, msg, node); }; var transforms = [ function () { return (0, tape_ava_helpers_1.rewriteDestructuredTArgument)(fileInfo, j, ast, testFunctionName); }, function () { return (0, tape_ava_helpers_1.renameExecutionInterface)(fileInfo, j, ast, testFunctionName); }, function updateAssertions() { ast .find(j.CallExpression, { callee: { object: { name: 't' }, property: function (_a) { var name = _a.name; return !tPropertiesNotMapped.has(name); }, }, }) .forEach(function (p) { var args = p.node.arguments; var oldPropertyName = p.value.callee.type === 'MemberExpression' && p.value.callee.property.type === 'Identifier' && p.value.callee.property.name; var newPropertyName = tPropertiesMap[oldPropertyName]; if (typeof newPropertyName === 'undefined') { logWarning("\"t.".concat(oldPropertyName, "\" is currently not supported"), p); return null; } var newCondition; if (newPropertyName === SPECIAL_BOOL) { newCondition = j.callExpression(j.identifier('toBe'), [ j.identifier(oldPropertyName), ]); } else if (newPropertyName === SPECIAL_PLAN_CASE) { var condition = j.memberExpression(j.identifier('expect'), j.callExpression(j.identifier('assertions'), [args[0]])); return j(p).replaceWith(condition); } else if (newPropertyName === SPECIAL_THROWS_CASE) { if (args.length === 1) { newCondition = j.callExpression(j.identifier(oldPropertyName === 'throws' ? 'toThrow' : 'not.toThrow'), []); } else { newCondition = j.callExpression(j.identifier(oldPropertyName === 'throws' ? 'toThrowError' : 'not.toThrowError'), [args[1]]); } } else { var hasSecondArgument = consts_1.PROP_WITH_SECONDS_ARGS.indexOf(newPropertyName) >= 0; if (hasSecondArgument && args.length < 2) { logWarning("\"t.".concat(oldPropertyName, "\" should have 2 arguments"), p); return; } var _a = __read(args, 3), _arg0 = _a[0], arg1 = _a[1], arg2 = _a[2]; var conditionArgs = hasSecondArgument ? [arg1] : []; if (newPropertyName === 'toMatchSnapshot') { // Can take an optional message argument if (arg1 && arg1.type === 'Literal') { conditionArgs = [arg1]; } else if (arg2 && arg2.type === 'Literal') { conditionArgs = [arg2]; } } newCondition = j.callExpression(j.identifier(newPropertyName), conditionArgs); } var newExpression = j.memberExpression(j.callExpression(j.identifier('expect'), [args[0]]), newCondition); return j(p).replaceWith(newExpression); }); }, function rewriteTestCallExpression() { // Can either be simple CallExpression like test() // Or MemberExpression like test.after.skip() ast .find(j.CallExpression, { callee: { name: testFunctionName }, }) .forEach(function (p) { if (p.node.callee.type === 'Identifier') { p.node.callee.name = 'test'; (0, tape_ava_helpers_1.rewriteAssertionsAndTestArgument)(j, p); } }); function mapPathToJestCallExpression(p) { var scope = p.scope; var name = p.node.callee.object.name; while (scope) { if (scope.declares(name)) { return j.callExpression(j.memberExpression(p.node.callee.object, p.node.callee.property), p.node.arguments); } scope = scope.parent; } var jestMethod = 'test'; var jestMethodArgs = p.node.arguments; // List like ['test', 'serial', 'cb', 'always'] var avaMethods = (0, recast_helpers_1.getMemberExpressionElements)(p.node.callee).filter(function (e) { return e !== 'serial' && e !== testFunctionName && e !== 'cb' && e != 'always'; }); if (avaMethods.length === 1) { var avaMethod = avaMethods[0]; if (avaMethod in avaToJestMethods) { jestMethod = avaToJestMethods[avaMethod]; } else { jestMethod = avaMethod; logWarning("Unknown AVA method \"".concat(avaMethod, "\""), p); } } else if (avaMethods[0] === 'context') { var identifier_1 = j.identifier(avaMethods[0]); avaMethods.slice(1).forEach(function (next) { identifier_1 = j.memberExpression(identifier_1, j.identifier(next)); }); return j.callExpression(identifier_1, jestMethodArgs); } else if (avaMethods.length > 0) { logWarning('Skipping setup/teardown hooks is currently not supported', p); } return j.callExpression(j.identifier(jestMethod), jestMethodArgs); } ast .find(j.CallExpression, { callee: { type: 'MemberExpression', }, }) .filter(function (p) { var identifier = (0, recast_helpers_1.getIdentifierFromExpression)(p.node.callee); if (identifier === null) { return null; } if (identifier.name === testFunctionName) { return Boolean(p); } return null; }) .forEach(function (p) { (0, tape_ava_helpers_1.rewriteAssertionsAndTestArgument)(j, p); }) .replaceWith(mapPathToJestCallExpression); }, ]; transforms.forEach(function (t) { return t(); }); return (0, finale_1.default)(fileInfo, j, ast, options); }; exports.default = avaToJest;