-
Notifications
You must be signed in to change notification settings - Fork 150
fix(no-node-access): improve detection for Testing Library calls #1033
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 9 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
6260880
feat: add StringLiteral and TemplateLiteral type checks
y-hsgw 05b2934
feat: add type checks for TSImportEqualsDeclaration and ImportExpression
y-hsgw 7b4e38c
feat: implement resolveToTestingLibraryFn utility for handling user e…
y-hsgw d445ec2
feat: enhance rule to handle user event instances and improve reporting
y-hsgw bdc3506
test: update no-node-access tests to include userEvent setup scenarios
y-hsgw 7510adf
feat: enhance no-node-access rule to support userEvent setup function…
y-hsgw bb7df93
refactor: remove unnecessary case for TaggedTemplateExpression in get…
y-hsgw bf45566
test: add tests for resolveToTestingLibraryFn
y-hsgw 9e49403
test: update userEvent import syntax in resolveToTestingLibraryFn tests
y-hsgw 6781117
feat: add support for settings['testing-library/utils-module']
y-hsgw f7ce66f
test: add test case with settings['testing-library/utils-module'] con…
y-hsgw ad7daab
test: add additional test cases for userEvent import variations
y-hsgw 0663480
test: update userEvent import cases and enhance error reporting in tests
y-hsgw 42278fe
refactor: remove redundant JSDoc comments from string and identifier …
y-hsgw e91aa36
refactor: replace direct type check with isLiteral utility in isStrin…
y-hsgw d426a29
refactor: rename isTemplateLiteral to isSimpleTemplateLiteral for cla…
y-hsgw df09b1a
refactor: add isTemplateLiteral utility function and update isSimpleT…
y-hsgw f51421f
refactor: import USER_EVENT_MODULE in resolve-to-testing-library-fn a…
y-hsgw cc0ab47
test: add test
y-hsgw c4a884b
Revert "test: add test"
y-hsgw db38d9f
test: add test
y-hsgw 8062770
test: clarify test-utils vs ./test-utils distinction in test comment
y-hsgw File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
import { | ||
AST_NODE_TYPES, | ||
ASTUtils, | ||
type TSESTree, | ||
} from '@typescript-eslint/utils'; | ||
|
||
/** | ||
* A `Literal` with a `value` of type `string`. | ||
*/ | ||
interface StringLiteral<Value extends string = string> | ||
extends TSESTree.StringLiteral { | ||
value: Value; | ||
} | ||
|
||
/** | ||
* Checks if the given `node` is a `StringLiteral`. | ||
* | ||
* If a `value` is provided & the `node` is a `StringLiteral`, | ||
* the `value` will be compared to that of the `StringLiteral`. | ||
* | ||
* @param {Node} node | ||
* @param {V} [value] | ||
* | ||
* @return {node is StringLiteral<V>} | ||
* | ||
* @template V | ||
*/ | ||
const isStringLiteral = <V extends string>( | ||
node: TSESTree.Node, | ||
value?: V | ||
): node is StringLiteral<V> => | ||
node.type === AST_NODE_TYPES.Literal && | ||
Belco90 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
typeof node.value === 'string' && | ||
(value === undefined || node.value === value); | ||
|
||
interface TemplateLiteral<Value extends string = string> | ||
extends TSESTree.TemplateLiteral { | ||
quasis: [TSESTree.TemplateElement & { value: { raw: Value; cooked: Value } }]; | ||
} | ||
|
||
/** | ||
* Checks if the given `node` is a `TemplateLiteral`. | ||
* | ||
* Complex `TemplateLiteral`s are not considered specific, and so will return `false`. | ||
* | ||
* If a `value` is provided & the `node` is a `TemplateLiteral`, | ||
* the `value` will be compared to that of the `TemplateLiteral`. | ||
* | ||
* @param {Node} node | ||
* @param {V} [value] | ||
* | ||
* @return {node is TemplateLiteral<V>} | ||
* | ||
* @template V | ||
*/ | ||
const isTemplateLiteral = <V extends string>( | ||
Belco90 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
node: TSESTree.Node, | ||
value?: V | ||
): node is TemplateLiteral<V> => | ||
node.type === AST_NODE_TYPES.TemplateLiteral && | ||
Belco90 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
node.quasis.length === 1 && // bail out if not simple | ||
(value === undefined || node.quasis[0].value.raw === value); | ||
|
||
export type StringNode<S extends string = string> = | ||
| StringLiteral<S> | ||
| TemplateLiteral<S>; | ||
|
||
/** | ||
* Checks if the given `node` is a {@link StringNode}. | ||
* | ||
* @param {Node} node | ||
* @param {V} [specifics] | ||
* | ||
* @return {node is StringNode} | ||
* | ||
* @template V | ||
*/ | ||
export const isStringNode = <V extends string>( | ||
node: TSESTree.Node, | ||
specifics?: V | ||
): node is StringNode<V> => | ||
isStringLiteral(node, specifics) || isTemplateLiteral(node, specifics); | ||
|
||
/** | ||
* Gets the value of the given `StringNode`. | ||
* | ||
* If the `node` is a `TemplateLiteral`, the `raw` value is used; | ||
* otherwise, `value` is returned instead. | ||
* | ||
* @param {StringNode<S>} node | ||
* | ||
* @return {S} | ||
* | ||
* @template S | ||
*/ | ||
export const getStringValue = <S extends string>(node: StringNode<S>): S => | ||
isTemplateLiteral(node) ? node.quasis[0].value.raw : node.value; | ||
|
||
/** | ||
* An `Identifier` with a known `name` value | ||
*/ | ||
interface KnownIdentifier<Name extends string> extends TSESTree.Identifier { | ||
name: Name; | ||
} | ||
|
||
/** | ||
* Checks if the given `node` is an `Identifier`. | ||
* | ||
* If a `name` is provided, & the `node` is an `Identifier`, | ||
* the `name` will be compared to that of the `identifier`. | ||
* | ||
* @param {Node} node | ||
* @param {V} [name] | ||
* | ||
* @return {node is KnownIdentifier<Name>} | ||
* | ||
* @template V | ||
*/ | ||
export const isIdentifier = <V extends string>( | ||
node: TSESTree.Node, | ||
name?: V | ||
): node is KnownIdentifier<V> => | ||
ASTUtils.isIdentifier(node) && (name === undefined || node.name === name); | ||
|
||
/** | ||
* Checks if the given `node` is a "supported accessor". | ||
* | ||
* This means that it's a node can be used to access properties, | ||
* and who's "value" can be statically determined. | ||
* | ||
* `MemberExpression` nodes most commonly contain accessors, | ||
* but it's possible for other nodes to contain them. | ||
* | ||
* If a `value` is provided & the `node` is an `AccessorNode`, | ||
* the `value` will be compared to that of the `AccessorNode`. | ||
* | ||
* Note that `value` here refers to the normalised value. | ||
* The property that holds the value is not always called `name`. | ||
* | ||
* @param {Node} node | ||
* @param {V} [value] | ||
* | ||
* @return {node is AccessorNode<V>} | ||
* | ||
* @template V | ||
*/ | ||
export const isSupportedAccessor = <V extends string>( | ||
node: TSESTree.Node, | ||
value?: V | ||
): node is AccessorNode<V> => | ||
isIdentifier(node, value) || isStringNode(node, value); | ||
|
||
/** | ||
* Gets the value of the given `AccessorNode`, | ||
* account for the different node types. | ||
* | ||
* @param {AccessorNode<S>} accessor | ||
* | ||
* @return {S} | ||
* | ||
* @template S | ||
*/ | ||
export const getAccessorValue = <S extends string = string>( | ||
accessor: AccessorNode<S> | ||
): S => | ||
accessor.type === AST_NODE_TYPES.Identifier | ||
? accessor.name | ||
: getStringValue(accessor); | ||
|
||
export type AccessorNode<Specifics extends string = string> = | ||
| StringNode<Specifics> | ||
| KnownIdentifier<Specifics>; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.