diff --git a/src/rules/__tests__/prefer-comparison-matcher.test.ts b/src/rules/__tests__/prefer-comparison-matcher.test.ts index b46833188..7d5d805c6 100644 --- a/src/rules/__tests__/prefer-comparison-matcher.test.ts +++ b/src/rules/__tests__/prefer-comparison-matcher.test.ts @@ -40,6 +40,18 @@ const generateInvalidCases = ( }, ], }, + { + code: `expect(value ${operator} 1).resolves.${equalityMatcher}(true);`, + output: `expect(value).resolves.${preferredMatcher}(1);`, + errors: [ + { + messageId: 'useToBeComparison', + data: { preferredMatcher }, + column: 27 + operator.length, + line: 1, + }, + ], + }, { code: `expect(value ${operator} 1).${equalityMatcher}(false);`, output: `expect(value).${preferredMatcherWhenNegated}(1);`, @@ -64,6 +76,18 @@ const generateInvalidCases = ( }, ], }, + { + code: `expect(value ${operator} 1).resolves.${equalityMatcher}(false);`, + output: `expect(value).resolves.${preferredMatcherWhenNegated}(1);`, + errors: [ + { + messageId: 'useToBeComparison', + data: { preferredMatcher: preferredMatcherWhenNegated }, + column: 27 + operator.length, + line: 1, + }, + ], + }, { code: `expect(value ${operator} 1).not.${equalityMatcher}(true);`, output: `expect(value).${preferredMatcherWhenNegated}(1);`, @@ -88,6 +112,18 @@ const generateInvalidCases = ( }, ], }, + { + code: `expect(value ${operator} 1).resolves.not.${equalityMatcher}(true);`, + output: `expect(value).resolves.${preferredMatcherWhenNegated}(1);`, + errors: [ + { + messageId: 'useToBeComparison', + data: { preferredMatcher: preferredMatcherWhenNegated }, + column: 27 + operator.length, + line: 1, + }, + ], + }, { code: `expect(value ${operator} 1).not.${equalityMatcher}(false);`, output: `expect(value).${preferredMatcher}(1);`, @@ -100,6 +136,54 @@ const generateInvalidCases = ( }, ], }, + { + code: `expect(value ${operator} 1).resolves.not.${equalityMatcher}(false);`, + output: `expect(value).resolves.${preferredMatcher}(1);`, + errors: [ + { + messageId: 'useToBeComparison', + data: { preferredMatcher }, + column: 27 + operator.length, + line: 1, + }, + ], + }, + { + code: `expect(value ${operator} 1)["resolves"].not.${equalityMatcher}(false);`, + output: `expect(value).resolves.${preferredMatcher}(1);`, + errors: [ + { + messageId: 'useToBeComparison', + data: { preferredMatcher }, + column: 30 + operator.length, + line: 1, + }, + ], + }, + { + code: `expect(value ${operator} 1)["resolves"]["not"].${equalityMatcher}(false);`, + output: `expect(value).resolves.${preferredMatcher}(1);`, + errors: [ + { + messageId: 'useToBeComparison', + data: { preferredMatcher }, + column: 30 + operator.length, + line: 1, + }, + ], + }, + { + code: `expect(value ${operator} 1)["resolves"]["not"]['${equalityMatcher}'](false);`, + output: `expect(value).resolves.${preferredMatcher}(1);`, + errors: [ + { + messageId: 'useToBeComparison', + data: { preferredMatcher }, + column: 30 + operator.length, + line: 1, + }, + ], + }, ]; }; @@ -128,6 +212,8 @@ const generateValidStringLiteralCases = (operator: string, matcher: string) => { `expect(${b} ${operator} ${a}).not.${matcher}(true)`, `expect(${b} ${operator} ${a}).not.${matcher}(false)`, `expect(${b} ${operator} ${b}).not.${matcher}(false)`, + `expect(${b} ${operator} ${b}).resolves.not.${matcher}(false)`, + `expect(${b} ${operator} ${b}).resolves.${matcher}(false)`, ], ]); }; diff --git a/src/rules/prefer-comparison-matcher.ts b/src/rules/prefer-comparison-matcher.ts index 0174f651e..214678737 100644 --- a/src/rules/prefer-comparison-matcher.ts +++ b/src/rules/prefer-comparison-matcher.ts @@ -1,6 +1,7 @@ import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils'; import { MaybeTypeCast, + ModifierName, ParsedEqualityMatcherCall, ParsedExpectMatcher, createRule, @@ -122,9 +123,15 @@ export default createRule({ return; } + const negation = modifier?.negation + ? { node: modifier.negation } + : modifier?.name === ModifierName.not + ? modifier + : null; + const preferredMatcher = determineMatcher( comparison.operator, - followTypeAssertionChain(matcher.arguments[0]).value === !!modifier, + followTypeAssertionChain(matcher.arguments[0]).value === !!negation, ); if (!preferredMatcher) { @@ -135,6 +142,12 @@ export default createRule({ fix(fixer) { const sourceCode = context.getSourceCode(); + // preserve the existing modifier if it's not a negation + const modifierText = + modifier && modifier?.node !== negation?.node + ? `.${modifier.name}` + : ''; + return [ // replace the comparison argument with the left-hand side of the comparison fixer.replaceText( @@ -144,7 +157,7 @@ export default createRule({ // replace the current matcher & modifier with the preferred matcher fixer.replaceTextRange( [expectCallEnd, matcher.node.range[1]], - `.${preferredMatcher}`, + `${modifierText}.${preferredMatcher}`, ), // replace the matcher argument with the right-hand side of the comparison fixer.replaceText( @@ -155,7 +168,7 @@ export default createRule({ }, messageId: 'useToBeComparison', data: { preferredMatcher }, - node: (modifier || matcher).node.property, + node: (negation || matcher).node.property, }); }, };