Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit bf4871f

Browse files
authored
fix(no-node-access): narrow detection to Testing Library queries (#1064)
Closes #1063 Closes #1041
1 parent 1467a18 commit bf4871f

File tree

3 files changed

+703
-90
lines changed

3 files changed

+703
-90
lines changed

‎lib/rules/no-node-access.ts

Lines changed: 22 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
1-
import {
2-
DefinitionType,
3-
type ScopeVariable,
4-
} from '@typescript-eslint/scope-manager';
51
import { TSESTree, ASTUtils } from '@typescript-eslint/utils';
62

73
import { createTestingLibraryRule } from '../create-testing-library-rule';
84
import {
95
getDeepestIdentifierNode,
10-
getPropertyIdentifierNode,
11-
isCallExpression,
6+
isLiteral,
127
isMemberExpression,
138
} from '../node-utils';
149
import {
10+
ALL_QUERIES_COMBINATIONS,
1511
ALL_RETURNING_NODES,
1612
EVENT_HANDLER_METHODS,
17-
getScope,
1813
resolveToTestingLibraryFn,
1914
} from '../utils';
2015

@@ -60,8 +55,6 @@ export default createTestingLibraryRule<Options, MessageIds>({
6055
],
6156

6257
create(context, [{ allowContainerFirstChild = false }], helpers) {
63-
const userEventInstanceNames = new Set<string>();
64-
6558
function showErrorForNodeAccess(node: TSESTree.MemberExpression) {
6659
// This rule is so aggressive that can cause tons of false positives outside test files when Aggressive Reporting
6760
// is enabled. Because of that, this rule will skip this mechanism and report only if some Testing Library package
@@ -99,94 +92,44 @@ export default createTestingLibraryRule<Options, MessageIds>({
9992
}
10093
}
10194

102-
function detectTestingLibraryFn(
103-
node: TSESTree.CallExpression,
104-
variable: ScopeVariable | null
95+
function getProperty(
96+
node: TSESTree.PrivateIdentifier | TSESTree.Expression
10597
) {
106-
if (variable && variable.defs.length > 0) {
107-
const def = variable.defs[0];
108-
if (
109-
def.type === DefinitionType.Variable &&
110-
isCallExpression(def.node.init)
111-
) {
112-
return resolveToTestingLibraryFn(def.node.init, context);
113-
}
98+
if (isLiteral(node)) {
99+
return node;
114100
}
115101

116-
return resolveToTestingLibraryFn(node,context);
102+
return getDeepestIdentifierNode(node);
117103
}
118104

119105
return {
120106
CallExpression(node: TSESTree.CallExpression) {
121-
const property = getDeepestIdentifierNode(node);
122-
const identifier = getPropertyIdentifierNode(node);
123-
124-
const isEventHandlerMethod = EVENT_HANDLER_METHODS.some(
125-
(method) => method === property?.name
126-
);
127-
const hasUserEventInstanceName = userEventInstanceNames.has(
128-
identifier?.name ?? ''
129-
);
130-
131-
const variable = identifier
132-
? ASTUtils.findVariable(getScope(context, node), identifier)
133-
: null;
134-
const testingLibraryFn = detectTestingLibraryFn(node, variable);
107+
if (!isMemberExpression(node.callee)) return;
135108

109+
const { callee } = node;
136110
if (
137-
!testingLibraryFn&&
138-
isEventHandlerMethod&&
139-
!hasUserEventInstanceName
111+
!EVENT_HANDLER_METHODS.some(
112+
(method)=>method===ASTUtils.getPropertyName(callee)
113+
)
140114
) {
141-
context.report({
142-
node,
143-
loc: property?.loc.start,
144-
messageId: 'noNodeAccess',
145-
});
146-
}
147-
},
148-
VariableDeclarator(node: TSESTree.VariableDeclarator) {
149-
const { init, id } = node;
150-
151-
if (!isCallExpression(init)) {
152115
return;
153116
}
117+
const identifier = getDeepestIdentifierNode(callee.object);
154118

155119
if (
156-
!isMemberExpression(init.callee) ||
157-
!ASTUtils.isIdentifier(init.callee.object)
120+
!identifier ||
121+
!ALL_QUERIES_COMBINATIONS.includes(identifier.name)
158122
) {
159123
return;
160124
}
161125

162-
const testingLibraryFn = resolveToTestingLibraryFn(init, context);
163-
if (
164-
init.callee.object.name === testingLibraryFn?.local &&
165-
ASTUtils.isIdentifier(init.callee.property) &&
166-
init.callee.property.name === 'setup' &&
167-
ASTUtils.isIdentifier(id)
168-
) {
169-
userEventInstanceNames.add(id.name);
170-
}
171-
},
172-
AssignmentExpression(node: TSESTree.AssignmentExpression) {
173-
if (
174-
ASTUtils.isIdentifier(node.left) &&
175-
isCallExpression(node.right) &&
176-
isMemberExpression(node.right.callee) &&
177-
ASTUtils.isIdentifier(node.right.callee.object)
178-
) {
179-
const testingLibraryFn = resolveToTestingLibraryFn(
180-
node.right,
181-
context
182-
);
183-
if (
184-
node.right.callee.object.name === testingLibraryFn?.local &&
185-
ASTUtils.isIdentifier(node.right.callee.property) &&
186-
node.right.callee.property.name === 'setup'
187-
) {
188-
userEventInstanceNames.add(node.left.name);
189-
}
126+
if (resolveToTestingLibraryFn(node, context)) {
127+
const property = getProperty(callee.property);
128+
context.report({
129+
node,
130+
loc: property?.loc.start,
131+
messageId: 'noNodeAccess',
132+
});
190133
}
191134
},
192135
'ExpressionStatement MemberExpression': showErrorForNodeAccess,

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /