Search code examples
reactjsunit-testingreact-testing-librarywai-aria

react-testing-library query whitespace issue


I am facing challanges querying with the reccommended byRole. I used the screen.debug() to confirm that the node I want to query is in DOM. The aria-labelledby value is passed to react component as prop and then set to the underlying button element as attribue value.

await screen.findAllByRole('button', { name: /Kärpät/i }); // [node]
await screen.findAllByRole('button', { name: /Syväkankaan Kioski/i }) // Unable to find role="button" and name "Syväkankaan Kioski"

I managed to workaround with using findAllByTestId but I would prefer to use the roles and would like to understand what is happening. Somehow the whitespace causes matcher to fail!?

screen.debug(await screen.findAllByRole('button')); log output:

console.log
    <button
      aria-label="Lopeta seuraaminen"
      aria-labelledby="Kärpät"
      class="follow-keyword-toggle-button follow-keyword-toggle-button--active"
      data-testid="follow-button-1477"
      type="button"
    >
      <i
        class="fas fa-heart"
      />
    </button>


  console.log
    <button
      aria-label="Lopeta seuraaminen"
      aria-labelledby="Syväkankaan Kioski"
      class="follow-keyword-toggle-button follow-keyword-toggle-button--active"
      data-testid="follow-button-111"
      type="button"
    >
      <i
        class="fas fa-heart"
      />
    </button>

PS I'm implementing a design so dont judge for using button without a text :)


Solution

  • Looks like you are passing the optional "accessible name" parameter to findAllByRole but you have to understand how an accessible name is generated to pass the correct value.

    There is a precedence list for where the accessible name comes from. In your code example, you are specifying two accessible names: aria-label and aria-labelledby. Only one will be used. aria-labelledby has higher precedence than aria-label so the aria-label will be ignored. See steps 2B (aria-labelledby) and 2C (aria-label) in the above URL.

    Also note that aria-labelledby should be the ID or list of IDs of other elements in the DOM. I can't tell from your example:

     aria-labelledby="Kärpät"
    

    if "Kärpät" is the ID of another element or if "Kärpät" is the actual label (a text literal). If the latter, then you're not using it correctly.

    Similarly with:

     aria-labelledby="Syväkankaan Kioski"
    

    aria-labelledby can be a list of IDs so if you have two DOM elements in your code, one with id="Syväkankaan" and one with id="Kioski", then you're using it correctly. But if you expect "Syväkankaan Kioski" to be the label, then you're not using it correctly.

    From the way you're calling findAllByRole, it appears you think aria-labelledby is a literal string, which is not correct.