Skip to content

Instantly share code, notes, and snippets.

@dcousineau
Created September 15, 2016 19:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dcousineau/0170c4cf30bcc83ebf1a39b4636ae7d6 to your computer and use it in GitHub Desktop.
Save dcousineau/0170c4cf30bcc83ebf1a39b4636ae7d6 to your computer and use it in GitHub Desktop.
AVA to Jest Codemod
const path = require('path');
function findAvaAssertion(assertionName, j, ast) {
return ast.find(j.CallExpression, {
callee: {
object: {name: 't'},
property: {name: assertionName},
},
});
}
function buildExpectStatement(method, expected, actual, j) {
return j.memberExpression(
j.callExpression(
j.identifier('expect'),
[expected]
),
j.callExpression(
j.identifier(method),
actual ? [actual] : []
)
);
}
function transformTestCall(isSkip, node, j) {
const name = isSkip ? 'xit' : 'it';
const args = node.get('arguments').value;
const [desc, testfn] = args;
if (testfn) {
testfn.params = [];
}
node.replace(
j.callExpression(
j.identifier(name),
args
),
);
}
module.exports = function(file, api, options = {}) {
const j = api.jscodeshift;
const printOptions = options.printOptions || {quote: 'single'};
const ast = j(file.source);
const { comments } = ast.find(j.Program).get('body', 0).node;
//Replace sinon.useFakeTimers() with jest && mockdate
const sinonResults = ast.find(j.CallExpression, {
callee: {
object: {name: 'sinon'},
property: {name: 'useFakeTimers'},
},
});
const shouldReplaceAvaWithMockDate = sinonResults.size() > 0;
let hasReplacedAvaWithMockDate = false;
ast.find(j.ImportDeclaration, {
source: {value: 'ava'}
}).forEach(p => {
if (shouldReplaceAvaWithMockDate && !hasReplacedAvaWithMockDate) {
p.replace(j.importDeclaration(
[j.importDefaultSpecifier(j.identifier('MockDate'))],
j.literal('mockdate'),
));
hasReplacedAvaWithMockDate = true;
} else {
p.prune();
}
});
sinonResults.forEach(p => {
const body = [
j.expressionStatement(j.memberExpression(
j.identifier('jest'),
j.callExpression(
j.identifier('useFakeTimers'),
[]
)
)),
j.expressionStatement(j.memberExpression(
j.identifier('MockDate'),
j.callExpression(
j.identifier('set'),
[j.literal('02/22/2016')]
)
)),
];
p.parent.replace(
j.blockStatement(body)
);
});
ast.find(j.ImportDeclaration, {
source: {value: 'ava'}
}).forEach(p => {
p.prune();
});
//unwrap test to it();
ast.find(j.CallExpression, {
callee: {
object: {name: 'test'},
property: {name: name => name === 'skip' || name === 'todo'},
},
})
.forEach(p => {
transformTestCall(true, p, j);
});
//unwrap test.serial to it();
ast.find(j.CallExpression, {
callee: {
object: {name: 'test'},
property: {name: name => name === 'serial'},
},
})
.forEach(p => {
transformTestCall(false, p, j);
});
//unwrap test to it();
ast.find(j.CallExpression, {
callee: {
name: 'test',
}
})
.forEach(p => {
transformTestCall(false, p, j);
});
findAvaAssertion('plan', j, ast).forEach(p => j(p).remove());
findAvaAssertion("deepEqual", j, ast).forEach(p => {
const [firstArg, secondArg] = p.get('arguments').value;
p.replace(buildExpectStatement("toEqual", secondArg, firstArg, j));
});
findAvaAssertion("is", j, ast).forEach(p => {
const [firstArg, secondArg] = p.get('arguments').value;
p.replace(buildExpectStatement("toBe", secondArg, firstArg, j));
});
findAvaAssertion("true", j, ast).forEach(p => {
const [firstArg] = p.get('arguments').value;
p.replace(buildExpectStatement("toBeTruthy", firstArg, undefined, j));
});
findAvaAssertion("false", j, ast).forEach(p => {
const [firstArg] = p.get('arguments').value;
p.replace(buildExpectStatement("toBeFalsy", firstArg, undefined, j));
});
findAvaAssertion("throws", j, ast).forEach(p => {
const [firstArg] = p.get('arguments').value;
p.replace(buildExpectStatement("toThrow", firstArg, undefined, j));
});
ast.get().node.comments = comments;
return ast.toSource(printOptions);
};
@dcousineau
Copy link
Author

Please note, requires mockdate npm library and migrates some sinon stuff since we used sinon. You'll most likely have to modify this file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment