Skip to content

What do we recommend people do for elements that have no implicit role (like input[type=password]) #567

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
kentcdodds opened this issue May 12, 2020 · 12 comments

Comments

@kentcdodds
Copy link
Member

Say you have a login form:

<form>
  <div>
    <label for="username-field">Username</label>
    <input id="username-field" name="username" type="text" />
  </div>
  <div>
    <label for="password-field">Password</label>
    <input id="password-field" name="password" type="password" />
  </div>
  <div>
    <button type="submit">Submit</button>
  </div>
</form>

You can retrieve the username field via: screen.getByRole('textbox', {name: /username/i}) However, the password field has no implicit role so you'd have to use getByLabelText(/password/i) for that one.

I'm guessing that we just recommend people use getByLabelText as a fallback in this case, but I'm curious what other people think about this (especially curious to hear @eps1lon's thoughts here).

@kentcdodds
Copy link
Member Author

Interesting discussion on the reason passwords don't have a role: w3c/aria#935

@eps1lon
Copy link
Member

eps1lon commented May 12, 2020

I'm guessing that we just recommend people use getByLabelText as a fallback in this case

I think this is our safest bet. I wouldn't want to diverge from the spec. Otherwise people might use <input type="text" role="password" />.

If people stumble over this often when doing getByRole('textbox', { name: 'Password' }) we could check if there are other roles with the same superclass (related to #448) and name (and add a special case for input[type="text"]).

@Tohaker
Copy link

Tohaker commented May 23, 2020

Quite conveniently (or not), I've just faced this issue and was confused as to why my password input just couldn't be found. Using getByLabelText works, but it does a look a bit strange in my test;

const usernameInput = getByRole("textbox", { name: /username/i });
const domainInput = getByRole("textbox", { name: /domain/i });
const passwordInput = getByLabelText(/password/i);

I'd appreciate eps1lon's suggestion, but if this would result in some hacky, unstable solution I'd rather stick with what I already have.

@weyert
Copy link
Contributor

weyert commented May 26, 2020

I would suggest to use getByLabelText as that would improve the accessibility of the form by the need of adding a label. If they don't want to see the label they can always hide the label element visually.

@kentcdodds
Copy link
Member Author

Thanks for the input @weyert. You actually get the exact same benefit (and more) by using getByRole with a name which is why it's recommended over getByLabel.

The issues is brought up because password fields don't have an implicit role assigned to them like regular inputs, so (as @Tohaker pointed out) it looks a little odd.

I'm pretty sure this is what we'll recommend however, so I'll go ahead and close this.

@JacobMGEvans
Copy link

I'm guessing that we just recommend people use getByLabelText as a fallback in this case

I think this is our safest bet. I wouldn't want to diverge from the spec. Otherwise people might use <input type="text" role="password" />.

If people stumble over this often when doing getByRole('textbox', { name: 'Password' }) we could check if there are other roles with the same superclass (related to #448) and name (and add a special case for input[type="text"]).

Disclaimer: Speculation & My Opinion
Wouldnt this be a security risk that would enable malicious scripts the ability to find password fields much easier. I think much like certain Checkout Cart behaviors that obfuscate what the fields are being used for, this is a similar thing. Not bulletproof security or anything but a simple layer

@nickserv
Copy link
Member

Password fields aren't encrypted, so they have pretty much no security in the client. What matters is that they have secure transport over the network (like a secure API using HTTPS).

@dguglielmi-git
Copy link

You can just add the attribute role="textbox" to your Input, and then find it by:
screen.getByRole('textbox', {name: /password/i}) (in order to find name: password I added title="password" within the Input)
It worked for me.

@kentcdodds
Copy link
Member Author

Setting roles manually is not advisable without testing how assistive technologies behave when you do. When in doubt, follow the spec.

@dguglielmi-git
Copy link

Setting roles manually is not advisable without testing how assistive technologies behave when you do. When in doubt, follow the spec.

Thanks Kent! I took into account your comment, so I modified it by adding aria-label="password" and then I could find it by getByLabel('password'). I was not using Label and Input, it was a Form.Input, do you have any suggestions about this approach or do you think this way is better?

@kentcdodds
Copy link
Member Author

I was not using Label and Input

The first rule of aria is "don't use aria" 😅 It's much better for accessibility to use an actual <label> than to use aria-label if possible. If a user isn't using a screen reader, how do they know that the field is for a password? Especially if the placeholder text isn't present? You'll probably want to have a visible label for every field you have unless it's purpose is made obvious by the contextual surroundings and even then be really thoughtful there.

@dguglielmi-git
Copy link

I thought that aria-label could be used when you don't have a label text visible on the screen, and it was the case since I was trying to get the Input within a Form without having a label element available, but, on the other hand, I do have a placeholder defined, so thinking in what you're saying, I could use that instead of adding more attributes.

solmatches added a commit to solmatches/react-week7-assignment-1 that referenced this issue Jun 15, 2022
input[type=password]의 경우 role을 가지고있지 않음
테스트할 때는 getByLabelText를 권장한다.

관련 토론:
- 암호에 role이 없는 이유애 대한 토론 내용도 나온다.
testing-library/dom-testing-library#567
rlamacraft added a commit to rspace-os/rspace-web that referenced this issue Jan 15, 2025
Password fields do not have a role and so have to be selected with *ByLabelText
instead of *ByRole. See
testing-library/dom-testing-library#567 for more
info.
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

7 participants