diff --git a/src/__tests__/ariaAttributes.js b/src/__tests__/ariaAttributes.js
index 2f0b76de..1ceb210d 100644
--- a/src/__tests__/ariaAttributes.js
+++ b/src/__tests__/ariaAttributes.js
@@ -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(
+ ` `,
+ )
+ expect(getByRole('link', {current: filterByValue})).toBeInTheDocument()
+ },
+)
+
+test('Missing `aria-current` matches `current: false`', () => {
+ const {getByRole} = renderIntoDocument(
+ `StartAbout`,
+ )
+ expect(getByRole('link', {current: false})).toBeInTheDocument()
+})
+
test('`level` matches elements with `heading` role', () => {
const {getAllByRole, queryByRole} = renderIntoDocument(
`
diff --git a/src/queries/role.js b/src/queries/role.js
index 0b1ebd94..8f08ae67 100644
--- a/src/queries/role.js
+++ b/src/queries/role.js
@@ -4,6 +4,7 @@ import {
computeAriaSelected,
computeAriaChecked,
computeAriaPressed,
+ computeAriaCurrent,
computeAriaExpanded,
computeHeadingLevel,
getImplicitAriaRoles,
@@ -35,6 +36,7 @@ function queryAllByRole(
selected,
checked,
pressed,
+ current,
level,
expanded,
} = {},
@@ -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') {
@@ -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)
}
diff --git a/src/role-helpers.js b/src/role-helpers.js
index 58fdfb6f..7de55932 100644
--- a/src/role-helpers.js
+++ b/src/role-helpers.js
@@ -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
@@ -301,6 +314,7 @@ export {
computeAriaSelected,
computeAriaChecked,
computeAriaPressed,
+ computeAriaCurrent,
computeAriaExpanded,
computeHeadingLevel,
}
diff --git a/types/queries.d.ts b/types/queries.d.ts
index 42777ffd..1d20f0b5 100644
--- a/types/queries.d.ts
+++ b/types/queries.d.ts
@@ -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"`