Skip to content

Commit

Permalink
feat(ByRole): Allow filter by aria-current state (testing-library#943)
Browse files Browse the repository at this point in the history
Co-authored-by: eps1lon <silbermann.sebastian@gmail.com>
  • Loading branch information
savcni01 and eps1lon authored Aug 25, 2021
1 parent d03f4f6 commit fbbb29a
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/__tests__/ariaAttributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,31 @@ test('`pressed: true|false` matches `pressed` elements with proper role', () =>
expect(getByRole('button', {pressed: false})).toBeInTheDocument()
})

test.each([
['true', true],
['false', false],
['date', 'date'],
['location', 'location'],
['page', 'page'],
['step', 'step'],
['time', 'time'],
])(
'`aria-current="%s"` matches `current: %j` elements with proper role',
(ariaCurrentValue, filterByValue) => {
const {getByRole} = renderIntoDocument(
` <a href="/" aria-current="${ariaCurrentValue}"></a>`,
)
expect(getByRole('link', {current: filterByValue})).toBeInTheDocument()
},
)

test('Missing `aria-current` matches `current: false`', () => {
const {getByRole} = renderIntoDocument(
`<a aria-current="true" href="/">Start</a><a href="/about">About</a>`,
)
expect(getByRole('link', {current: false})).toBeInTheDocument()
})

test('`level` matches elements with `heading` role', () => {
const {getAllByRole, queryByRole} = renderIntoDocument(
`<div>
Expand Down
15 changes: 15 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,
computeAriaCurrent,
computeAriaExpanded,
computeHeadingLevel,
getImplicitAriaRoles,
Expand Down Expand Up @@ -35,6 +36,7 @@ function queryAllByRole(
selected,
checked,
pressed,
current,
level,
expanded,
} = {},
Expand Down Expand Up @@ -64,6 +66,16 @@ function queryAllByRole(
}
}

if (current !== undefined) {
/* istanbul ignore next */
// guard against unknown roles
// All currently released ARIA versions support `aria-current` on all roles.
// Leaving this for symetry and forward compatibility
if (allRoles.get(role)?.props['aria-current'] === undefined) {
throw new Error(`"aria-current" is not supported on role "${role}".`)
}
}

if (level !== undefined) {
// guard against using `level` option with any role other than `heading`
if (role !== 'heading') {
Expand Down Expand Up @@ -124,6 +136,9 @@ function queryAllByRole(
if (pressed !== undefined) {
return pressed === computeAriaPressed(element)
}
if (current !== undefined) {
return current === computeAriaCurrent(element)
}
if (expanded !== undefined) {
return expanded === computeAriaExpanded(element)
}
Expand Down
14 changes: 14 additions & 0 deletions src/role-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,19 @@ function computeAriaPressed(element) {
return checkBooleanAttribute(element, 'aria-pressed')
}

/**
* @param {Element} element -
* @returns {boolean | string | null} -
*/
function computeAriaCurrent(element) {
// https://www.w3.org/TR/wai-aria-1.1/#aria-current
return (
checkBooleanAttribute(element, 'aria-current') ??
element.getAttribute('aria-current') ??
false
)
}

/**
* @param {Element} element -
* @returns {boolean | undefined} - false/true if (not)expanded, undefined if not expand-able
Expand Down Expand Up @@ -301,6 +314,7 @@ export {
computeAriaSelected,
computeAriaChecked,
computeAriaPressed,
computeAriaCurrent,
computeAriaExpanded,
computeHeadingLevel,
}
4 changes: 4 additions & 0 deletions types/queries.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ export interface ByRoleOptions extends MatcherOptions {
* pressed in the accessibility tree, i.e., `aria-pressed="true"`
*/
pressed?: boolean
/**
* Filters elements by their `aria-current` state. `true` and `false` match `aria-current="true"` and `aria-current="false"` (as well as a missing `aria-current` attribute) respectively.
*/
current?: boolean | string
/**
* If true only includes elements in the query set that are marked as
* expanded in the accessibility tree, i.e., `aria-expanded="true"`
Expand Down

0 comments on commit fbbb29a

Please sign in to comment.