@@ -6,12 +6,12 @@ import {
66import {
77 CallExpressionWithSingleArgument ,
88 DescribeAlias ,
9- JestFunctionCallExpressionWithIdentifierCallee ,
109 StringNode ,
1110 TestCaseName ,
1211 createRule ,
1312 getStringValue ,
1413 isDescribe ,
14+ isEachCall ,
1515 isStringNode ,
1616 isTestCase ,
1717} from './utils' ;
@@ -21,38 +21,37 @@ type IgnorableFunctionExpressions =
2121 | TestCaseName . test
2222 | DescribeAlias . describe ;
2323
24- type CallExpressionWithCorrectCalleeAndArguments = JestFunctionCallExpressionWithIdentifierCallee < IgnorableFunctionExpressions > &
25- CallExpressionWithSingleArgument < StringNode > ;
26-
2724const hasStringAsFirstArgument = (
2825 node : TSESTree . CallExpression ,
2926) : node is CallExpressionWithSingleArgument < StringNode > =>
3027 node . arguments [ 0 ] && isStringNode ( node . arguments [ 0 ] ) ;
3128
32- const isJestFunctionWithLiteralArg = (
29+ const findNodeNameAndArgument = (
3330 node : TSESTree . CallExpression ,
34- ) : node is CallExpressionWithCorrectCalleeAndArguments =>
35- ( isTestCase ( node ) || isDescribe ( node ) ) &&
36- node . callee . type === AST_NODE_TYPES . Identifier &&
37- hasStringAsFirstArgument ( node ) ;
38-
39- const jestFunctionName = (
40- node : CallExpressionWithCorrectCalleeAndArguments ,
41- allowedPrefixes : readonly string [ ] ,
42- ) => {
43- const description = getStringValue ( node . arguments [ 0 ] ) ;
44-
45- if ( allowedPrefixes . some ( name => description . startsWith ( name ) ) ) {
31+ ) : [ name : string , firstArg : StringNode ] | null => {
32+ if ( ! ( isTestCase ( node ) || isDescribe ( node ) ) ) {
4633 return null ;
4734 }
4835
49- const firstCharacter = description . charAt ( 0 ) ;
36+ if ( isEachCall ( node ) ) {
37+ if (
38+ node . parent ?. type === AST_NODE_TYPES . CallExpression &&
39+ hasStringAsFirstArgument ( node . parent )
40+ ) {
41+ return [ node . callee . object . name , node . parent . arguments [ 0 ] ] ;
42+ }
43+
44+ return null ;
45+ }
5046
51- if ( ! firstCharacter || firstCharacter === firstCharacter . toLowerCase ( ) ) {
47+ if (
48+ node . callee . type !== AST_NODE_TYPES . Identifier ||
49+ ! hasStringAsFirstArgument ( node )
50+ ) {
5251 return null ;
5352 }
5453
55- return node . callee . name ;
54+ return [ node . callee . name , node . arguments [ 0 ] ] ;
5655} ;
5756
5857export default createRule <
@@ -117,10 +116,6 @@ export default createRule<
117116
118117 return {
119118 CallExpression ( node : TSESTree . CallExpression ) {
120- if ( ! isJestFunctionWithLiteralArg ( node ) ) {
121- return ;
122- }
123-
124119 if ( isDescribe ( node ) ) {
125120 numberOfDescribeBlocks ++ ;
126121
@@ -129,32 +124,50 @@ export default createRule<
129124 }
130125 }
131126
132- const erroneousMethod = jestFunctionName ( node , allowedPrefixes ) ;
133-
134- if ( erroneousMethod && ! ignore . includes ( node . callee . name ) ) {
135- context . report ( {
136- messageId : 'unexpectedLowercase' ,
137- node : node . arguments [ 0 ] ,
138- data : { method : erroneousMethod } ,
139- fix ( fixer ) {
140- const [ firstArg ] = node . arguments ;
141-
142- const description = getStringValue ( firstArg ) ;
143-
144- const rangeIgnoringQuotes : TSESLint . AST . Range = [
145- firstArg . range [ 0 ] + 1 ,
146- firstArg . range [ 1 ] - 1 ,
147- ] ;
148- const newDescription =
149- description . substring ( 0 , 1 ) . toLowerCase ( ) +
150- description . substring ( 1 ) ;
151-
152- return [
153- fixer . replaceTextRange ( rangeIgnoringQuotes , newDescription ) ,
154- ] ;
155- } ,
156- } ) ;
127+ const results = findNodeNameAndArgument ( node ) ;
128+
129+ if ( ! results ) {
130+ return ;
157131 }
132+
133+ const [ name , firstArg ] = results ;
134+
135+ const description = getStringValue ( firstArg ) ;
136+
137+ if ( allowedPrefixes . some ( name => description . startsWith ( name ) ) ) {
138+ return ;
139+ }
140+
141+ const firstCharacter = description . charAt ( 0 ) ;
142+
143+ if (
144+ ! firstCharacter ||
145+ firstCharacter === firstCharacter . toLowerCase ( ) ||
146+ ignore . includes ( name as IgnorableFunctionExpressions )
147+ ) {
148+ return ;
149+ }
150+
151+ context . report ( {
152+ messageId : 'unexpectedLowercase' ,
153+ node : node . arguments [ 0 ] ,
154+ data : { method : name } ,
155+ fix ( fixer ) {
156+ const description = getStringValue ( firstArg ) ;
157+
158+ const rangeIgnoringQuotes : TSESLint . AST . Range = [
159+ firstArg . range [ 0 ] + 1 ,
160+ firstArg . range [ 1 ] - 1 ,
161+ ] ;
162+ const newDescription =
163+ description . substring ( 0 , 1 ) . toLowerCase ( ) +
164+ description . substring ( 1 ) ;
165+
166+ return [
167+ fixer . replaceTextRange ( rangeIgnoringQuotes , newDescription ) ,
168+ ] ;
169+ } ,
170+ } ) ;
158171 } ,
159172 'CallExpression:exit' ( node : TSESTree . CallExpression ) {
160173 if ( isDescribe ( node ) ) {
0 commit comments