Add `level` option for `*ByRole('heading')`
See original GitHub issueDescribe the feature youād like:
Add new queries for *ByHeadingLevel that allow the specification of the heading level by which to query, e.g. getAllByHeadingLevel('h2').
I know that suggestions about adding queries by tag have been rejected because they go against the user-centric testing principles, but I think this particular case is user-centric, especially for those using assistive technologies.
Suggested implementation:
getByHeadingLevel, queryByHeadingLevel, getAllByHeadingLevel, queryAllByHeadingLevel, findByHeadingLevel, findAllByHeadingLevel
getByHeadingLevel(
container: HTMLElement, // or skip this if using `screen`
level: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
// I don't think this would need to use to standard options like `exact` (with the way it's typed)
// or `normalizer`, but please correct me if I'm wrong
): HTMLElement
Describe alternatives youāve considered:
While *ByRole('heading') can grab the headings on the DOM, there is currently no way to specify the heading levels. And while a custom query could be made, or simply using document.querySelector(), this particular query seems like it should be a built-in as it is one of the ways that people using assistive technologies navigate web pages.
Teachability, Documentation, Adoption, Migration Strategy:
Because the syntax is similar to other queries, I imagine the teachability and adoption should take minimal effort (beyond whatās needed to learn any of the other queries).
Possible Documentation
ByHeadingLevel
getByHeadingLevel, queryByHeadingLevel, getAllByHeadingLevel, queryAllByHeadingLevel, findByHeadingLevel, findAllByHeadingLevel
getByHeadingLevel(
container: HTMLElement, // if you're using `screen`, then skip this argument
level: HeadingLevel ('h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6')
// I don't think this would need to use to standard options like `exact` (with the way it's typed)
// or `normalizer`, but please correct me if I'm wrong
): HTMLElement
Queries headings by their level and returns the element ā either the HTML heading element (<h1> - <h6>) or the element with role="heading" and aria-level with matching level.
Although ByHeadingLevel queries elements with role="heading" and the aria-level attribute present, it is strongly encouraged to use the semantic HTML heading elements (<h1> - <h6>).
Note that the ByHeadingLevel query only supports heading levels h1-h6. While, it is possible to use aria-level with a heading level greater than 6, it is discouraged due to inconsistent browser and assistive technology support.
For example in
<body>
<main>
<h1>All About Tuesday</h1>
<h2>What I Did Today</h2>
<p>I didn't get as much done today as I would have liked.</p>
<h3>Drinking Coffee</h3>
<p>I drank a lot of iced coffee. It was a Kona blend with oat milk.</p>
<p>I'm really bad at coming up with examples.</p>
<h2>What I Didn't Accomplish Today</h2>
<p>Everything else.</p>
</main>
</body>
getByHeadingLabel('h3') would return <h3>Drinking Coffee</h3>.
getAllByHeadingLabel('h2') would return [<h2>What I Did Today</h2>, <h2>What I Didn't Accomplish Today</h2>].
(ā¦plus some reference links thrown inā¦)
Issue Analytics
- State:
- Created 3 years ago
- Reactions:2
- Comments:9 (8 by maintainers)

Top Related StackOverflow Question
Iād prefer
ByRole('heading', { level: n }). It could query byaria-leveland would be in line with the currentpressed,selected, andexpandedfilters inByRole.Maybe
aria-queryalready has some built-in validation for allowed values ofaria-level.I think we already do similar checks for the existing filters. Anybody that wants to work on this might want to check out #540, #692 or #729.
Though I think we shouldnāt throw with āaria-X is not supportedā but rather with āthe element cannot have Xā. They donāt always come from aria attributes and, in the end, ARIA is just an implementation details š