Skip to content

Unable to find an accessible element with the role "form" #474

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ruscal opened this issue Mar 11, 2020 · 13 comments
Closed

Unable to find an accessible element with the role "form" #474

ruscal opened this issue Mar 11, 2020 · 13 comments

Comments

@ruscal
Copy link

ruscal commented Mar 11, 2020

  • DOM Testing Library version: 9.5.0 (react library)
  • node version: Whatever CodeSandbox runs on for React sandboxes
  • npm (or yarn) version: Whatever CodeSandbox runs on for React sandboxes

Relevant code or config:

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

const Form = () => (
  <div>
    <form id='form1' title='form title'>
      <p>Hi</p>
    </form>
  </div>
)

const wrapper = render(<Form />);

wrapper.getByRole('form');

What you did:

Trying to select the form element by role. This also fails with findByRole.

What happened:

Error
Unable to find an accessible element with the role "form"

Here are the accessible roles:

  document:

  Name "":
  <body />

Adding role='form' to form element does find the form element but should not be required.

Reproduction:

https://codesandbox.io/s/falling-surf-0br51

Looks like bug was introduced in 16.4.1 as 16.4.0 works fine (with 9.4.1 version of @testing-library/react):
https://codesandbox.io/s/dom-testing-library-template-kzorw

Problem description:

Fails tests that are asserting that an accessible form is in the DOM.

Suggested solution:

aria-query looks to still be exporting form in the roles map so that's probably not the issue. Other than that not had enough time to dig further.

@eps1lon
Copy link
Member

eps1lon commented Mar 11, 2020

This is actually intended by spec. A <form> element needs an accessible name to have the form role. So you need <form aria-label="form" /> or <form aria-labelledby="form-label-element-id" />.

Though we could extend the error message to add a hint if a role is queried where an element needs an accessible name to have that role.

@ruscal
Copy link
Author

ruscal commented Mar 11, 2020

So it's changed from title being the semantic equivalent to name then. I've verified that changing to using name works fine.

Thanks for your help!

@sunpietro
Copy link

In my case, neither name nor aria-label work when running screen.getByRole('form').

php-coder added a commit to php-coder/mystamps that referenced this issue Jan 11, 2021
…omponent

This change is also needed by #1484:
- the "role" attribute makes the alert "searchable" by screen.getByRole()
- the "aria-label" attribute makes the form "searchable" by screen.getByRole()
  (testing-library/dom-testing-library#474 (comment))

Part of #1493
@Nargonath
Copy link

If I have:

<form name="profile" action="#" >
</form>

It works when querying with screen.getByRole("form") however it doesn't work when doing screen.getByRole("form", { name: "profile" });. I have to add an aria-label="profile" to the form for the name option to work. Is this normal? I thought the name property was enough to consider the form accessible.

@alexkrolick
Copy link
Collaborator

name is used for form submission to identify the field names. It's not user-accessible content like a label tag or aria-label.

@Nargonath
Copy link

@alexkrolick When you run screen.getByRole("form") on:

<form action="#"></form>

getByRole throws because the form only has role="form" when it has an accessible name. But if you add a name property to the form the same query works so I guess name works for adding an accessible name to a form.

@alexkrolick
Copy link
Collaborator

alexkrolick commented Aug 7, 2022

I see aria-query (which powers getByRole) implements that but I am not sure that is correct behavior. At least in Chrome devtools, a form with just a name attribute doesn't have an accessible name.

src/etc/roles/literal/formRole.js
Screen Shot 2022-08-06 at 11 33 36 PM

@MatanBobi
Copy link
Member

As @alexkrolick mentioned, the name property is not the accessible name for a form.
Accessible names are defined either "from author" or "from content" where "from author" stands for: aria-label, aria-labelledby and in some cases alt or title.
More on this can be found in the ARIA spec :)
https://www.w3.org/TR/wai-aria-1.2/#namecalculation

@Nargonath
Copy link

Alright, thank you @MatanBobi and @alexkrolick for your explanation. 👍

@andremarcondesteixeira
Copy link

I disagree on this. This can lead to fragile tests.
Let's say you create a button that when clicked displays a form.
The form has a cancel button inside, and you put a aria-label in the form so that dom-testing-library detects it by role.
You write a test that asserts that the form is hidden when the cancel button is clicked.
The test uses expect(screen.queryByRole('form')).not.toBeInTheDocument() to make the assertion.
Now imagine that in the future, someone breaks the cancel button and now the form keeps being displayed, and also this person removed the aria-label attribute.
In this scenario, the previous tests you wrote will keep passing, because even though the form is still visible, dom-testing-library does not see any element with the form role anymore.

@Nargonath
Copy link

While I agree with you @andremarcondesteixeira, if this is per the spec I'm not sure it's good diverting from it.

@MatanBobi
Copy link
Member

I disagree on this. This can lead to fragile tests. Let's say you create a button that when clicked displays a form. The form has a cancel button inside, and you put a aria-label in the form so that dom-testing-library detects it by role. You write a test that asserts that the form is hidden when the cancel button is clicked. The test uses expect(screen.queryByRole('form')).not.toBeInTheDocument() to make the assertion. Now imagine that in the future, someone breaks the cancel button and now the form keeps being displayed, and also this person removed the aria-label attribute. In this scenario, the previous tests you wrote will keep passing, because even though the form is still visible, dom-testing-library does not see any element with the form role anymore.

I get what you're saying but the same can happen if the engineer removes the name property, keep in mind that if you don't have the aria-label/aria-labelledyby, you're form isn't accessible so you have an accessibility issue.
Eventually, @Nargonath is right, the spec states that and we work according to the spec :)

QuailtyDev added a commit to QuailtyDev/mui-next that referenced this issue Oct 22, 2022
@lacrossehub
Copy link

Solved for me by enabling the hidden option in getByRole

screen.getByRole('form', { hidden: true }),

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants