From 707b559bbe0268875f3b4cc61c559429db1bf7fe Mon Sep 17 00:00:00 2001 From: Anton Niklasson Date: Wed, 25 Nov 2020 15:21:58 +0100 Subject: [PATCH 1/3] add failing test cases --- src/__tests__/lib/rules/prefer-in-document.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/__tests__/lib/rules/prefer-in-document.js b/src/__tests__/lib/rules/prefer-in-document.js index 917a619..26543dd 100644 --- a/src/__tests__/lib/rules/prefer-in-document.js +++ b/src/__tests__/lib/rules/prefer-in-document.js @@ -35,6 +35,7 @@ const valid = [ ]), `expect(screen.notAQuery('foo-bar')).toHaveLength(1)`, `expect(screen.getByText('foo-bar')).toHaveLength(2)`, + `const element = screen.findByText('lorem ipsum'); expect(element).toBeDefined();`, ]; const invalid = [ // Invalid cases that applies to all variants From aa86e36fcf67ece4cc1c8d133d39b9da9648a789 Mon Sep 17 00:00:00 2001 From: Anton Niklasson Date: Wed, 25 Nov 2020 16:08:47 +0100 Subject: [PATCH 2/3] lint only for-sure valid TL queries --- src/__tests__/lib/rules/prefer-in-document.js | 6 +++++- src/rules/prefer-in-document.js | 16 ++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/__tests__/lib/rules/prefer-in-document.js b/src/__tests__/lib/rules/prefer-in-document.js index 26543dd..bfc0b19 100644 --- a/src/__tests__/lib/rules/prefer-in-document.js +++ b/src/__tests__/lib/rules/prefer-in-document.js @@ -35,7 +35,11 @@ const valid = [ ]), `expect(screen.notAQuery('foo-bar')).toHaveLength(1)`, `expect(screen.getByText('foo-bar')).toHaveLength(2)`, - `const element = screen.findByText('lorem ipsum'); expect(element).toBeDefined();`, + + `expect(foo).toBeDefined();`, + `expect(foo).not.toBeDefined();`, + `expect(foo).toBeNull();`, + `expect(foo).not.toBeNull();`, ]; const invalid = [ // Invalid cases that applies to all variants diff --git a/src/rules/prefer-in-document.js b/src/rules/prefer-in-document.js index fd06149..6828d9d 100644 --- a/src/rules/prefer-in-document.js +++ b/src/rules/prefer-in-document.js @@ -29,15 +29,19 @@ function isAntonymMatcher(matcherNode, matcherArguments) { function check( context, - { queryNode, matcherNode, matcherArguments, negatedMatcher } + { subject, matcherNode, matcherArguments, negatedMatcher } ) { - const query = queryNode.name || queryNode.property.name; + if (subject.type !== "CallExpression") { + return; + } // toHaveLength() is only invalid with 0 or 1 if (matcherNode.name === "toHaveLength" && matcherArguments[0].value > 1) { return; } + const query = subject.callee.name || subject.callee.property.name; + if (queries.includes(query)) { context.report({ node: matcherNode, @@ -82,13 +86,13 @@ export const create = (context) => { [`CallExpression[callee.object.object.callee.name='expect'][callee.object.property.name='not'][callee.property.name=${alternativeMatchers}]`]( node ) { - const queryNode = node.callee.object.object.arguments[0].callee; + const subject = node.callee.object.object.arguments[0]; const matcherNode = node.callee.property; const matcherArguments = node.arguments; check(context, { negatedMatcher: true, - queryNode, + subject, matcherNode, matcherArguments, }); @@ -98,13 +102,13 @@ export const create = (context) => { [`CallExpression[callee.object.callee.name='expect'][callee.property.name=${alternativeMatchers}]`]( node ) { - const queryNode = node.callee.object.arguments[0].callee; + const subject = node.callee.object.arguments[0]; const matcherNode = node.callee.property; const matcherArguments = node.arguments; check(context, { negatedMatcher: false, - queryNode, + subject, matcherNode, matcherArguments, }); From 2852d11fbab0a5a34fbc48f8798056f06cb00dc9 Mon Sep 17 00:00:00 2001 From: Anton Niklasson Date: Fri, 27 Nov 2020 22:35:49 +0100 Subject: [PATCH 3/3] backtrack variable in prefer-document to look for TL queries --- src/__tests__/lib/rules/prefer-in-document.js | 15 ++++++++++----- src/rules/prefer-in-document.js | 18 ++++++++++++++++-- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/__tests__/lib/rules/prefer-in-document.js b/src/__tests__/lib/rules/prefer-in-document.js index bfc0b19..75aac07 100644 --- a/src/__tests__/lib/rules/prefer-in-document.js +++ b/src/__tests__/lib/rules/prefer-in-document.js @@ -35,11 +35,8 @@ const valid = [ ]), `expect(screen.notAQuery('foo-bar')).toHaveLength(1)`, `expect(screen.getByText('foo-bar')).toHaveLength(2)`, - - `expect(foo).toBeDefined();`, - `expect(foo).not.toBeDefined();`, - `expect(foo).toBeNull();`, - `expect(foo).not.toBeNull();`, + `expect(undefinedVariable).toBeDefined()`, + `expect([1,2,3]).toHaveLength(1);`, ]; const invalid = [ // Invalid cases that applies to all variants @@ -56,6 +53,14 @@ const invalid = [ `expect(wrapper.${q}('foo')).toHaveLength(1)`, `expect(wrapper.${q}('foo')).toBeInTheDocument()` ), + invalidCase( + `const element = screen.${q}('foo'); expect(element).toHaveLength(1);`, + `const element = screen.${q}('foo'); expect(element).toBeInTheDocument();` + ), + invalidCase( + `const element = ${q}('foo'); expect(element).toBeNull();`, + `const element = ${q}('foo'); expect(element).not.toBeInTheDocument();` + ), ]), // Invalid cases that applies to queryBy* and queryAllBy* ...queriesByVariant.query.map((q) => [ diff --git a/src/rules/prefer-in-document.js b/src/rules/prefer-in-document.js index 6828d9d..ec7a0b5 100644 --- a/src/rules/prefer-in-document.js +++ b/src/rules/prefer-in-document.js @@ -31,7 +31,19 @@ function check( context, { subject, matcherNode, matcherArguments, negatedMatcher } ) { - if (subject.type !== "CallExpression") { + let query; + + if (subject.type === "Identifier") { + // Backtrack the variable to see if it was populated by a query. + try { + const variable = context + .getScope() + .variables.find((v) => v.name === subject.name).defs[0].node.init; + query = variable.callee.name || variable.callee.property.name; + } catch (error) { + return; + } + } else if (subject.type !== "CallExpression") { return; } @@ -40,7 +52,9 @@ function check( return; } - const query = subject.callee.name || subject.callee.property.name; + if (!query) { + query = subject.callee.name || subject.callee.property.name; + } if (queries.includes(query)) { context.report({