Created
September 6, 2019 04:13
-
-
Save krainboltgreene/694be83f3d6573a1cfc16786d511d6a9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
exports.default = tapeToJest; | |
var _imports = require("../utils/imports"); | |
var _consts = require("../utils/consts"); | |
var _tapeAvaHelpers = require("../utils/tape-ava-helpers"); | |
var _logger = _interopRequireDefault(require("../utils/logger")); | |
var _finale = _interopRequireDefault(require("../utils/finale")); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
/** | |
* Codemod for transforming Tape tests into Jest. | |
*/ | |
var SPECIAL_THROWS_CASE = '(special throws case)'; | |
var SPECIAL_PLAN_CASE = '(special plan case)'; | |
var tPropertiesMap = { | |
ok: 'toBeTruthy', | |
true: 'toBeTruthy', | |
assert: 'toBeTruthy', | |
notOk: 'toBeFalsy', | |
false: 'toBeFalsy', | |
notok: 'toBeFalsy', | |
error: 'toBeFalsy', | |
ifError: 'toBeFalsy', | |
ifErr: 'toBeFalsy', | |
iferror: 'toBeFalsy', | |
equal: 'toBe', | |
equals: 'toBe', | |
isEqual: 'toBe', | |
is: 'toBe', | |
strictEqual: 'toBe', | |
strictEquals: 'toBe', | |
notEqual: 'not.toBe', | |
notEquals: 'not.toBe', | |
notStrictEqual: 'not.toBe', | |
notStrictEquals: 'not.toBe', | |
isNotEqual: 'not.toBe', | |
isNot: 'not.toBe', | |
not: 'not.toBe', | |
doesNotEqual: 'not.toBe', | |
isInequal: 'not.toBe', | |
deepEqual: 'toEqual', | |
deepEquals: 'toEqual', | |
isEquivalent: 'toEqual', | |
same: 'toEqual', | |
notDeepEqual: 'not.toEqual', | |
notEquivalent: 'not.toEqual', | |
notDeeply: 'not.toEqual', | |
notSame: 'not.toEqual', | |
isNotDeepEqual: 'not.toEqual', | |
isNotDeeply: 'not.toEqual', | |
isNotEquivalent: 'not.toEqual', | |
isInequivalent: 'not.toEqual', | |
throws: SPECIAL_THROWS_CASE, | |
doesNotThrow: SPECIAL_THROWS_CASE, | |
plan: SPECIAL_PLAN_CASE | |
}; | |
var tPropertiesNotMapped = new Set(['pass', 'fail', 'end', 'comment']); | |
var tPropertiesUnsupported = new Set(['timeoutAfter', // toEqual is more strict but might be used in some cases: | |
'deepLooseEqual', 'looseEqual', 'looseEquals', 'notDeepLooseEqual', 'notLooseEqual', 'notLooseEquals', 'skip']); | |
var unsupportedTestFunctionProperties = new Set(['createStream', 'onFinish']); | |
function tapeToJest(fileInfo, api, options) { | |
var j = api.jscodeshift; | |
var ast = j(fileInfo.source); | |
var testFunctionName = (0, _imports.removeRequireAndImport)(j, ast, 'tap'); | |
if (!testFunctionName) { | |
// No Tape require/import were found | |
if (!options.skipImportDetection) { | |
return fileInfo.source; | |
} | |
testFunctionName = 'tap'; | |
} | |
var logWarning = function logWarning(msg, node) { | |
return (0, _logger.default)(fileInfo, msg, node); | |
}; | |
var transforms = [function () { | |
return (0, _tapeAvaHelpers.rewriteDestructuredTArgument)(fileInfo, j, ast, testFunctionName); | |
}, function () { | |
return (0, _tapeAvaHelpers.detectUnsupportedNaming)(fileInfo, j, ast, testFunctionName); | |
}, function detectUnsupportedFeatures() { | |
ast.find(j.CallExpression, { | |
callee: { | |
object: { | |
name: 't' | |
}, | |
property: function property(_ref) { | |
var name = _ref.name; | |
return tPropertiesUnsupported.has(name); | |
} | |
} | |
}).forEach(function (p) { | |
var propertyName = p.value.callee.property.name; | |
if (propertyName.toLowerCase().indexOf('looseequal') >= 0) { | |
logWarning(`"t.${propertyName}" is currently not supported. Try the stricter "toEqual" or "not.toEqual"`, p); | |
} else { | |
logWarning(`"t.${propertyName}" is currently not supported`, p); | |
} | |
}); | |
ast.find(j.CallExpression, { | |
callee: { | |
object: { | |
name: testFunctionName | |
}, | |
property: function property(_ref2) { | |
var name = _ref2.name; | |
return unsupportedTestFunctionProperties.has(name); | |
} | |
} | |
}).forEach(function (p) { | |
var propertyName = p.value.callee.property.name; | |
logWarning(`"${propertyName}" is currently not supported`, p); | |
}); | |
}, function updateAssertions() { | |
ast.find(j.CallExpression, { | |
callee: { | |
object: { | |
name: 't' | |
}, | |
property: function property(_ref3) { | |
var name = _ref3.name; | |
return !tPropertiesUnsupported.has(name) && !tPropertiesNotMapped.has(name); | |
} | |
} | |
}).forEach(function (p) { | |
var args = p.node.arguments; | |
var oldPropertyName = p.value.callee.property.name; | |
var newPropertyName = tPropertiesMap[oldPropertyName]; | |
if (typeof newPropertyName === 'undefined') { | |
logWarning(`"t.${oldPropertyName}" is currently not supported`, p); | |
return null; | |
} | |
var newCondition; | |
if (newPropertyName === SPECIAL_THROWS_CASE) { | |
// The semantics of t.throws(fn, expected, msg) in Tape: | |
// If `expected` is a string, it is set to msg, else exception reg exp | |
var secondArgString = args.length === 2 && args[1].type === 'Literal' && typeof args[1].value === 'string'; | |
var noErrorType = args.length === 1 || secondArgString; | |
if (noErrorType) { | |
newCondition = j.callExpression(j.identifier(oldPropertyName === 'throws' ? 'toThrow' : 'not.toThrow'), []); | |
} else { | |
newCondition = j.callExpression(j.identifier(oldPropertyName === 'throws' ? 'toThrowError' : 'not.toThrowError'), [args[1]]); | |
} | |
} 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 { | |
var hasSecondArgument = _consts.PROP_WITH_SECONDS_ARGS.indexOf(newPropertyName) >= 0; | |
var conditionArgs = hasSecondArgument ? [args[1]] : []; | |
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 updateTapeComments() { | |
ast.find(j.CallExpression, { | |
callee: { | |
object: { | |
name: 't' | |
}, | |
property: { | |
name: 'comment' | |
} | |
} | |
}).forEach(function (p) { | |
p.node.callee = 'console.log'; | |
}); | |
}, function rewriteTestCallExpression() { | |
ast.find(j.CallExpression, { | |
callee: { | |
name: testFunctionName | |
} | |
}).forEach(function (p) { | |
// Convert Tape option parameters, test([name], [opts], cb) | |
p.value.arguments.forEach(function (a) { | |
if (a.type === 'ObjectExpression') { | |
a.properties.forEach(function (tapeOption) { | |
var tapeOptionKey = tapeOption.key.name; | |
var tapeOptionValue = tapeOption.value.value; | |
if (tapeOptionKey === 'skip' && tapeOptionValue === true) { | |
p.value.callee.name = 'test.skip'; | |
} | |
if (tapeOptionKey === 'timeout') { | |
logWarning('"timeout" option is currently not supported', p); | |
} | |
}); | |
p.value.arguments = p.value.arguments.filter(function (pa) { | |
return pa.type !== 'ObjectExpression'; | |
}); | |
} | |
}); | |
if (p.node.callee.name !== 'test.skip') { | |
p.node.callee.name = 'test'; | |
} | |
(0, _tapeAvaHelpers.rewriteAssertionsAndTestArgument)(j, p); | |
}); | |
}]; | |
transforms.forEach(function (t) { | |
return t(); | |
}); | |
return (0, _finale.default)(fileInfo, j, ast, options); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment