diff --git a/src/rules/prefer-todo.ts b/src/rules/prefer-todo.ts index 829a14c41..2a7277b95 100644 --- a/src/rules/prefer-todo.ts +++ b/src/rules/prefer-todo.ts @@ -6,19 +6,15 @@ import { import { FunctionExpression, JestFunctionCallExpression, - StringLiteral, TestCaseName, createRule, getNodeName, + hasOnlyOneArgument, isFunction, isStringNode, isTestCase, } from './tsUtils'; -function isOnlyTestTitle(node: TSESTree.CallExpression) { - return node.arguments.length === 1; -} - function isFunctionBodyEmpty(node: FunctionExpression) { /* istanbul ignore next https://github.com/typescript-eslint/typescript-eslint/issues/734 */ if (!node.body) { @@ -49,16 +45,6 @@ function addTodo( return fixer.replaceText(node.callee, `${testName}.todo`); } -interface CallExpressionWithStringArgument extends TSESTree.CallExpression { - arguments: [StringLiteral | TSESTree.TemplateLiteral]; -} - -function isFirstArgString( - node: TSESTree.CallExpression, -): node is CallExpressionWithStringArgument { - return node.arguments[0] && isStringNode(node.arguments[0]); -} - const isTargetedTestCase = ( node: TSESTree.CallExpression, ): node is JestFunctionCallExpression => @@ -88,7 +74,9 @@ export default createRule({ create(context) { return { CallExpression(node) { - if (!isTargetedTestCase(node) || !isFirstArgString(node)) { + const [firstArg, secondArg] = node.arguments; + + if (!isTargetedTestCase(node) || !isStringNode(firstArg)) { return; } @@ -97,16 +85,13 @@ export default createRule({ messageId: 'todoOverEmpty', node, fix: fixer => [ - fixer.removeRange([ - node.arguments[0].range[1], - node.arguments[1].range[1], - ]), + fixer.removeRange([firstArg.range[1], secondArg.range[1]]), addTodo(node, fixer), ], }); } - if (isOnlyTestTitle(node)) { + if (hasOnlyOneArgument(node)) { context.report({ messageId: 'todoOverUnimplemented', node, diff --git a/src/rules/tsUtils.ts b/src/rules/tsUtils.ts index 87d1c8ceb..4a8a5ff43 100644 --- a/src/rules/tsUtils.ts +++ b/src/rules/tsUtils.ts @@ -108,6 +108,27 @@ export const isStringNode = ( export const getStringValue = (node: StringNode): S => isTemplateLiteral(node) ? node.quasis[0].value.raw : node.value; +/** + * Represents a `CallExpression` with a single argument. + */ +export interface CallExpressionWithSingleArgument< + Argument extends TSESTree.Expression = TSESTree.Expression +> extends TSESTree.CallExpression { + arguments: [Argument]; +} + +/** + * Guards that the given `call` has only one `argument`. + * + * @param {CallExpression} call + * + * @return {call is CallExpressionWithSingleArgument} + */ +export const hasOnlyOneArgument = ( + call: TSESTree.CallExpression, +): call is CallExpressionWithSingleArgument => + call.arguments && call.arguments.length === 1; + /** * Gets the value of the given `AccessorNode`, * account for the different node types.