1
1
import { AST_NODE_TYPES , TSESTree } from '@typescript-eslint/utils' ;
2
2
import {
3
- ModifierName ,
4
3
createRule ,
5
4
followTypeAssertionChain ,
5
+ getAccessorValue ,
6
6
isBooleanEqualityMatcher ,
7
- isExpectCall ,
8
7
isInstanceOfBinaryExpression ,
9
8
isParsedInstanceOfMatcherCall ,
10
9
isSupportedAccessor ,
11
- parseExpectCall ,
10
+ parseJestFnCall ,
12
11
} from './utils' ;
13
12
14
13
const isArrayIsArrayCall = (
@@ -42,25 +41,21 @@ export default createRule<Options, MessageIds>({
42
41
create ( context ) {
43
42
return {
44
43
CallExpression ( node ) {
45
- if ( ! isExpectCall ( node ) ) {
46
- return ;
47
- }
48
-
49
- const { expect, modifier, matcher } = parseExpectCall ( node ) ;
44
+ const jestFnCall = parseJestFnCall ( node , context ) ;
50
45
51
- if ( ! matcher ) {
46
+ if ( jestFnCall ?. type !== 'expect' ) {
52
47
return ;
53
48
}
54
49
55
- if ( isParsedInstanceOfMatcherCall ( matcher , 'Array' ) ) {
50
+ if ( isParsedInstanceOfMatcherCall ( jestFnCall , 'Array' ) ) {
56
51
context . report ( {
57
- node : matcher . node . property ,
52
+ node : jestFnCall . matcher ,
58
53
messageId : 'preferToBeArray' ,
59
54
fix : fixer => [
60
55
fixer . replaceTextRange (
61
56
[
62
- matcher . node . property . range [ 0 ] ,
63
- matcher . node . property . range [ 1 ] + '(Array)' . length ,
57
+ jestFnCall . matcher . range [ 0 ] ,
58
+ jestFnCall . matcher . range [ 1 ] + '(Array)' . length ,
64
59
] ,
65
60
'toBeArray()' ,
66
61
) ,
@@ -70,11 +65,17 @@ export default createRule<Options, MessageIds>({
70
65
return ;
71
66
}
72
67
68
+ const { parent : expect } = jestFnCall . head . node ;
69
+
70
+ if ( expect ?. type !== AST_NODE_TYPES . CallExpression ) {
71
+ return ;
72
+ }
73
+
73
74
const [ expectArg ] = expect . arguments ;
74
75
75
76
if (
76
77
! expectArg ||
77
- ! isBooleanEqualityMatcher ( matcher ) ||
78
+ ! isBooleanEqualityMatcher ( jestFnCall ) ||
78
79
! (
79
80
isArrayIsArrayCall ( expectArg ) ||
80
81
isInstanceOfBinaryExpression ( expectArg , 'Array' )
@@ -84,11 +85,11 @@ export default createRule<Options, MessageIds>({
84
85
}
85
86
86
87
context . report ( {
87
- node : matcher . node . property ,
88
+ node : jestFnCall . matcher ,
88
89
messageId : 'preferToBeArray' ,
89
90
fix ( fixer ) {
90
91
const fixes = [
91
- fixer . replaceText ( matcher . node . property , 'toBeArray' ) ,
92
+ fixer . replaceText ( jestFnCall . matcher , 'toBeArray' ) ,
92
93
expectArg . type === AST_NODE_TYPES . CallExpression
93
94
? fixer . remove ( expectArg . callee )
94
95
: fixer . removeRange ( [
@@ -97,10 +98,11 @@ export default createRule<Options, MessageIds>({
97
98
] ) ,
98
99
] ;
99
100
100
- let invertCondition = matcher . name === 'toBeFalse' ;
101
+ let invertCondition =
102
+ getAccessorValue ( jestFnCall . matcher ) === 'toBeFalse' ;
101
103
102
- if ( matcher . arguments ? .length ) {
103
- const [ matcherArg ] = matcher . arguments ;
104
+ if ( jestFnCall . args . length ) {
105
+ const [ matcherArg ] = jestFnCall . args ;
104
106
105
107
fixes . push ( fixer . remove ( matcherArg ) ) ;
106
108
@@ -111,13 +113,17 @@ export default createRule<Options, MessageIds>({
111
113
}
112
114
113
115
if ( invertCondition ) {
116
+ const notModifier = jestFnCall . modifiers . find (
117
+ nod => getAccessorValue ( nod ) === 'not' ,
118
+ ) ;
119
+
114
120
fixes . push (
115
- modifier && modifier . name === ModifierName . not
121
+ notModifier
116
122
? fixer . removeRange ( [
117
- modifier . node . property . range [ 0 ] - 1 ,
118
- modifier . node . property . range [ 1 ] ,
123
+ notModifier . range [ 0 ] - 1 ,
124
+ notModifier . range [ 1 ] ,
119
125
] )
120
- : fixer . insertTextBefore ( matcher . node . property , 'not.' ) ,
126
+ : fixer . insertTextBefore ( jestFnCall . matcher , 'not.' ) ,
121
127
) ;
122
128
}
123
129
0 commit comments