How to fetch element with 'name' attribute in react-testing-library
Asked Answered
T

3

35

I'm testing my react app with react testing library and jest.

And I want to know how to fetch element with 'name' attribute in react-testing-library.

For example, in the following page, is it possible to fetch this element with "userName"?

<input type="text" name="userName" />

Or should I set data-testId into the element and use getByTestId method?

return (
  <div>
    <input type="text" name="userName" />
  </div>
)
Tigress answered 1/2, 2021 at 2:33 Comment(0)
A
41

You can use the returned container. The container is a DOM node and supports the querySelector method, which accepts a CSS selector to find an element. Same approach as in this more detailed answer.

For example:

const { container } = render(<MyComponent />);
const inputEl = container.querySelector(`input[name="userName"]`);
Anticipation answered 8/11, 2021 at 16:46 Comment(0)
B
30

The general recommended way to find elements in the DOM is taking an approach that resembles the way application is used.

In this particular example name attribute will not be recognised as pointed out by @ggorlen.

As a fallback for the text input you could either rely on getByLabelText (assuming you have added a label with htmlFor), or you could add aria-label to your text input:

<input type="text" aria-label="userName" />

and then use:

screen.getByRole("textbox", {name: /userName/i});

The "problem" with data-testid is you have to add it specifically for your tests, instead of relying on more natural findByRole, findByPlaceholderText, findByLabelText.

getByTestId should be your last resort.

As a follow up I recommend using Testing Playground browser extension, which generates RTL queries for elements, in a similar fashion to find element in browser devTools.

Also, when troubled with searching by name (or other attributes), try to investigate on accessibility features of given element/component to figure precisely how to search for it.

Bifurcate answered 26/5, 2022 at 7:1 Comment(4)
There may be some confusion about name here. It's the aria accessible name, not the name="userName" attribute. See What is the name option in react-testing-library?.Canvasback
I added an answer with an example showing that this approach {name: /userName/i} doesn't work.Canvasback
Thank you for your feedback, I updated my answer, so no misinformed code snippet is here for future readers. I also tagged you, so you are credited.Bifurcate
this work for me, after adding aria-label="somekey" on in input and query using getByRole Example: getByRole("textbox", { name: /somekey/i })Mascot
C
5

Instead of resorting to the native DOM, in certain situations you can select the element by role (or, less ideally, by test id), then assert that the attribute in question exists, in lieu of an all-in-one getBy call:

expect(screen.getByRole("textbox")).toHaveAttribute("name", "userName");

Unfortunately,

screen.getByRole("textbox", {name: "userName"});

doesn't work as it seems like it should. See What is the name option in react-testing-library? for an explanation.

Proof:

import React from "react"; // 18.2.0
import {render, screen} from "@testing-library/react"; // 13.4.0
import "@testing-library/jest-dom/extend-expect"; // ^5.16.5

describe("getByRole experiments", () => {
  beforeEach(() => render(<input type="text" name="userName" />));

  it("should work with a plain getByRole", () => {
    expect(screen.getByRole("textbox"))
      .toHaveAttribute("name", "userName"); // OK
  });

  it("will fail specifying {name: /userName/i}", () => {
    screen.getByRole("textbox", {name: /userName/i}); // Fails
  });

  it('will also fail specifying {name: "userName"}', () => {
    screen.getByRole("textbox", {name: "userName"}); // Fails
  });
});

Partial output (the name: "userName" assertion failure is basically the same):

TestingLibraryElementError: Unable to find an accessible element with the role "textbox" and name `/userName/i`

Here are the accessible roles:

  textbox:

  Name "":
  <input
    name="userName"
  />

  --------------------------------------------------

Ignored nodes: comments, <script />, <style />
<body>
  <div>
    <input
      name="userName"
    />
  </div>
</body>

See also React testing library: how to getByRole on custom role.

Canvasback answered 15/12, 2022 at 20:25 Comment(2)
Would it work for password field?Lowestoft
See dom-testing-library issue #567 for selecting password fields.Canvasback

© 2022 - 2024 — McMap. All rights reserved.