11import {
22 AST_NODE_TYPES ,
3+ TSESLint ,
34 TSESTree ,
45} from '@typescript-eslint/experimental-utils' ;
56import {
67 EqualityMatcher ,
78 MaybeTypeCast ,
89 ModifierName ,
910 ParsedEqualityMatcherCall ,
11+ ParsedExpectMatcher ,
12+ ParsedExpectModifier ,
1013 createRule ,
1114 followTypeAssertionChain ,
1215 isExpectCall ,
@@ -60,6 +63,49 @@ const getFirstArgument = (matcher: ParsedEqualityMatcherCall) => {
6063 return followTypeAssertionChain ( matcher . arguments [ 0 ] ) ;
6164} ;
6265
66+ type MessageId =
67+ | 'useToBe'
68+ | 'useToBeUndefined'
69+ | 'useToBeDefined'
70+ | 'useToBeNull'
71+ | 'useToBeNaN' ;
72+
73+ type ToBeWhat = MessageId extends `useToBe${infer M } ` ? M : never ;
74+
75+ const reportPreferToBe = (
76+ context : TSESLint . RuleContext < MessageId , unknown [ ] > ,
77+ whatToBe : ToBeWhat ,
78+ matcher : ParsedExpectMatcher ,
79+ modifier ?: ParsedExpectModifier ,
80+ ) => {
81+ const modifierNode = modifier ?. negation || modifier ?. node ;
82+
83+ context . report ( {
84+ messageId : `useToBe${ whatToBe } ` ,
85+ fix ( fixer ) {
86+ const fixes = [
87+ fixer . replaceText ( matcher . node . property , `toBe${ whatToBe } ` ) ,
88+ ] ;
89+
90+ if ( matcher . arguments ?. length && whatToBe !== '' ) {
91+ fixes . push ( fixer . remove ( matcher . arguments [ 0 ] ) ) ;
92+ }
93+
94+ if ( modifierNode ) {
95+ fixes . push (
96+ fixer . removeRange ( [
97+ modifierNode . property . range [ 0 ] - 1 ,
98+ modifierNode . property . range [ 1 ] ,
99+ ] ) ,
100+ ) ;
101+ }
102+
103+ return fixes ;
104+ } ,
105+ node : matcher . node . property ,
106+ } ) ;
107+ } ;
108+
63109export default createRule ( {
64110 name : __filename ,
65111 meta : {
@@ -98,20 +144,12 @@ export default createRule({
98144 ( modifier . name === ModifierName . not || modifier . negation ) &&
99145 [ 'toBeUndefined' , 'toBeDefined' ] . includes ( matcher . name )
100146 ) {
101- const modifierNode = modifier . negation || modifier . node ;
102- const name = matcher . name === 'toBeDefined' ? 'Undefined' : 'Defined' ;
103-
104- context . report ( {
105- fix : fixer => [
106- fixer . replaceText ( matcher . node . property , `toBe${ name } ` ) ,
107- fixer . removeRange ( [
108- modifierNode . property . range [ 0 ] - 1 ,
109- modifierNode . property . range [ 1 ] ,
110- ] ) ,
111- ] ,
112- messageId : `useToBe${ name } ` ,
113- node : matcher . node . property ,
114- } ) ;
147+ reportPreferToBe (
148+ context ,
149+ matcher . name === 'toBeDefined' ? 'Undefined' : 'Defined' ,
150+ matcher ,
151+ modifier ,
152+ ) ;
115153
116154 return ;
117155 }
@@ -121,14 +159,7 @@ export default createRule({
121159 }
122160
123161 if ( isNullEqualityMatcher ( matcher ) ) {
124- context . report ( {
125- fix : fixer => [
126- fixer . replaceText ( matcher . node . property , 'toBeNull' ) ,
127- fixer . remove ( matcher . arguments [ 0 ] ) ,
128- ] ,
129- messageId : 'useToBeNull' ,
130- node : matcher . node . property ,
131- } ) ;
162+ reportPreferToBe ( context , 'Null' , matcher ) ;
132163
133164 return ;
134165 }
@@ -140,42 +171,13 @@ export default createRule({
140171 ? 'Defined'
141172 : 'Undefined' ;
142173
143- context . report ( {
144- fix ( fixer ) {
145- const fixes = [
146- fixer . replaceText ( matcher . node . property , `toBe${ name } ` ) ,
147- fixer . remove ( matcher . arguments [ 0 ] ) ,
148- ] ;
149-
150- const modifierNode = modifier ?. negation || modifier ?. node ;
151-
152- if ( modifierNode ) {
153- fixes . push (
154- fixer . removeRange ( [
155- modifierNode . property . range [ 0 ] - 1 ,
156- modifierNode . property . range [ 1 ] ,
157- ] ) ,
158- ) ;
159- }
160-
161- return fixes ;
162- } ,
163- messageId : `useToBe${ name } ` ,
164- node : matcher . node . property ,
165- } ) ;
174+ reportPreferToBe ( context , name , matcher , modifier ) ;
166175
167176 return ;
168177 }
169178
170179 if ( isNaNEqualityMatcher ( matcher ) ) {
171- context . report ( {
172- fix : fixer => [
173- fixer . replaceText ( matcher . node . property , 'toBeNaN' ) ,
174- fixer . remove ( matcher . arguments [ 0 ] ) ,
175- ] ,
176- messageId : 'useToBeNaN' ,
177- node : matcher . node . property ,
178- } ) ;
180+ reportPreferToBe ( context , 'NaN' , matcher ) ;
179181
180182 return ;
181183 }
@@ -184,11 +186,7 @@ export default createRule({
184186 isPrimitiveLiteral ( matcher ) &&
185187 ! isParsedEqualityMatcherCall ( matcher , EqualityMatcher . toBe )
186188 ) {
187- context . report ( {
188- fix : fixer => fixer . replaceText ( matcher . node . property , 'toBe' ) ,
189- messageId : 'useToBe' ,
190- node : matcher . node . property ,
191- } ) ;
189+ reportPreferToBe ( context , '' , matcher ) ;
192190 }
193191 } ,
194192 } ;
0 commit comments