# testing-library/no-node-access 📝 Disallow direct Node access. 💼 This rule is enabled in the following configs: ![badge-angular](https://img.shields.io/badge/-Angular-black?style=flat-square&logo=angular&logoColor=white&labelColor=DD0031&color=black) `angular`, ![badge-dom](https://img.shields.io/badge/%F0%9F%90%99-DOM-black?style=flat-square) `dom`, ![badge-marko](https://img.shields.io/badge/-Marko-black?style=flat-square&logo=marko&logoColor=white&labelColor=2596BE&color=black) `marko`, ![badge-react](https://img.shields.io/badge/-React-black?style=flat-square&logo=react&logoColor=white&labelColor=61DAFB&color=black) `react`, ![badge-svelte](https://img.shields.io/badge/-Svelte-black?style=flat-square&logo=svelte&logoColor=white&labelColor=FF3E00&color=black) `svelte`, ![badge-vue](https://img.shields.io/badge/-Vue-black?style=flat-square&logo=vue.js&logoColor=white&labelColor=4FC08D&color=black) `vue`. Disallow direct access or manipulation of DOM nodes in favor of Testing Library's user-centric APIs. ## Rule Details This rule aims to disallow direct access and manipulation of DOM nodes using native HTML properties and methods — including traversal (e.g. `closest`, `lastChild`) as well as direct actions (e.g. `click()`, `select()`). Use Testing Library’s queries and userEvent APIs instead. > [!NOTE] > This rule does not report usage of `focus()` or `blur()`, because imperative usage (e.g. `getByText('focus me').focus()` or .`blur()`) is recommended over `fireEvent.focus()` or `fireEvent.blur()`. > If an element is not focusable, related assertions will fail, leading to more robust tests. See [Testing Library Events Guide](https://testing-library.com/docs/guide-events/) for more details. 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'; screen.getByText('Submit').click(); ``` ```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 { screen } from '@testing-library/react'; userEvent.click(screen.getByText('Submit')); ``` ```js import { render, within } from '@testing-library/react'; const { getByLabelText } = render(); const signinModal = getByLabelText('Sign In'); within(signinModal).getByPlaceholderText('Username'); ``` ```js import { screen } from '@testing-library/react'; function ComponentA(props) { // props.children is not reported return
{props.children}
; } render(); ``` ```js // If is not importing a testing-library package document.getElementById('submit-btn').closest('button'); ``` ## Options This rule has one option: - `allowContainerFirstChild`: **disabled by default**. When we have container with rendered content then the easiest way to access content itself is [by using `firstChild` property](https://testing-library.com/docs/react-testing-library/api/#container-1). Use this option in cases when this is hardly avoidable. ```js "testing-library/no-node-access": ["error", {"allowContainerFirstChild": true}] ``` Correct: ```jsx const { container } = render(); expect(container.firstChild).toMatchSnapshot(); ``` ## 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) ### Testing Library Guides - [Testing Library Events Guide](https://testing-library.com/docs/guide-events/)