133

I'm using react-testing-libarary to test my react application. For some reason, I need to be able to find the element by id and not data-testid. There is no way to achieve this in the documentation.

Is there a way to achieve this?

I have the rendered output as follows:

const dom = render(<App />);

I'm looking for something along the lines of:

const input = dom.getElementById('firstinput');
//or 
const input = dom.getById('firstinput');
1
  • 2
    This worked for me: document.getElementById('firstinput') Commented Mar 18, 2021 at 1:29

8 Answers 8

151

I feel like none of the answers really gave a complete solution, so here it is:

const result = render(<SomeComponent />);
const someElement = result.container.querySelector('#some-id');
Sign up to request clarification or add additional context in comments.

2 Comments

did not work for me. but when I logged result.debug() I can clearly see the element with that id. :(
This initially did not work for me because the id was on the react component and in the component, I ignored the id. I changed it such that the component was wrapped in a div that had the id, annd it worked!
91

I found a way to do this.

import App from './App';
import { render, queryByAttribute } from 'react-testing-library';

const getById = queryByAttribute.bind(null, 'id');

const dom = render(<App />);
const table = getById(dom.container, 'directory-table');

I hope this helps.

5 Comments

Why they don't have this by default?? I can't believe it.
It's much easier to simply use document.getElementById. But the ID of an element is an implemention detail and I recommend against using it.
@Victor Believe it. Users don't fill out elements by ID, so the test shouldn't either (at least according to react-testing-library's philosophy). They fill them out by label, so you should find your elements in the test the same way users will find them: by label or placeholder text or whatever.
@Imat - Reinstate Monica , well, I discussed some scenarios where the #id solution can be the ideal one. Everything depends on scenarios. A simple example: when using a third-party library (like Kendo), which build their elements by your provided #id, you can create tests relying on the id to access the elements. Using the #id will maintain compatibility with new versions of the third party library and it also doesn't pollute our code with data-test-id's. I explained this more in-depth right here: github.com/testing-library/react-testing-library/issues/…
Keep scrolling until @Liran H answer.
33

It looks you have DOM node itself as a container. Therefore, you should be able to call .querySelector('#firstinput') with that.

5 Comments

yes this works but the only issue here is now I'm not able to use the react-testing-library helpers on this returned node.
Nothing wrong with not using the helpers if you don't need them
"I'm not able to use the react-testing-library helpers on this returned node." This is incorrect. What helpers are you talking about? All helpers deal with regular DOM nodes, so it doesn't make a difference how you found it. But either way, finding an element by its ID is not included in the library because that's an implementation detail. Use one of the built-in queries.
Liran H's answer is better. Some people might not understand what you mean. Giving a complete example like his is better imo.
This is the fastest and easiest means of achieving this. Hugs
21

There are two ways to do so

  1. Simply use container.getElementById('id'). In the end, all the helpers are doing is making queries like this one under the hood
  2. If you want to have your custom query you can write a custom render. Check the documentation for more info https://github.com/kentcdodds/react-testing-library#getbytestidtext-textmatch-htmlelement

As a final note, if you can avoid looking for elements by id it's better.

7 Comments

I don't think you have access to getElementById on the container.
Try to log container my guess is that it's not what you're looking for
@kentcdodds I mean, would be nice if that work that way (from 1.), but all i get is TS2339: Property 'getElementById' does not exist on type 'HTMLElement'.
getElementById is not even present on RTL docs '-' For me the correct way is using the this tool: chrome.google.com/webstore/detail/testing-playground/… I never spent time adding/looking for ids again.
getElementById is not in the docs because it's not an API of RTL, it's a DOM API, supported by all browsers. The error @pbialy and @mihai-zamfir are experiencing is a TypeScript error and has nothing to do with RTL.
|
12

You can set up with testIdAttribute in the configuration.

configure({ testIdAttribute: 'id' })

https://testing-library.com/docs/dom-testing-library/api-configuration


The setting has pros and cons. The benefit of it is that you can set an id for multiple uses. (Test id, marketing analytics, tag manager, ...etc) You don't have to add both id and test-id. It's good for the conciseness of the code.

But be careful, you might accidentally set the same id at two different components on the same page. Remember to add index or identification to a component id for list items.

4 Comments

testIdAttribute: The attribute used by getByTestId and related queries. Defaults to data-testid.
This is a bad idea because ids are meant to be unique to a single element on an entire page, whereas a test id can be used on more than one element (list items, for example).
Yeah, you're probably right. But there are some benefits for the setting if we need the ids for multiple purposes. (tag manager, for example)
To clarify, the suggestion made to use the id for multiple uses is not good yes, but using testIdAttribute is not a bad idea in itself.
2

My advice: stop adding and searching by ids, this always takes to much time and effort because you have to add the ids (sometimes test-ids) and then find out the best way to query the element. But even if you really need an id, this tool will save you a lot of time by showing the best way to query any DOM element on your screen: Testing Playground

1 Comment

Needing to assert that a dom element has a particular ID is a valid testing use case.
2

If you use TypeScript, and want to get a non-null result, here's a convenience function:

function getById<T extends Element>(container: HTMLElement, id: string): T {
  const element = container.querySelector<T>(`#${id}`);
  assert(element !== null, `Unable to find an element with ID #${id}.`)
  return element;
}

You can then use it like this:

import { render } from '@testing-library/react';

const { container } = render(<App />);
const myInputElement = getById<HTMLInputElement>(container, 'myInputElement');

Comments

0

    await waitFor(() => {
            const innerOverlay = queryByAttribute("id", baseElement, "yourId");
            expect(innerOverlay).toBeTruthy();
        });
    

I haven't find anyway to findBy and attribute, however it has queryByAttribute. So we can use it with waitFor to make it similar with findBy

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.