To do this, I:
- Uninstalled `tap` and replaced it with `borp`
- Wrote a [jscodeshift] codemod (below)
- Updated `instanbul` references to `c8`, which Borp uses internally
- Dropped Node 16 support, which `node:test` requires
- Made a few small manual tweaks
Here's the jscodeshift transformer:
```typescript
import type {
Transform,
Expression,
FunctionExpression,
ArrowFunctionExpression,
} from 'jscodeshift'
const isFunctionExpression = (
expression: Readonly<Expression>
): expression is FunctionExpression | ArrowFunctionExpression =>
expression.type === 'FunctionExpression' ||
expression.type === 'ArrowFunctionExpression'
const transform: Transform = (fileInfo, api) => {
const { j } = api
const root = j(fileInfo.source)
// Update imports
{
const commonJsImport = (varName: string, moduleName: string) =>
j.variableDeclaration('const', [
j.variableDeclarator(
j.identifier(varName),
j.callExpression(j.identifier('require'), [
j.stringLiteral(moduleName),
])
),
])
const tapImport = root.find(j.VariableDeclaration, {
declarations: [
{
init: {
callee: { name: 'require' },
arguments: [
{
value: 'tap',
},
],
},
},
],
})
tapImport.insertBefore(commonJsImport('test', 'node:test'))
tapImport.insertBefore(commonJsImport('assert', 'node:assert/strict'))
tapImport.remove()
}
// Drop args from test callback
root
.find(j.CallExpression, { callee: { name: 'test' } })
.forEach((callExpression) => {
for (const arg of callExpression.value.arguments) {
if (!isFunctionExpression(arg)) continue
arg.params = []
}
})
// Drop t.pass
root
.find(j.ExpressionStatement, {
expression: {
callee: {
type: 'MemberExpression',
object: { name: 't' },
property: { name: 'pass' },
},
},
})
.remove()
// Simple replacements of various calls
{
const toReplace: Map<string, string> = new Map([
['comment', 'console.log'],
['equal', 'assert.equal'],
['fail', 'assert.fail'],
['not', 'assert.notEqual'],
['ok', 'assert.ok'],
['same', 'assert.deepEqual'],
])
for (const [tMethod, memberExpressionString] of toReplace) {
const [newObj, newProp] = memberExpressionString.split('.')
root
.find(j.MemberExpression, {
object: { name: 't' },
property: { name: tMethod },
})
.forEach((memberExpression) => {
memberExpression.value.object = j.identifier(newObj)
memberExpression.value.property = j.identifier(newProp)
})
}
}
// Replace `t.notOk(x)` with `assert.equal(x, false)`.
// Doesn't always work, but works how we use it.
root
.find(j.CallExpression, {
callee: {
type: 'MemberExpression',
object: { name: 't' },
property: { name: 'notOk' },
},
})
.forEach((callExpression) => {
callExpression.value.callee = j.memberExpression(
j.identifier('assert'),
j.identifier('equal')
)
callExpression.value.arguments = [
callExpression.value.arguments[0],
j.booleanLiteral(false),
...callExpression.value.arguments.slice(1),
]
})
// All done!
return root.toSource()
}
export default transform
```
[jscodeshift]: https://github.com/facebook/jscodeshift