From 29b1203e68cea79cfaeb51d428171c9d4b90fa62 Mon Sep 17 00:00:00 2001 From: Berkin Anik Date: Tue, 8 Nov 2022 21:31:40 +0300 Subject: [PATCH 1/3] fix(prefer-in-document): crash when on matcher args in toHaveLength --- src/__tests__/lib/rules/prefer-in-document.js | 20 +++++++++++++++++++ src/rules/prefer-in-document.js | 7 ++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/__tests__/lib/rules/prefer-in-document.js b/src/__tests__/lib/rules/prefer-in-document.js index 5e0bd4b..e936616 100644 --- a/src/__tests__/lib/rules/prefer-in-document.js +++ b/src/__tests__/lib/rules/prefer-in-document.js @@ -51,6 +51,10 @@ const valid = [ expect(foo).not.toHaveLength(0)`, `let foo; expect(foo).toHaveLength(1);`, + `let foo; + expect(foo).toHaveLength()`, + `let foo; + expect(foo).toHaveLength(1, 2, 3)`, `expect(screen.notAQuery('foo-bar')).toHaveLength(1)`, `expect(screen.getAllByText('foo-bar')).toHaveLength(2)`, `import foo from "./foo"; @@ -99,6 +103,22 @@ const valid = [ expect(element).toBeInTheDocument`, ]; const invalid = [ + invalidCase( + `expect(screen.getByText('foo')).toHaveLength()`, + `expect(screen.getByText('foo')).not.toBeInTheDocument()` + ), + invalidCase( + `expect(screen.getAllByText('foo')).toHaveLength()`, + `expect(screen.getByText('foo')).not.toBeInTheDocument()` + ), + invalidCase( + `expect(screen.getByRole('foo')).toHaveLength()`, + `expect(screen.getByRole('foo')).not.toBeInTheDocument()` + ), + invalidCase( + `expect(screen.getAllByRole('foo')).toHaveLength()`, + `expect(screen.getByRole('foo')).not.toBeInTheDocument()` + ), invalidCase( `expect(screen.getByText('foo')).toHaveLength(1)`, `expect(screen.getByText('foo')).toBeInTheDocument()` diff --git a/src/rules/prefer-in-document.js b/src/rules/prefer-in-document.js index 8c22611..190c7d5 100644 --- a/src/rules/prefer-in-document.js +++ b/src/rules/prefer-in-document.js @@ -40,7 +40,12 @@ function usesToBeOrToEqualWithNull(matcherNode, matcherArguments) { } function usesToHaveLengthZero(matcherNode, matcherArguments) { - return matcherNode.name === "toHaveLength" && matcherArguments[0].value === 0; + // matcherArguments.length === 0: toHaveLength() will cause jest matcher error + // matcherArguments[0].value: toHaveLength(0, ...) means zero length + return ( + matcherNode.name === "toHaveLength" && + (matcherArguments.length === 0 || matcherArguments[0].value === 0) + ); } export const create = (context) => { From 078f793dc278d31541db285d04e681605ab0baa6 Mon Sep 17 00:00:00 2001 From: Berkin Anik Date: Tue, 8 Nov 2022 21:33:27 +0300 Subject: [PATCH 2/3] fix(prefer-in-document): properly remove all matcher args and commas --- src/__tests__/lib/rules/prefer-in-document.js | 60 +++++++++++++++++++ src/rules/prefer-in-document.js | 6 ++ 2 files changed, 66 insertions(+) diff --git a/src/__tests__/lib/rules/prefer-in-document.js b/src/__tests__/lib/rules/prefer-in-document.js index e936616..adc3a8b 100644 --- a/src/__tests__/lib/rules/prefer-in-document.js +++ b/src/__tests__/lib/rules/prefer-in-document.js @@ -119,6 +119,66 @@ const invalid = [ `expect(screen.getAllByRole('foo')).toHaveLength()`, `expect(screen.getByRole('foo')).not.toBeInTheDocument()` ), + invalidCase( + `expect(screen.getByRole('foo')).toHaveLength(0,2,3)`, + `expect(screen.getByRole('foo')).not.toBeInTheDocument()` + ), + invalidCase( + `expect(screen.getAllByRole('foo')).toHaveLength(0,2,3,)`, + `expect(screen.getByRole('foo')).not.toBeInTheDocument()` + ), + invalidCase( + `expect(screen.getByRole('foo')).toHaveLength(1,2,3)`, + `expect(screen.getByRole('foo')).toBeInTheDocument()` + ), + invalidCase( + `expect(screen.getAllByRole('foo')).toHaveLength(1,2,3,)`, + `expect(screen.getByRole('foo')).toBeInTheDocument()` + ), + invalidCase( + `expect(screen.getAllByRole('foo')).toHaveLength(0//comment +)`, + `expect(screen.getByRole('foo')).not.toBeInTheDocument(//comment +)` + ), + invalidCase( + `expect(screen.getAllByRole('foo')).toHaveLength(1,//comment +)`, + `expect(screen.getByRole('foo')).toBeInTheDocument(//comment +)` + ), + invalidCase( + `expect(screen.getAllByRole('foo')).toHaveLength(0,2,3//comment +)`, + `expect(screen.getByRole('foo')).not.toBeInTheDocument(//comment +)` + ), + invalidCase( + `expect(screen.getAllByRole('foo')).toHaveLength(1,2,3,//comment +)`, + `expect(screen.getByRole('foo')).toBeInTheDocument(//comment +)` + ), + invalidCase( + `expect(screen.getAllByRole('foo')).toHaveLength(0,2,//comment +3,4)`, + `expect(screen.getByRole('foo')).not.toBeInTheDocument(//comment +)` + ), + invalidCase( + `expect(screen.getAllByRole('foo')).toHaveLength(1,2,//comment +3,4,)`, + `expect(screen.getByRole('foo')).toBeInTheDocument(//comment +)` + ), + invalidCase( + `expect(screen.getAllByRole('foo')).toHaveLength(0,2/*comment*/,3)`, + `expect(screen.getByRole('foo')).not.toBeInTheDocument(/*comment*/)` + ), + invalidCase( + `expect(screen.getAllByRole('foo')).toHaveLength(1,2,/*comment*/3,)`, + `expect(screen.getByRole('foo')).toBeInTheDocument(/*comment*/)` + ), invalidCase( `expect(screen.getByText('foo')).toHaveLength(1)`, `expect(screen.getByText('foo')).toBeInTheDocument()` diff --git a/src/rules/prefer-in-document.js b/src/rules/prefer-in-document.js index 190c7d5..f49db23 100644 --- a/src/rules/prefer-in-document.js +++ b/src/rules/prefer-in-document.js @@ -122,6 +122,12 @@ export const create = (context) => { // Remove any arguments in the matcher for (const argument of Array.from(matcherArguments)) { + const sourceCode = context.getSourceCode(); + const token = sourceCode.getTokenAfter(argument); + if (token.value === "," && token.type === "Punctuator") { + // Remove commas if toHaveLength had more than one argument + operations.push(fixer.replaceText(token, "")); + } operations.push(fixer.remove(argument)); } From 92ba227782942b6aa9392a2630fc04afd313deef Mon Sep 17 00:00:00 2001 From: Berkin Anik Date: Tue, 8 Nov 2022 22:11:00 +0300 Subject: [PATCH 3/3] fix(prefer-in-document): update comment on comma removal logic --- src/rules/prefer-in-document.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rules/prefer-in-document.js b/src/rules/prefer-in-document.js index f49db23..d9a5618 100644 --- a/src/rules/prefer-in-document.js +++ b/src/rules/prefer-in-document.js @@ -125,7 +125,7 @@ export const create = (context) => { const sourceCode = context.getSourceCode(); const token = sourceCode.getTokenAfter(argument); if (token.value === "," && token.type === "Punctuator") { - // Remove commas if toHaveLength had more than one argument + // Remove commas if toHaveLength had more than one argument or a trailing comma operations.push(fixer.replaceText(token, "")); } operations.push(fixer.remove(argument));