Skip to content

Commit

Permalink
Feature: adds aria-expanded filter to *ByRole (#821)
Browse files Browse the repository at this point in the history
Co-authored-by: Luis Rodrigues <luis.rodrigues@springernature.com>
Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>
  • Loading branch information
3 people authored Dec 11, 2020
1 parent 21c4db3 commit f753c8a
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 0 deletions.
31 changes: 31 additions & 0 deletions src/__tests__/ariaAttributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ test('`checked` throws on unsupported roles', () => {
)
})

test('`expanded` throws on unsupported roles', () => {
const {getByRole} = render(`<h1 aria-expanded="true">Heading</h1>`)
expect(() =>
getByRole('heading', {expanded: true}),
).toThrowErrorMatchingInlineSnapshot(
`"\\"aria-expanded\\" is not supported on role \\"heading\\"."`,
)
})

test('`checked: true|false` matches `checked` checkboxes', () => {
const {getByRole} = renderIntoDocument(
`<div>
Expand Down Expand Up @@ -202,3 +211,25 @@ test('`level` throws on unsupported roles', () => {
`"Role \\"button\\" cannot have \\"level\\" property."`,
)
})

test('`expanded: true|false` matches `expanded` buttons', () => {
const {getByRole} = renderIntoDocument(
`<div>
<button aria-expanded="true" />
<button aria-expanded="false" />
</div>`,
)
expect(getByRole('button', {expanded: true})).toBeInTheDocument()
expect(getByRole('button', {expanded: false})).toBeInTheDocument()
})

test('`expanded: true|false` matches `expanded` elements with proper role', () => {
const {getByRole} = renderIntoDocument(
`<div>
<span role="button" aria-expanded="true">✔</span>
<span role="button" aria-expanded="false">𝒙</span>
</div>`,
)
expect(getByRole('button', {expanded: true})).toBeInTheDocument()
expect(getByRole('button', {expanded: false})).toBeInTheDocument()
})
12 changes: 12 additions & 0 deletions src/queries/role.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
computeAriaSelected,
computeAriaChecked,
computeAriaPressed,
computeAriaExpanded,
computeHeadingLevel,
getImplicitAriaRoles,
prettyRoles,
Expand Down Expand Up @@ -35,6 +36,7 @@ function queryAllByRole(
checked,
pressed,
level,
expanded,
} = {},
) {
checkContainerType(container)
Expand Down Expand Up @@ -69,6 +71,13 @@ function queryAllByRole(
}
}

if (expanded !== undefined) {
// guard against unknown roles
if (allRoles.get(role)?.props['aria-expanded'] === undefined) {
throw new Error(`"aria-expanded" is not supported on role "${role}".`)
}
}

const subtreeIsInaccessibleCache = new WeakMap()
function cachedIsSubtreeInaccessible(element) {
if (!subtreeIsInaccessibleCache.has(element)) {
Expand Down Expand Up @@ -115,6 +124,9 @@ function queryAllByRole(
if (pressed !== undefined) {
return pressed === computeAriaPressed(element)
}
if (expanded !== undefined) {
return expanded === computeAriaExpanded(element)
}
if (level !== undefined) {
return level === computeHeadingLevel(element)
}
Expand Down
10 changes: 10 additions & 0 deletions src/role-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,15 @@ function computeAriaPressed(element) {
return checkBooleanAttribute(element, 'aria-pressed')
}

/**
* @param {Element} element -
* @returns {boolean | undefined} - false/true if (not)expanded, undefined if not expand-able
*/
function computeAriaExpanded(element) {
// https://www.w3.org/TR/wai-aria-1.1/#aria-expanded
return checkBooleanAttribute(element, 'aria-expanded')
}

function checkBooleanAttribute(element, attribute) {
const attributeValue = element.getAttribute(attribute)
if (attributeValue === 'true') {
Expand Down Expand Up @@ -292,5 +301,6 @@ export {
computeAriaSelected,
computeAriaChecked,
computeAriaPressed,
computeAriaExpanded,
computeHeadingLevel,
}
5 changes: 5 additions & 0 deletions types/queries.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ export interface ByRoleOptions extends MatcherOptions {
* pressed in the accessibility tree, i.e., `aria-pressed="true"`
*/
pressed?: boolean
/**
* If true only includes elements in the query set that are marked as
* expanded in the accessibility tree, i.e., `aria-expanded="true"`
*/
expanded?: boolean
/**
* Includes elements with the `"heading"` role matching the indicated level,
* either by the semantic HTML heading elements `<h1>-<h6>` or matching
Expand Down

0 comments on commit f753c8a

Please sign in to comment.