dom-testing-library icon indicating copy to clipboard operation
dom-testing-library copied to clipboard

`ByLabelText` does not ignore invalid IDREF in `aria-labelledby`

Open silvenon opened this issue 4 years ago • 5 comments

Relevant code or config:

/**
 * @jest-environment jsdom
 */

const { getByRole, getByLabelText } = require('@testing-library/dom')

test('aria-labelledby', () => {
  const container = document.createElement('div')
  container.innerHTML = `
    <label>
      Name: <input aria-labelledby="oops">
    </label>
  `
  getByRole(container, 'textbox', { name: /Name/ })
  getByLabelText(container, /Name/)
})

What you did:

npx jest

What happened:

 FAIL  ./test.js
  ✕ aria-labelledby (64 ms)

  ● aria-labelledby

    TestingLibraryElementError: Found a label with the text of: /Name/, however no form control was found associated to that label. Make sure you're using the "for" attribute or "aria-labelledby" attribute correctly.

    Ignored nodes: comments, <script />, <style />
    <div>
      
        
      <label>
        
          Name: 
        <input
          aria-labelledby="oops"
        />
        
        
      </label>
      
      
    </div>

      13 |   `
      14 |   getByRole(container, 'textbox', { name: /Name/ })
    > 15 |   getByLabelText(container, /Name/)
         |   ^
      16 | })
      17 |

Reproduction:

silvenon/dom-testing-library-template

Problem description:

Perhaps I'm wrong, but based on what I read in the ByRole docs it seems that in this context the name option should behave the same way as ByLabelText.

Suggested solution:

In that case getByRole should also throw because aria-labelledby is wrong.

silvenon avatar Sep 13 '21 08:09 silvenon

Why should ByRole throw? There's a textbox with the name Name: . ByLabelText seems to not recognize <input /> as a form control though it's unclear why. <input /> is equivalent to <input type="text" />:

The missing value default and the invalid value default are the Text state.

-- https://html.spec.whatwg.org/multipage/input.html#the-input-element

How does the test behave without the invalid aria-labelledby? It shouldn't have any effect.

eps1lon avatar Sep 13 '21 09:09 eps1lon

ByLabelText seems to not recognize <input /> as a form control though it's unclear why.

Because aria-labelledby points away from the <label>, removing that attribute fixes the assertion.

Why should ByRole throw? There's a textbox with the name Name: .

The docs for ByRole say:

The accessible name is for simple cases equal to e.g. the label of a form element

and because the form element points away from the label I would expect the assertion not to work based on what I think the accessible name is:

name is generated from values provided by the author in explicit markup features such as the aria-label and aria-labelledby attribute

Accessible Name and Description

silvenon avatar Sep 13 '21 09:09 silvenon

aria-labelledby is ignored if it's invalid. I don't understand why this should affect if an element is considered a form control or not.

eps1lon avatar Sep 13 '21 10:09 eps1lon

So then ByLabelText should be adjusted to ignore invalid aria-labelledby, right?

silvenon avatar Sep 14 '21 08:09 silvenon

So then ByLabelText should be adjusted to ignore invalid aria-labelledby, right?

If they want to implement accname in that regard, yes. But ByLabelText is not equivalent to ByRole#name so I wouldn't know.

if computing a name, and the current node has an aria-labelledby attribute that contains at least one valid IDREF

-- https://www.w3.org/TR/accname-1.2/

Focus on the "valid IDREF".

eps1lon avatar Sep 16 '21 10:09 eps1lon