Cant find button using Test Library (React)
Asked Answered
L

4

20

I'm must be missing something quite obvious, I have a react app that has a left div with multiple buttons, each one of them with different texts. I want to check if every one of those buttons was rendered.So for instance to find one of the buttons (using the Testing Library) I'm doing the following:

screen.getByText("/channels/i", { selector: "button" })

I Also tried

screen.getByRole("button", { name: /channels/i })

But I always get the result

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

    There are no accessible roles. But there might be some inaccessible roles. If you wish to access them, then set the `hidden` option to `true`. Learn more about this here: https://testing-library.com/docs/dom-testing-library/api-queries#byrole

But as you can see it does exist

enter image description here

Like that I have probably another 10 buttons, so I don't get why it says that there are no accessible roles.

What I'm doing wrong?

Legitimist answered 15/11, 2020 at 13:11 Comment(1)
if my answer doesn't solve your issue, I probably need to see more code on the Button component. Could you create a sandbox?Thorazine
L
6

In this particular case, it actually was a stupid mistake, I had my render() placed somewhat like this:

render(<App />)
describe("Navigation", () => {
        it("Navigation Test 1", () => {...

So basically because I'm using Testing Library before each iteration "it" would clean my App component making getByRole not able to find the nodes.

The moment I placed render() inside "it", all started working... Stupid mistake and with the code I provided it would be really hard to guess. Thanks anyway Doug.

Legitimist answered 16/11, 2020 at 1:57 Comment(2)
I am curious about how the component could be rendered for all tests within a file without it cleaning it up. It would be nice to make the render call once and run tests for all the cases in an organized way.Mesoglea
Simply render the component in each test case. Do not try to create some kind of abstraction/helper function to render a component just to avoid the "duplication".Cowans
T
32

There are mainly 2 possibilities I see.

  1. Not waiting for the button to appear. If your button is rendered after a certain thing has finished loading, you need to wait for it to appear on the screen. You can do that with a findBy query.
await screen.findByRole('button', { name: 'Channels' });
  1. If your button is somehow not accessible, hidden by CSS or by aria-hidden="true", it won't be found by the getByRole query. You can verify this by passing the hidden prop. Note you should probably not be using hidden in most cases.
screen.getByRole('button', { name: 'Channels', hidden: true });

Useful links

Thorazine answered 16/11, 2020 at 1:23 Comment(1)
very useful. It helped me solving the issue I hadPurpure
L
6

In this particular case, it actually was a stupid mistake, I had my render() placed somewhat like this:

render(<App />)
describe("Navigation", () => {
        it("Navigation Test 1", () => {...

So basically because I'm using Testing Library before each iteration "it" would clean my App component making getByRole not able to find the nodes.

The moment I placed render() inside "it", all started working... Stupid mistake and with the code I provided it would be really hard to guess. Thanks anyway Doug.

Legitimist answered 16/11, 2020 at 1:57 Comment(2)
I am curious about how the component could be rendered for all tests within a file without it cleaning it up. It would be nice to make the render call once and run tests for all the cases in an organized way.Mesoglea
Simply render the component in each test case. Do not try to create some kind of abstraction/helper function to render a component just to avoid the "duplication".Cowans
B
2

This can also be caused by the name of the button being wrong. E.g.

screen.getByRole('button', { name: 'Sumbit' })

Note the typo: 'Sumbit' instead of 'Submit'. In this case, you get this very misleading error message:

Unable to find role="button"

I just lost half an hour on a simple typo and a bad error message. 🥲

Borchardt answered 16/12, 2021 at 10:39 Comment(1)
This also just happened to me. I meant to pass the name as a regex since I presume this looks for an exact match. (i.e. {name: 'Submit'} doesn't match a button called Submit… but {name: /Submit/} gives a better error with other roles RTL tried.)Toplevel
M
0

I got a similar error when running screen.getByRole("button", { name: "clear" });

Unable to find an accessible element with the role "button" and name "clear"

My problem was that I was defining the element incorrectly, this is the way to fix

<button
 aria-label="clear" // instead of name="clear"
...
Mesoglea answered 4/4, 2024 at 14:42 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.