jest-codemods
Version:
Codemods for migrating test files to Jest
475 lines (474 loc) • 19.7 kB
JavaScript
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);
}
;