testing-library / dom-testing-library

🐙 Simple and complete DOM testing utilities that encourage good testing practices.
https://testing-library.com/dom
MIT License
3.26k stars 467 forks source link

getByRole doesn't work for passwords #1128

Closed dwjohnston closed 2 years ago

dwjohnston commented 2 years ago

Note, I think I answered my own answer. But can someone clarify - when searching for password fields - should I just search by labelText?

This is possibly a regression of https://github.com/testing-library/dom-testing-library/issues/737 ?

Relevant code or config:

const MyPassword = () => {
  return <label>Hello<input type="password" /></label>
}

const MyPassword2 = () => {
  return <><label htmlFor="password">Hello</label><input type="password" id="password" /></>
}
const MyPassword3 = () => {
  return <><label id="label">Hello</label><input type="password" aria-labelledby='label' /></>
}

describe('</>', () => {
  it("Passwords are selectedable label 1", () => {
    render(<MyPassword />)

    expect(screen.getByRole("textbox", {
      name: /hello/i
    })).toBeInTheDocument();
  });

  it("Passwords are selectedable label 2", () => {
    render(<MyPassword2 />)

    expect(screen.getByRole("textbox", {
      name: /hello/i
    })).toBeInTheDocument();
  });

  it("Passwords are selectedable label 3", () => {
    render(<MyPassword3 />)

    expect(screen.getByRole("textbox", {
      name: /hello/i
    })).toBeInTheDocument();
  });
});

What you did:

Try to write tests to assert that password fields exist.

What happened:

These tests fail.

TestingLibraryElementError: Unable to find an accessible element with the role "textbox" and name `/hello/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

    Ignored nodes: comments, <script />, <style />
    <body>
      <div>
        <label
          id="label"
        >
          Hello
        </label>
        <input
          aria-labelledby="label"
          type="password"
        />
      </div>
    </body>

      35 |     render(<MyPassword3 />)
      36 |
    > 37 |     expect(screen.getByRole("textbox", {
         |                   ^
      38 |       name: /hello/i
      39 |     })).toBeInTheDocument();
      40 |   });

Reproduction:

Full repro here.

https://github.com/dwjohnston/rtl-password

Run yarn && yarn test

Problem description:

<input type='password'> should have role 'textbox'

Whoops, no it shouldn't - as per the W3 aria spec - it has no role.

Suggested solution:

eps1lon commented 2 years ago

Duplicate of https://github.com/testing-library/dom-testing-library/issues/567 TL;DR: type="password" has no role and is therefore not suitable for getByRole

BudgieInWA commented 1 year ago

This should be added to the examples in the docs. Many of the examples use a "username" input, but there is no mention of "password" near any of them.

type=password having no role is a surprise for many users (as indicated by the many issues in this repo) so I think it would be very valuable to provide guidance from veterans/authors as to which query tool fits the philosophy best for this awkward situation that new users are likely to encounter.

MatanBobi commented 1 year ago

@BudgieInWA we're open for PR's in the docs repo if you feel that this can be helpful :)