diff --git a/src/rules/__tests__/valid-describe.test.ts b/src/rules/__tests__/valid-describe.test.ts index adfbad592..b5e2cd76e 100644 --- a/src/rules/__tests__/valid-describe.test.ts +++ b/src/rules/__tests__/valid-describe.test.ts @@ -9,6 +9,7 @@ const ruleTester = new TSESLint.RuleTester({ ruleTester.run('valid-describe', rule, { valid: [ + 'describe.each()()', 'describe("foo", function() {})', 'describe("foo", () => {})', 'describe(`foo`, () => {})', diff --git a/src/rules/valid-describe.ts b/src/rules/valid-describe.ts index b1f4c8b34..c6682240b 100644 --- a/src/rules/valid-describe.ts +++ b/src/rules/valid-describe.ts @@ -1,6 +1,7 @@ import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/typescript-estree'; import { FunctionExpression, + JestFunctionCallExpression, createRule, isDescribe, isFunction, @@ -25,6 +26,11 @@ const paramsLocation = ( }; }; +const isDescribeEach = (node: JestFunctionCallExpression) => + node.callee.type === AST_NODE_TYPES.MemberExpression && + node.callee.property.type === AST_NODE_TYPES.Identifier && + node.callee.property.name === 'each'; + export default createRule({ name: __filename, meta: { @@ -50,63 +56,64 @@ export default createRule({ create(context) { return { CallExpression(node) { - if (isDescribe(node)) { - if (node.arguments.length === 0) { - return context.report({ - messageId: 'nameAndCallback', - loc: node.loc, - }); - } + if (!isDescribe(node) || isDescribeEach(node)) { + return; + } + + if (node.arguments.length === 0) { + return context.report({ + messageId: 'nameAndCallback', + loc: node.loc, + }); + } + const [name] = node.arguments; + const [, callbackFunction] = node.arguments; + if (!isString(name)) { + context.report({ + messageId: 'firstArgumentMustBeName', + loc: paramsLocation(node.arguments), + }); + } + if (!callbackFunction) { + context.report({ + messageId: 'nameAndCallback', + loc: paramsLocation(node.arguments), + }); - const [name] = node.arguments; - const [, callbackFunction] = node.arguments; - if (!isString(name)) { + return; + } + if (isFunction(callbackFunction)) { + if (isAsync(callbackFunction)) { context.report({ - messageId: 'firstArgumentMustBeName', - loc: paramsLocation(node.arguments), + messageId: 'noAsyncDescribeCallback', + node: callbackFunction, }); } - if (!callbackFunction) { + if (hasParams(callbackFunction)) { context.report({ - messageId: 'nameAndCallback', - loc: paramsLocation(node.arguments), + messageId: 'unexpectedDescribeArgument', + loc: paramsLocation(callbackFunction.params), }); - - return; } - if (isFunction(callbackFunction)) { - if (isAsync(callbackFunction)) { - context.report({ - messageId: 'noAsyncDescribeCallback', - node: callbackFunction, - }); - } - if (hasParams(callbackFunction)) { - context.report({ - messageId: 'unexpectedDescribeArgument', - loc: paramsLocation(callbackFunction.params), - }); - } - if ( - callbackFunction.body && - callbackFunction.body.type === AST_NODE_TYPES.BlockStatement - ) { - callbackFunction.body.body.forEach(node => { - if (node.type === 'ReturnStatement') { - context.report({ - messageId: 'unexpectedReturnInDescribe', - node, - }); - } - }); - } - } else { - context.report({ - messageId: 'secondArgumentMustBeFunction', - loc: paramsLocation(node.arguments), + if ( + callbackFunction.body && + callbackFunction.body.type === AST_NODE_TYPES.BlockStatement + ) { + callbackFunction.body.body.forEach(node => { + if (node.type === 'ReturnStatement') { + context.report({ + messageId: 'unexpectedReturnInDescribe', + node, + }); + } }); - return; } + } else { + context.report({ + messageId: 'secondArgumentMustBeFunction', + loc: paramsLocation(node.arguments), + }); + return; } }, };