Search code examples
reactjsaccessibilityreact-testing-library

Why doesn't getByRole get an element with a name (but it does with aria-label)?


What I'm trying is to get a <button/> with getByRole for unit testing. Here's a simplified example:

<Button
  classes={myCustomClass}
  name={'day'}
>
  <ViewDayOutlinedIcon /> {/** <- This is a Material UI icon */}
</Button>

// There are similar other buttons with different values in "name" attribute

The test case looks like...

render(<Component/>);
const dayButton = screen.getByRole('button', { name: 'day' });

// fire events with dayButton and expect something

The console says TestingLibraryElementError: Unable to find an accessible element with the role "button" and name "day", and shows the following

Here are the accessible roles:

  button:

    Name "":
    <button
      class="MuiButtonBase-root makeStyles-iconButtonRoot-19 MuiIconButton-root MuiIconButton-sizeMedium css-78trlr-MuiButtonBase-root-MuiIconButton-root"
      name="day"
      tabindex="0"
      type="button"
    />

If I replace name={'day'} with aria-label={'day'} in the component, the button can be found by screen.getByRole('button', { name: 'day' }).

Why does it happen? getByRole is supposed to find an element by a name attribute and a wigdet role (button, chekckbox, link, etc), right? I can't find the answer from RTL's doc.


Solution

  • W3C Accessible Name:

    The accessible name is the name of a user interface element. Each platform accessibility API provides the accessible name property. The value of the accessible name may be derived from a visible (e.g., the visible text on a button) or invisible (e.g., the text alternative that describes an icon) property of the user interface element.

    A simple use for the accessible name property may be illustrated by an "OK" button. The text "OK" is the accessible name.

    MDN basic buttons:

    Buttons should always have an accessible name. For most buttons, this name will be the same as the text inside the button, between the opening and closing tags.

    So the text "Day" is the accessible name for your case NOT the name attribute of the button HTML element.

    Try:

    screen.getByRole('button', { name: /day/i });
    

    The name option accepts a TextMatch, it can be a string or regex.