mirror of
https://github.com/toss/es-toolkit.git
synced 2024-11-28 03:34:26 +03:00
chore(script): enhance transforming lodash test codes script (#546)
* Handle import lodash methods * Supports assert.deepStrictEqual * Enhance brokenSyntax * Update assert * Enhance import * Enhance Error log * Enhance brokenSyntax and add commenting delete local variable
This commit is contained in:
parent
c21874ef3b
commit
f53bfd5c34
@ -1,21 +1,54 @@
|
||||
export function formatBrokenSyntax(source: string): string {
|
||||
// Fix broken syntax
|
||||
const brokenMatched = source.match(/(?<=,)[\s\d\w?]+\[.+\).toEqual\((?!\[).+\]\);/g);
|
||||
if (brokenMatched != null) {
|
||||
for (const match of brokenMatched) {
|
||||
const splited = match.split(').toEqual(');
|
||||
const formatted = `).toEqual(${splited.join(', ')}`;
|
||||
source = source.replace(match, formatted);
|
||||
}
|
||||
function fixExpectFunction(source: string): string {
|
||||
const expectMatched = source.match(/expect(\(.+\)).toEqual.+\);/g);
|
||||
|
||||
if (!expectMatched) {
|
||||
return source;
|
||||
}
|
||||
|
||||
// Remove deleting local variable
|
||||
const deleteMatched = source.match(/delete [\w\d]+;/g);
|
||||
if (deleteMatched != null) {
|
||||
for (const match of deleteMatched) {
|
||||
source = source.replace(match, '');
|
||||
const splitMatched = expectMatched.map(match => match.split('.toEqual('));
|
||||
const brokenSyntax = splitMatched.map(([expect]) => {
|
||||
let count = 0;
|
||||
|
||||
for (const char of expect) {
|
||||
if (['(', '{', '['].includes(char)) {
|
||||
count++;
|
||||
} else if ([')', '}', ']'].includes(char)) {
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
return count > 0;
|
||||
});
|
||||
|
||||
for (let i = 0; i < expectMatched.length; i++) {
|
||||
if (brokenSyntax[i]) {
|
||||
const front = splitMatched[i][0];
|
||||
const startWithBracket = front.match(/expect\([{[].+[}\]],/);
|
||||
const startWithFunction = front.match(/expect\(.+\(.+\),/);
|
||||
|
||||
const start = startWithFunction
|
||||
? startWithFunction[0].length
|
||||
: startWithBracket
|
||||
? startWithBracket[0].length
|
||||
: front.indexOf(',') + 1;
|
||||
const fixed = `${front.slice(0, start)}).toEqual(${front.slice(start, front.length - 1)}, ${splitMatched[i][1]}`;
|
||||
|
||||
source = source.replace(expectMatched[i], fixed);
|
||||
}
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
export function formatBrokenSyntax(source: string): string {
|
||||
// Fix broken syntax
|
||||
source = fixExpectFunction(source);
|
||||
|
||||
// `delete localvariable` to comment
|
||||
source = source.replace(
|
||||
/delete [^.[\]]+;/g,
|
||||
match => `// Deleting local variable in strict mode. So commenting it out.\n// ${match}`
|
||||
);
|
||||
|
||||
return source;
|
||||
}
|
||||
|
53
.scripts/tests/_internal/transform/assert.ts
Normal file
53
.scripts/tests/_internal/transform/assert.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import type { Collection, JSCodeshift } from 'jscodeshift';
|
||||
|
||||
export function transformAssert(root: Collection, jscodeshift: JSCodeshift): void {
|
||||
// Change `assert.deepStrictEqual(a, b, c)` to `expect(a, c).toEqual(b)`
|
||||
root
|
||||
.find(jscodeshift.CallExpression, {
|
||||
callee: {
|
||||
type: 'MemberExpression',
|
||||
object: {
|
||||
name: 'assert',
|
||||
},
|
||||
property: {
|
||||
type: 'Identifier',
|
||||
},
|
||||
},
|
||||
})
|
||||
.replaceWith(({ node }) => {
|
||||
if (node.callee.type === 'MemberExpression' && node.callee.property.type === 'Identifier') {
|
||||
const expectArguments =
|
||||
node.arguments.length === 3 ? [node.arguments[0], node.arguments[2]] : [node.arguments[0]];
|
||||
const expect = jscodeshift.callExpression(jscodeshift.identifier('expect'), expectArguments);
|
||||
|
||||
switch (node.callee.property.name) {
|
||||
case 'deepStrictEqual':
|
||||
return jscodeshift.memberExpression(
|
||||
expect,
|
||||
jscodeshift.callExpression(jscodeshift.identifier('toEqual'), [node.arguments[1]])
|
||||
);
|
||||
case 'deepEqual':
|
||||
return jscodeshift.memberExpression(
|
||||
expect,
|
||||
jscodeshift.callExpression(jscodeshift.identifier('toEqual'), [node.arguments[1]])
|
||||
);
|
||||
case 'strictEqual':
|
||||
return jscodeshift.memberExpression(
|
||||
expect,
|
||||
jscodeshift.callExpression(jscodeshift.identifier('toBe'), [node.arguments[1]])
|
||||
);
|
||||
case 'notEqual':
|
||||
return jscodeshift.memberExpression(
|
||||
expect,
|
||||
jscodeshift.callExpression(jscodeshift.identifier('not.toBe'), [node.arguments[1]])
|
||||
);
|
||||
case 'notStrictEqual':
|
||||
return jscodeshift.memberExpression(
|
||||
expect,
|
||||
jscodeshift.callExpression(jscodeshift.identifier('not.toBe'), [node.arguments[1]])
|
||||
);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
});
|
||||
}
|
@ -35,15 +35,44 @@ export function transformImport(root: Collection, jscodeshift: JSCodeshift): voi
|
||||
.remove();
|
||||
|
||||
// Add import { describe, it, expect } from 'vitest';
|
||||
const vitestImport = jscodeshift.importDeclaration(
|
||||
[
|
||||
jscodeshift.importSpecifier(jscodeshift.identifier('describe')),
|
||||
jscodeshift.importSpecifier(jscodeshift.identifier('it')),
|
||||
jscodeshift.importSpecifier(jscodeshift.identifier('expect')),
|
||||
const vitestImport = root.find(jscodeshift.ImportDeclaration, {
|
||||
source: {
|
||||
value: 'vitest',
|
||||
},
|
||||
specifiers: [
|
||||
{
|
||||
type: 'ImportSpecifier',
|
||||
imported: {
|
||||
name: 'describe',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'ImportSpecifier',
|
||||
imported: {
|
||||
name: 'it',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'ImportSpecifier',
|
||||
imported: {
|
||||
name: 'expect',
|
||||
},
|
||||
},
|
||||
],
|
||||
jscodeshift.literal('vitest')
|
||||
);
|
||||
astPath.value.program.body.unshift(vitestImport);
|
||||
});
|
||||
|
||||
if (!vitestImport.length) {
|
||||
astPath.value.program.body.unshift(
|
||||
jscodeshift.importDeclaration(
|
||||
[
|
||||
jscodeshift.importSpecifier(jscodeshift.identifier('describe')),
|
||||
jscodeshift.importSpecifier(jscodeshift.identifier('it')),
|
||||
jscodeshift.importSpecifier(jscodeshift.identifier('expect')),
|
||||
],
|
||||
jscodeshift.literal('vitest')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Remove import from 'lodash'
|
||||
root
|
||||
@ -53,4 +82,28 @@ export function transformImport(root: Collection, jscodeshift: JSCodeshift): voi
|
||||
},
|
||||
})
|
||||
.remove();
|
||||
|
||||
// Change '../src/merge' to '../index'
|
||||
const methodSet = new Set<string>();
|
||||
root
|
||||
.find(jscodeshift.ImportDeclaration, {
|
||||
source: {
|
||||
value: (value: string) => value.startsWith('../src/'),
|
||||
},
|
||||
})
|
||||
.forEach(({ node }) => {
|
||||
if (node.specifiers && node.specifiers[0].type === 'ImportDefaultSpecifier' && node.specifiers[0].local) {
|
||||
methodSet.add(node.specifiers[0].local.name);
|
||||
}
|
||||
})
|
||||
.remove();
|
||||
|
||||
if (methodSet.size) {
|
||||
const methodImport = jscodeshift.importDeclaration(
|
||||
Array.from(methodSet).map(method => jscodeshift.importSpecifier(jscodeshift.identifier(method))),
|
||||
jscodeshift.literal('../index')
|
||||
);
|
||||
|
||||
astPath.value.program.body.unshift(methodImport);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
import type { Collection, JSCodeshift } from 'jscodeshift';
|
||||
|
||||
export function transformLodashStable(root: Collection, jscodeshift: JSCodeshift): void {
|
||||
// Replace lodashStable.each and lodashStable.map with Array.prototype.forEach and Array.prototype.map
|
||||
const astPath = root.getAST()[0];
|
||||
let needImportEsToolkit = false;
|
||||
|
||||
root
|
||||
.find(jscodeshift.CallExpression, {
|
||||
callee: {
|
||||
@ -28,10 +30,19 @@ export function transformLodashStable(root: Collection, jscodeshift: JSCodeshift
|
||||
node.callee.object = node.arguments[0] as any;
|
||||
return jscodeshift.callExpression(node.callee, node.arguments.slice(1));
|
||||
}
|
||||
|
||||
// Remove lodashStable from the callee
|
||||
return jscodeshift.callExpression(node.callee.property, node.arguments);
|
||||
node.callee.object = jscodeshift.identifier('esToolkit');
|
||||
needImportEsToolkit = true;
|
||||
}
|
||||
return node;
|
||||
});
|
||||
|
||||
if (needImportEsToolkit) {
|
||||
const esToolkitImport = jscodeshift.importDeclaration(
|
||||
[jscodeshift.importNamespaceSpecifier(jscodeshift.identifier('esToolkit'))],
|
||||
jscodeshift.literal('../index')
|
||||
);
|
||||
|
||||
astPath.value.program.body.unshift(esToolkitImport);
|
||||
}
|
||||
}
|
||||
|
@ -2,17 +2,19 @@ import type { API, FileInfo } from 'jscodeshift';
|
||||
import { formatBrokenSyntax } from './_internal/formatter/brokenSyntax';
|
||||
import { transformImport } from './_internal/transform/import';
|
||||
import { transformLodashStable } from './_internal/transform/lodashStable';
|
||||
import { transformAssert } from './_internal/transform/assert';
|
||||
|
||||
export default function transform(file: FileInfo, { jscodeshift }: API) {
|
||||
try {
|
||||
const root = jscodeshift(formatBrokenSyntax(file.source));
|
||||
|
||||
transformImport(root, jscodeshift);
|
||||
transformLodashStable(root, jscodeshift);
|
||||
transformImport(root, jscodeshift);
|
||||
transformAssert(root, jscodeshift);
|
||||
|
||||
return root.toSource();
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
console.error(`File Path: ${file.path}`);
|
||||
console.error(`Error Messaging: ${error.message}`);
|
||||
console.error('Please resolve the error before continuing.');
|
||||
console.error('If you need help, please open an issue on GitHub.');
|
||||
|
Loading…
Reference in New Issue
Block a user