Skip to content

Commit 25809e3

Browse files
committed
refactor: extract function for finding import specifier
1 parent f698500 commit 25809e3

File tree

2 files changed

+68
-52
lines changed

2 files changed

+68
-52
lines changed

lib/create-testing-library-rule/detect-testing-library-utils.ts

Lines changed: 13 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66

77
import {
88
findClosestVariableDeclaratorNode,
9+
findImportSpecifier,
910
getAssertNodeInfo,
1011
getDeepestIdentifierNode,
1112
getImportModuleName,
@@ -196,7 +197,7 @@ export function detectTestingLibraryUtils<
196197
return false;
197198
}
198199

199-
const importedUtilSpecifier = getImportedUtilSpecifier(
200+
const importedUtilSpecifier = getTestingLibraryImportedUtilSpecifier(
200201
referenceNodeIdentifier
201202
);
202203

@@ -470,7 +471,9 @@ export function detectTestingLibraryUtils<
470471
* Determines whether a given node is fireEvent method or not
471472
*/
472473
const isFireEventMethod: IsFireEventMethodFn = (node) => {
473-
const fireEventUtil = findImportedUtilSpecifier(FIRE_EVENT_NAME);
474+
const fireEventUtil = findImportedTestingLibraryUtilSpecifier(
475+
FIRE_EVENT_NAME
476+
);
474477
let fireEventUtilName: string | undefined;
475478

476479
if (fireEventUtil) {
@@ -687,60 +690,18 @@ export function detectTestingLibraryUtils<
687690
};
688691

689692
/**
690-
* Gets a string and verifies if it was imported/required by Testing Library
691-
* related module.
693+
* Finds the import util specifier related to Testing Library for a given name.
692694
*/
693-
const findImportedUtilSpecifier: FindImportedUtilSpecifierFn = (
695+
const findImportedTestingLibraryUtilSpecifier: FindImportedUtilSpecifierFn = (
694696
specifierName
695-
) => {
697+
): TSESTree.ImportClause | TSESTree.Identifier | undefined => {
696698
const node = getCustomModuleImportNode() ?? getTestingLibraryImportNode();
697699

698700
if (!node) {
699701
return undefined;
700702
}
701703

702-
if (isImportDeclaration(node)) {
703-
const namedExport = node.specifiers.find((n) => {
704-
return (
705-
isImportSpecifier(n) &&
706-
[n.imported.name, n.local.name].includes(specifierName)
707-
);
708-
});
709-
710-
// it is "import { foo [as alias] } from 'baz'""
711-
if (namedExport) {
712-
return namedExport;
713-
}
714-
715-
// it could be "import * as rtl from 'baz'"
716-
return node.specifiers.find((n) => isImportNamespaceSpecifier(n));
717-
} else {
718-
if (!ASTUtils.isVariableDeclarator(node.parent)) {
719-
return undefined;
720-
}
721-
const requireNode = node.parent;
722-
723-
if (ASTUtils.isIdentifier(requireNode.id)) {
724-
// this is const rtl = require('foo')
725-
return requireNode.id;
726-
}
727-
728-
// this should be const { something } = require('foo')
729-
if (!isObjectPattern(requireNode.id)) {
730-
return undefined;
731-
}
732-
733-
const property = requireNode.id.properties.find(
734-
(n) =>
735-
isProperty(n) &&
736-
ASTUtils.isIdentifier(n.key) &&
737-
n.key.name === specifierName
738-
);
739-
if (!property) {
740-
return undefined;
741-
}
742-
return (property as TSESTree.Property).key as TSESTree.Identifier;
743-
}
704+
return findImportSpecifier(specifierName, node);
744705
};
745706

746707
const findImportedUserEventSpecifier: () => TSESTree.Identifier | null = () => {
@@ -774,7 +735,7 @@ export function detectTestingLibraryUtils<
774735
return null;
775736
};
776737

777-
const getImportedUtilSpecifier = (
738+
const getTestingLibraryImportedUtilSpecifier = (
778739
node: TSESTree.MemberExpression | TSESTree.Identifier
779740
): TSESTree.ImportClause | TSESTree.Identifier | undefined => {
780741
const identifierName: string | undefined = getPropertyIdentifierNode(node)
@@ -784,7 +745,7 @@ export function detectTestingLibraryUtils<
784745
return undefined;
785746
}
786747

787-
return findImportedUtilSpecifier(identifierName);
748+
return findImportedTestingLibraryUtilSpecifier(identifierName);
788749
};
789750

790751
/**
@@ -803,7 +764,7 @@ export function detectTestingLibraryUtils<
803764
const isNodeComingFromTestingLibrary: IsNodeComingFromTestingLibraryFn = (
804765
node
805766
) => {
806-
const importNode = getImportedUtilSpecifier(node);
767+
const importNode = getTestingLibraryImportedUtilSpecifier(node);
807768

808769
if (!importNode) {
809770
return false;
@@ -877,7 +838,7 @@ export function detectTestingLibraryUtils<
877838
isPresenceAssert,
878839
isAbsenceAssert,
879840
canReportErrors,
880-
findImportedUtilSpecifier,
841+
findImportedUtilSpecifier: findImportedTestingLibraryUtilSpecifier,
881842
isNodeComingFromTestingLibrary,
882843
};
883844

lib/node-utils/index.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ import {
1414
isCallExpression,
1515
isExpressionStatement,
1616
isImportDeclaration,
17+
isImportNamespaceSpecifier,
18+
isImportSpecifier,
1719
isLiteral,
1820
isMemberExpression,
21+
isObjectPattern,
22+
isProperty,
1923
isReturnStatement,
2024
isVariableDeclaration,
2125
} from './is-node-of-type';
@@ -569,3 +573,54 @@ export function isEmptyFunction(node: TSESTree.Node): boolean | undefined {
569573

570574
return false;
571575
}
576+
577+
/**
578+
* Finds the import specifier matching a given name for a given import module node.
579+
*/
580+
export function findImportSpecifier(
581+
specifierName: string,
582+
node: ImportModuleNode
583+
): TSESTree.ImportClause | TSESTree.Identifier | undefined {
584+
if (isImportDeclaration(node)) {
585+
const namedExport = node.specifiers.find((n) => {
586+
return (
587+
isImportSpecifier(n) &&
588+
[n.imported.name, n.local.name].includes(specifierName)
589+
);
590+
});
591+
592+
// it is "import { foo [as alias] } from 'baz'""
593+
if (namedExport) {
594+
return namedExport;
595+
}
596+
597+
// it could be "import * as rtl from 'baz'"
598+
return node.specifiers.find((n) => isImportNamespaceSpecifier(n));
599+
} else {
600+
if (!ASTUtils.isVariableDeclarator(node.parent)) {
601+
return undefined;
602+
}
603+
const requireNode = node.parent;
604+
605+
if (ASTUtils.isIdentifier(requireNode.id)) {
606+
// this is const rtl = require('foo')
607+
return requireNode.id;
608+
}
609+
610+
// this should be const { something } = require('foo')
611+
if (!isObjectPattern(requireNode.id)) {
612+
return undefined;
613+
}
614+
615+
const property = requireNode.id.properties.find(
616+
(n) =>
617+
isProperty(n) &&
618+
ASTUtils.isIdentifier(n.key) &&
619+
n.key.name === specifierName
620+
);
621+
if (!property) {
622+
return undefined;
623+
}
624+
return (property as TSESTree.Property).key as TSESTree.Identifier;
625+
}
626+
}

0 commit comments

Comments
 (0)