From 395bef54c9f80cce3042e0e5930797d8d84b27b5 Mon Sep 17 00:00:00 2001 From: Hasegawa-Yukihiro Date: Sun, 3 Aug 2025 00:14:53 +0900 Subject: [PATCH 1/2] fix: add support for AssignmentExpression --- lib/rules/no-node-access.ts | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/rules/no-node-access.ts b/lib/rules/no-node-access.ts index faecf12e..b905275d 100644 --- a/lib/rules/no-node-access.ts +++ b/lib/rules/no-node-access.ts @@ -12,8 +12,6 @@ export const RULE_NAME = 'no-node-access'; export type MessageIds = 'noNodeAccess'; export type Options = [{ allowContainerFirstChild: boolean }]; -const userEventInstanceNames = new Set(); - export default createTestingLibraryRule({ name: RULE_NAME, meta: { @@ -52,6 +50,8 @@ export default createTestingLibraryRule({ ], create(context, [{ allowContainerFirstChild = false }], helpers) { + const userEventInstanceNames = new Set(); + function showErrorForNodeAccess(node: TSESTree.MemberExpression) { // This rule is so aggressive that can cause tons of false positives outside test files when Aggressive Reporting // is enabled. Because of that, this rule will skip this mechanism and report only if some Testing Library package @@ -144,6 +144,26 @@ export default createTestingLibraryRule({ userEventInstanceNames.add(id.name); } }, + AssignmentExpression(node: TSESTree.AssignmentExpression) { + if ( + ASTUtils.isIdentifier(node.left) && + isCallExpression(node.right) && + isMemberExpression(node.right.callee) && + ASTUtils.isIdentifier(node.right.callee.object) + ) { + const testingLibraryFn = resolveToTestingLibraryFn( + node.right, + context + ); + if ( + node.right.callee.object.name === testingLibraryFn?.local && + ASTUtils.isIdentifier(node.right.callee.property) && + node.right.callee.property.name === 'setup' + ) { + userEventInstanceNames.add(node.left.name); + } + } + }, 'ExpressionStatement MemberExpression': showErrorForNodeAccess, 'VariableDeclarator MemberExpression': showErrorForNodeAccess, }; From 9146a8d3f4cd4833571060ed04f17ba31ee07840 Mon Sep 17 00:00:00 2001 From: Hasegawa-Yukihiro Date: Sun, 3 Aug 2025 00:19:44 +0900 Subject: [PATCH 2/2] test: add tests --- tests/lib/rules/no-node-access.test.ts | 37 ++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/lib/rules/no-node-access.test.ts b/tests/lib/rules/no-node-access.test.ts index 05d5754b..6c594c43 100644 --- a/tests/lib/rules/no-node-access.test.ts +++ b/tests/lib/rules/no-node-access.test.ts @@ -209,6 +209,43 @@ ruleTester.run(RULE_NAME, rule, { const buttonText = screen.getByText('submit'); userEvt.click(buttonText); + `, + }, + { + code: ` + import { screen } from '${testingFramework}'; + import userEvent from '@testing-library/user-event'; + + describe('Testing', () => { + let user; + + beforeEach(() => { + user = userEvent.setup(); + }); + + it('test 1', async () => { + await user.click(screen.getByRole('button')); + }); + }); + `, + }, + { + settings: { 'testing-library/utils-module': 'test-utils' }, + code: ` + // case: custom module set but not imported using ${testingFramework} (aggressive reporting limited) + import { screen, userEvent } from 'test-utils'; + + describe('Testing', () => { + let user; + + beforeEach(() => { + user = userEvent.setup(); + }); + + it('test 1', async () => { + await user.click(screen.getByRole('button')); + }); + }); `, }, {