Skip to content

Commit 2617373

Browse files
committed
refactor: split checks for import matching node name in different methods
1 parent 97e8146 commit 2617373

File tree

4 files changed

+76
-20
lines changed

4 files changed

+76
-20
lines changed

lib/detect-testing-library-utils.ts

+22-20
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
getImportModuleName,
99
getPropertyIdentifierNode,
1010
getReferenceNode,
11+
hasImportMatch,
1112
ImportModuleNode,
1213
isImportDeclaration,
1314
isImportNamespaceSpecifier,
@@ -127,6 +128,12 @@ export function detectTestingLibraryUtils<
127128
/**
128129
* Small method to extract common checks to determine whether a node is
129130
* related to Testing Library or not.
131+
*
132+
* To determine whether a node is a valid Testing Library util, there are
133+
* two conditions to match:
134+
* - it's named in a particular way (decided by given callback)
135+
* - it's imported from valid Testing Library module (depends on aggressive
136+
* reporting)
130137
*/
131138
function isTestingLibraryUtil(
132139
node: TSESTree.Identifier,
@@ -136,28 +143,14 @@ export function detectTestingLibraryUtils<
136143
return false;
137144
}
138145

139-
const referenceNode = getReferenceNode(node);
140-
const referenceNodeIdentifier = getPropertyIdentifierNode(referenceNode);
141-
142146
if (isAggressiveModuleReportingEnabled()) {
143147
return true;
144148
}
145149

146-
// TODO: extract this into function, combined with logic from isFireEventMethod
147-
// TODO: include some tests create-testing-library-rule
148-
const importNode = findImportedUtilSpecifier(
149-
referenceNodeIdentifier.name
150-
);
151-
152-
if (!importNode) {
153-
return false;
154-
}
155-
156-
if (ASTUtils.isIdentifier(importNode)) {
157-
return importNode.name === referenceNodeIdentifier.name;
158-
}
150+
const referenceNode = getReferenceNode(node);
151+
const referenceNodeIdentifier = getPropertyIdentifierNode(referenceNode);
159152

160-
return importNode.local.name === referenceNodeIdentifier.name;
153+
return isNodeComingFromTestingLibrary(referenceNodeIdentifier);
161154
}
162155

163156
/**
@@ -454,17 +447,26 @@ export function detectTestingLibraryUtils<
454447
const canReportErrors: CanReportErrorsFn = () => {
455448
return isTestingLibraryImported() && isValidFilename();
456449
};
450+
457451
/**
458-
* Takes a MemberExpression or an Identifier and verifies if its name comes from the import in TL
459-
* @param node a MemberExpression (in "foo.property" it would be property) or an Identifier
452+
* Determines whether a node is imported from a valid Testing Library module
453+
*
454+
* This method will try to find any import matching the given node name,
455+
* and also make sure the name is a valid match in case it's been renamed.
460456
*/
461457
const isNodeComingFromTestingLibrary: IsNodeComingFromTestingLibraryFn = (
462458
node
463459
) => {
464460
const identifierName: string | undefined = getPropertyIdentifierNode(node)
465461
.name;
466462

467-
return !!findImportedUtilSpecifier(identifierName);
463+
const importNode = findImportedUtilSpecifier(identifierName);
464+
465+
if (!importNode) {
466+
return false;
467+
}
468+
469+
return hasImportMatch(importNode, identifierName);
468470
};
469471

470472
const helpers: DetectionHelpers = {

lib/node-utils.ts

+11
Original file line numberDiff line numberDiff line change
@@ -620,3 +620,14 @@ export function getInnermostReturningFunction(
620620

621621
return functionScope.block;
622622
}
623+
624+
export function hasImportMatch(
625+
importNode: TSESTree.ImportClause | TSESTree.Identifier,
626+
identifierName: string
627+
): boolean {
628+
if (ASTUtils.isIdentifier(importNode)) {
629+
return importNode.name === identifierName;
630+
}
631+
632+
return importNode.local.name === identifierName;
633+
}

tests/create-testing-library-rule.test.ts

+28
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,19 @@ ruleTester.run(RULE_NAME, rule, {
126126
const utils = render()
127127
`,
128128
},
129+
{
130+
settings: {
131+
'testing-library/utils-module': 'test-utils',
132+
},
133+
code: `
134+
// case (render util): aggressive reporting disabled - method with same name
135+
// as TL method but not coming from TL module is valid
136+
import { render as testingLibraryRender } from 'test-utils'
137+
import { render } from 'somewhere-else'
138+
139+
const utils = render()
140+
`,
141+
},
129142

130143
// Test Cases for presence/absence assertions
131144
// cases: asserts not related to presence/absence
@@ -287,6 +300,21 @@ ruleTester.run(RULE_NAME, rule, {
287300
waitFor()
288301
`,
289302
},
303+
{
304+
settings: {
305+
'testing-library/utils-module': 'test-utils',
306+
},
307+
code: `
308+
// case (async util): aggressive reporting disabled - method with same name
309+
// as TL method but not coming from TL module is valid
310+
import { waitFor as testingLibraryWaitFor } from 'test-utils'
311+
import { waitFor } from 'somewhere-else'
312+
313+
test('this should not be reported', () => {
314+
waitFor()
315+
});
316+
`,
317+
},
290318

291319
// Test Cases for all settings mixed
292320
{

tests/lib/rules/prefer-wait-for.test.ts

+15
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,21 @@ ruleTester.run(RULE_NAME, rule, {
218218
cy.wait();
219219
`,
220220
},
221+
{
222+
settings: {
223+
'testing-library/utils-module': 'test-utils',
224+
},
225+
code: `
226+
// case: aggressive reporting disabled - method named same as invalid method
227+
// but not coming from Testing Library is valid
228+
import { wait as testingLibraryWait } from 'test-utils'
229+
import { wait } from 'somewhere-else'
230+
231+
async () => {
232+
await wait();
233+
}
234+
`,
235+
},
221236
{
222237
// https://github.com/testing-library/eslint-plugin-testing-library/issues/145
223238
code: `import * as foo from 'imNoTestingLibrary';

0 commit comments

Comments
 (0)