-
Notifications
You must be signed in to change notification settings - Fork 132
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add no-node-access rule (#190)
* refactor(utils): add properties and methods that returns another Node * test(no-node-access): add first scenarios * feat(no-node-access): add rule with few test cases * test(no-node-access): add scenarios * refactor(no-node-access): simplify conditions * refactor(no-node-access): add scenario when no variable is declared * refactor(no-node-access): remove conditional * refactor(utils): add DOM properties * refactor(no-node-access): add scenario for accessing document directly * docs(no-node-access): add readme * refactor(utils): export const containing all properties and methods that return a Node * docs(no-node-access): fix file location * docs(readme): add no-node-access * refactor(no-node-access): change highlight location * docs(no-node-access): fix typo * refactor(utils): add missing property that returns a Node * refactor(no-node-access): simplify checks triggering error for all methods with names matching the forbidden ones * test(no-node-access): add more scenarios with destructuring * docs(no-node-access): update examples * refactor(no-node-access): narrow error cases * refactor(no-node-access): check imports to validate whether is importing a testing-library package | update examples and testing scenarios * refactor(no-node-access): rename variable
- Loading branch information
1 parent
b2ef721
commit 9d4c1e4
Showing
8 changed files
with
423 additions
and
5 deletions.
There are no files selected for viewing
This file contains 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 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 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,60 @@ | ||
# Disallow direct Node access (no-node-access) | ||
|
||
The Testing Library already provides methods for querying DOM elements. | ||
|
||
## Rule Details | ||
|
||
This rule aims to disallow DOM traversal using native HTML methods and properties, such as `closest`, `lastChild` and all that returns another Node element from an HTML tree. | ||
|
||
Examples of **incorrect** code for this rule: | ||
|
||
```js | ||
import { screen } from '@testing-library/react'; | ||
|
||
screen.getByText('Submit').closest('button'); // chaining with Testing Library methods | ||
``` | ||
|
||
```js | ||
import { screen } from '@testing-library/react'; | ||
|
||
const buttons = screen.getAllByRole('button'); | ||
expect(buttons[1].lastChild).toBeInTheDocument(); | ||
``` | ||
|
||
```js | ||
import { screen } from '@testing-library/react'; | ||
|
||
const buttonText = screen.getByText('Submit'); | ||
const button = buttonText.closest('button'); | ||
``` | ||
|
||
Examples of **correct** code for this rule: | ||
|
||
```js | ||
import { screen } from '@testing-library/react'; | ||
|
||
const button = screen.getByRole('button'); | ||
expect(button).toHaveTextContent('submit'); | ||
``` | ||
|
||
```js | ||
import { render, within } from '@testing-library/react'; | ||
|
||
const { getByLabelText } = render(<MyComponent />); | ||
const signinModal = getByLabelText('Sign In'); | ||
within(signinModal).getByPlaceholderText('Username'); | ||
``` | ||
|
||
```js | ||
// If is not importing a testing-library package | ||
|
||
document.getElementById('submit-btn').closest('button'); | ||
``` | ||
|
||
## Further Reading | ||
|
||
### Properties / methods that return another Node | ||
|
||
- [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) | ||
- [`Element`](https://developer.mozilla.org/en-US/docs/Web/API/Element) | ||
- [`Node`](https://developer.mozilla.org/en-US/docs/Web/API/Node) |
This file contains 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 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,49 @@ | ||
import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'; | ||
import { getDocsUrl, ALL_RETURNING_NODES } from '../utils'; | ||
import { isIdentifier } from '../node-utils'; | ||
|
||
export const RULE_NAME = 'no-node-access'; | ||
|
||
export default ESLintUtils.RuleCreator(getDocsUrl)({ | ||
name: RULE_NAME, | ||
meta: { | ||
type: 'problem', | ||
docs: { | ||
description: 'Disallow direct Node access', | ||
category: 'Best Practices', | ||
recommended: 'error', | ||
}, | ||
messages: { | ||
noNodeAccess: | ||
'Avoid direct Node access. Prefer using the methods from Testing Library.', | ||
}, | ||
fixable: null, | ||
schema: [], | ||
}, | ||
defaultOptions: [], | ||
|
||
create(context) { | ||
let isImportingTestingLibrary = false; | ||
|
||
function checkTestingEnvironment(node: TSESTree.ImportDeclaration) { | ||
isImportingTestingLibrary = /testing-library/g.test(node.source.value as string); | ||
} | ||
|
||
function showErrorForNodeAccess(node: TSESTree.MemberExpression) { | ||
isIdentifier(node.property) && | ||
ALL_RETURNING_NODES.includes(node.property.name) && | ||
isImportingTestingLibrary && | ||
context.report({ | ||
node: node, | ||
loc: node.property.loc.start, | ||
messageId: 'noNodeAccess', | ||
}); | ||
} | ||
|
||
return { | ||
['ImportDeclaration']: checkTestingEnvironment, | ||
['ExpressionStatement MemberExpression']: showErrorForNodeAccess, | ||
['VariableDeclarator MemberExpression']: showErrorForNodeAccess, | ||
}; | ||
}, | ||
}); |
This file contains 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 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.