UNPKG

jest-codemods

Version:

Codemods for migrating test files to Jest

475 lines (474 loc) 19.7 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; 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 }); exports.default = transformer; var finale_1 = __importDefault(require("../utils/finale")); var imports_1 = require("../utils/imports"); var logger_1 = __importDefault(require("../utils/logger")); var getAssertionExpression = function (chaiAssertExpression, assertionName) { return ({ type: 'CallExpression', callee: { type: 'MemberExpression', object: chaiAssertExpression, property: { type: 'Identifier', name: assertionName, }, }, }); }; var assertToExpectMapping = [ { assert: 'ok', expect: 'toBeTruthy', ignoreExpectedValue: true, }, { assert: 'notOk', expect: 'toBeFalsy', ignoreExpectedValue: true, }, { assert: 'isOk', expect: 'toBeTruthy', ignoreExpectedValue: true, }, { assert: 'isNotOk', expect: 'toBeFalsy', ignoreExpectedValue: true, }, { assert: 'equal', expect: 'toEqual', includeNegative: 'notEqual', }, { assert: 'strictEqual', expect: 'toBe', includeNegative: 'notStrictEqual', }, { assert: 'deepEqual', expect: 'toEqual', includeNegative: 'notDeepEqual', }, { assert: 'deepStrictEqual', expect: 'toStrictEqual', includeNegative: 'notDeepStrictEqual', }, { assert: 'isAbove', expect: 'toBeGreaterThan', }, { assert: 'isAtLeast', expect: 'toBeGreaterThanOrEqual', }, { assert: 'isBelow', expect: 'toBeLessThan', }, { assert: 'isAtMost', expect: 'toBeLessThanOrEqual', }, { assert: 'isTrue', expect: 'toBe', expectedOverride: true, includeNegative: 'isNotTrue', }, { assert: 'isFalse', expect: 'toBe', expectedOverride: false, includeNegative: 'isNotFalse', }, { assert: 'isNull', expect: 'toBeNull', ignoreExpectedValue: true, includeNegative: 'isNotNull', }, { assert: 'isNaN', expect: 'toBe', ignoreExpectedValue: true, expectedOverride: 'NaN', includeNegative: 'isNotNaN', }, { assert: 'isDefined', expect: 'toBeDefined', ignoreExpectedValue: true, includeNegative: 'isUndefined', }, { assert: 'instanceOf', expect: 'toBeInstanceOf', includeNegative: 'notInstanceOf', }, { assert: 'include', expect: 'toContain', includeNegative: 'notInclude', }, { assert: 'match', expect: 'toMatch', includeNegative: 'notMatch', }, { assert: 'throws', expect: 'toThrow', ignoreExpectedValue: true, includeNegative: 'doesNotThrow', }, { assert: 'sameMembers', expect: 'toEqual', }, { assert: 'sameDeepMembers', expect: 'toEqual', }, { assert: 'nestedProperty', expect: 'toHaveProperty', includeNegative: 'notNestedProperty', }, ]; var objectChecks = [ 'isExtensible', 'isNotExtensible', 'isSealed', 'isNotSealed', 'isFrozen', 'isNotFrozen', ]; /** * Type checking */ var chaiAssertTypeofs = [ { assert: 'isFunction', type: 'function' }, { assert: 'isObject', type: 'object' }, { assert: 'isString', type: 'string' }, { assert: 'isNumber', type: 'number' }, { assert: 'isBoolean', type: 'boolean' }, ]; var getArguments = function (path, ignoreExpectedValue, expectedOverride) { var _a = __read(path.value.arguments, 2), actual = _a[0], originalExpectation = _a[1]; var expectation = !ignoreExpectedValue ? expectedOverride || originalExpectation : undefined; return expectation ? { actual: actual, expectation: expectation } : { actual: actual }; }; var unsupportedAssertions = [ 'operator', 'changes', 'doesNotChange', 'increases', 'doesNotIncrease', 'decreases', 'doesNotDecrease', ]; function transformer(fileInfo, api, options) { var j = api.jscodeshift; var ast = j(fileInfo.source); var chaiAssertExpression; var assertLocalName = (0, imports_1.removeRequireAndImport)(j, ast, 'chai', 'assert'); var defaultImportLocalName = (0, imports_1.removeDefaultImport)(j, ast, 'chai'); if (assertLocalName) { chaiAssertExpression = { type: 'Identifier', name: assertLocalName, }; } else if (defaultImportLocalName) { chaiAssertExpression = { type: 'MemberExpression', object: { type: 'Identifier', name: defaultImportLocalName, }, property: { type: 'Identifier', name: 'assert', }, }; } if (!chaiAssertExpression) { if (!options.skipImportDetection) { // No Chai require/import were found return fileInfo.source; } assertLocalName = 'assert'; chaiAssertExpression = { type: 'Identifier', name: 'assert', }; } var logWarning = function (msg, path) { return (0, logger_1.default)(fileInfo, msg, path); }; var makeExpectation = function (identifier, actual, expectation) { if (expectation === void 0) { expectation = []; } return j.callExpression(j.memberExpression(j.callExpression(j.identifier('expect'), [actual]), j.identifier(identifier)), Array.isArray(expectation) ? expectation : [expectation]); }; var makeExpectationNamedArguments = function (_a) { var identifier = _a.identifier, actual = _a.actual, _b = _a.expectation, expectation = _b === void 0 ? [] : _b; return makeExpectation(identifier, actual, expectation); }; var makeNegativeExpectation = function (identifier, actual, expectation) { if (expectation === void 0) { expectation = []; } return j.callExpression(j.memberExpression(j.memberExpression(j.callExpression(j.identifier('expect'), [actual]), j.identifier('not')), j.identifier(identifier)), Array.isArray(expectation) ? expectation : [expectation]); }; var makeNegativeExpectationNamedArguments = function (_a) { var identifier = _a.identifier, actual = _a.actual, _b = _a.expectation, expectation = _b === void 0 ? [] : _b; return makeNegativeExpectation(identifier, actual, expectation); }; assertToExpectMapping.forEach(function (_a) { var assert = _a.assert, expect = _a.expect, ignoreExpectedValue = _a.ignoreExpectedValue, includeNegative = _a.includeNegative, expectedOverride = _a.expectedOverride; var override; if (typeof expectedOverride !== 'undefined') { override = typeof expectedOverride === 'boolean' ? j.literal(expectedOverride) : j.identifier(expectedOverride); } ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, assert)) .replaceWith(function (path) { return makeExpectationNamedArguments(__assign({ identifier: expect }, getArguments(path, ignoreExpectedValue, override))); }); if (includeNegative) { ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, includeNegative)) .replaceWith(function (path) { return makeNegativeExpectationNamedArguments(__assign({ identifier: expect }, getArguments(path, ignoreExpectedValue, override))); }); } }); unsupportedAssertions.forEach(function (assertion) { ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, assertion)) .forEach(function (path) { logWarning("Unsupported Chai Assertion \"".concat(assertion, "\"."), path); }); }); ['approximately', 'closeTo'].forEach(function (assertion) { ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, assertion)) .replaceWith(function (path) { return makeExpectation('toBeLessThanOrEqual', j.callExpression(j.memberExpression(j.identifier('Math'), j.identifier('abs')), [ j.binaryExpression('-', path.value.arguments[0], path.value.arguments[1]), ]), [path.value.arguments[2]]); }); }); // assert.nestedPropertyVal -> expect(obj).toHaveProperty() ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'nestedPropertyVal')) .replaceWith(function (path) { return makeExpectation('toHaveProperty', path.value.arguments[0], [ path.value.arguments[1], path.value.arguments[2], ]); }); // assert.notNestedPropertyVal -> expect(obj).not.toHaveProperty() ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'notNestedPropertyVal')) .replaceWith(function (path) { return makeNegativeExpectation('toHaveProperty', path.value.arguments[0], [ path.value.arguments[1], path.value.arguments[2], ]); }); // assert.fail -> expect(false).toBeTruthy() ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'fail')) .replaceWith(function (path) { return makeExpectation('toBe', j.literal(false), j.literal(true)); }); // assert.propertyVal -> expect(*.[prop]).toBe() ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'propertyVal')) .replaceWith(function (path) { var _a = __read(path.value.arguments, 3), obj = _a[0], prop = _a[1], value = _a[2]; return makeExpectation('toBe', j.memberExpression(obj, prop), value); }); // assert.propertyNotVal -> expect(*.[prop]).not.toBe() ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'propertyNotVal')) .replaceWith(function (path) { var _a = __read(path.value.arguments, 3), obj = _a[0], prop = _a[1], value = _a[2]; return makeNegativeExpectation('toBe', j.memberExpression(obj, prop), value); }); // assert.notPropertyVal -> expect(*.[prop]).not.toBe() ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'notPropertyVal')) .replaceWith(function (path) { var _a = __read(path.value.arguments, 3), obj = _a[0], prop = _a[1], value = _a[2]; return makeNegativeExpectation('toBe', j.memberExpression(obj, prop), value); }); // assert.deepPropertyVal -> expect(*).toHaveProperty(keyPath, ?value) ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'deepPropertyVal')) .replaceWith(function (path) { var _a = __read(path.value.arguments, 3), obj = _a[0], prop = _a[1], value = _a[2]; return makeExpectation('toHaveProperty', obj, [prop, value]); }); // assert.deepPropertyNotVal -> expect(*).not.toHaveProperty(keyPath, ?value) ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'deepPropertyNotVal')) .replaceWith(function (path) { var _a = __read(path.value.arguments, 3), obj = _a[0], prop = _a[1], value = _a[2]; return makeNegativeExpectation('toHaveProperty', obj, [prop, value]); }); // assert.notDeepPropertyVal -> expect(*).not.toHaveProperty(keyPath, ?value) ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'notDeepPropertyVal')) .replaceWith(function (path) { var _a = __read(path.value.arguments, 3), obj = _a[0], prop = _a[1], value = _a[2]; return makeNegativeExpectation('toHaveProperty', obj, [prop, value]); }); // assert.deepProperty -> expect(*).toHaveProperty(keyPath) ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'deepProperty')) .replaceWith(function (path) { var _a = __read(path.value.arguments, 2), obj = _a[0], prop = _a[1]; return makeExpectation('toHaveProperty', obj, prop); }); // assert.notDeepProperty -> expect(*).not.toHaveProperty(keyPath) ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'notDeepProperty')) .replaceWith(function (path) { var _a = __read(path.value.arguments, 2), obj = _a[0], prop = _a[1]; return makeNegativeExpectation('toHaveProperty', obj, prop); }); // assert.property -> expect(prop in obj).toBeTruthy() ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'property')) .replaceWith(function (path) { return makeExpectation('toBeTruthy', j.binaryExpression('in', path.value.arguments[1], path.value.arguments[0])); }); // assert.notProperty -> expect(prop in obj).toBeFalsy() ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'notProperty')) .replaceWith(function (path) { return makeExpectation('toBeFalsy', j.binaryExpression('in', path.value.arguments[1], path.value.arguments[0])); }); // assert.ifError -> expect(*).toBeFalsy() ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'ifError')) .replaceWith(function (path) { return makeExpectation('toBeFalsy', path.value.arguments[0]); }); // assert.includeMembers -> expect([]).toEqual(expect.arrayContaining([])) ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'includeMembers')) .replaceWith(function (path) { return makeExpectation('toEqual', path.value.arguments[0], j.callExpression(j.memberExpression(j.identifier('expect'), j.identifier('arrayContaining')), [path.value.arguments[1]])); }); // assert.notIncludeMembers -> expect([]).not.toEqual(expect.arrayContaining([])) ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'notIncludeMembers')) .replaceWith(function (path) { return makeNegativeExpectation('toEqual', path.value.arguments[0], j.callExpression(j.memberExpression(j.identifier('expect'), j.identifier('arrayContaining')), [path.value.arguments[1]])); }); // assert.includeDeepMembers -> expect([]).toEqual(expect.arrayContaining([])) ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'includeDeepMembers')) .replaceWith(function (path) { return makeExpectation('toEqual', path.value.arguments[0], j.callExpression(j.memberExpression(j.identifier('expect'), j.identifier('arrayContaining')), [path.value.arguments[1]])); }); // assert.notIncludeDeepMembers -> expect([]).not.toEqual(expect.arrayContaining([])) ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'notIncludeDeepMembers')) .replaceWith(function (path) { return makeNegativeExpectation('toEqual', path.value.arguments[0], j.callExpression(j.memberExpression(j.identifier('expect'), j.identifier('arrayContaining')), [path.value.arguments[1]])); }); // assert.isArray -> expect(Array.isArray).toBe(true) ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'isArray')) .replaceWith(function (path) { return makeExpectation('toBe', j.callExpression(j.memberExpression(j.identifier('Array'), j.identifier('isArray')), [path.value.arguments[0]]), j.literal(true)); }); // assert.isArray -> expect(Array.isArray).toBe(false) ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'isNotArray')) .replaceWith(function (path) { return makeNegativeExpectation('toBe', j.callExpression(j.memberExpression(j.identifier('Array'), j.identifier('isArray')), [path.value.arguments[0]]), j.literal(true)); }); // assert.typeOf(foo, Bar) -> expect(typeof foo).toBe(Bar) ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'typeOf')) .replaceWith(function (path) { return makeExpectation('toBe', j.unaryExpression('typeof', path.value.arguments[0]), path.value.arguments[1]); }); // assert.notTypeOf(foo, Bar) -> expect(typeof foo).not.toBe(Bar) ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'notTypeOf')) .replaceWith(function (path) { return makeNegativeExpectation('toBe', j.unaryExpression('typeof', path.value.arguments[0]), path.value.arguments[1]); }); chaiAssertTypeofs.forEach(function (_a) { var assert = _a.assert, type = _a.type; ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, assert)) .replaceWith(function (path) { return makeExpectation('toBe', j.unaryExpression('typeof', path.value.arguments[0]), j.literal(type)); }); ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, assert.replace(/^is/, 'isNot'))) .replaceWith(function (path) { return makeNegativeExpectation('toBe', j.unaryExpression('typeof', path.value.arguments[0]), j.literal(type)); }); }); // assert.lengthOf -> expect(*.length).toBe() ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'lengthOf')) .replaceWith(function (path) { return makeExpectation('toBe', j.memberExpression(path.value.arguments[0], j.identifier('length')), path.value.arguments[1]); }); // Object-specific boolean checks objectChecks.forEach(function (check) { var isNegative = check.indexOf('isNot') === 0; var expectation = check.replace('isNot', 'is'); ast .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, check)) .replaceWith(function (path) { return (isNegative ? makeNegativeExpectation : makeExpectation)('toBe', j.callExpression(j.memberExpression(j.identifier('Object'), j.identifier(expectation)), [path.value.arguments[0]]), j.literal(true)); }); }); // assert -> expect().toBeTruthy() ast .find(j.CallExpression, { callee: { type: 'Identifier', name: assertLocalName }, }) .replaceWith(function (path) { return makeExpectation('toBeTruthy', path.value.arguments[0]); }); return (0, finale_1.default)(fileInfo, j, ast, options); }