diff --git a/src/__tests__/ariaAttributes.js b/src/__tests__/ariaAttributes.js index 236ac1b0..7984d5e0 100644 --- a/src/__tests__/ariaAttributes.js +++ b/src/__tests__/ariaAttributes.js @@ -36,6 +36,28 @@ test('`expanded` throws on unsupported roles', () => { ) }) +test('`busy` throws on unsupported roles', () => { + const {getByRole} = render( + `
Hello, Dave!
`, + ) + expect(() => + getByRole('none', {busy: true}), + ).toThrowErrorMatchingInlineSnapshot( + `"aria-busy" is not supported on role "none".`, + ) +}) + +test('`busy: true|false` matches `busy` regions', () => { + const {getByRole} = renderIntoDocument( + `
+
+
+
`, + ) + expect(getByRole('log', {busy: true})).toBeInTheDocument() + expect(getByRole('log', {busy: false})).toBeInTheDocument() +}) + test('`checked: true|false` matches `checked` checkboxes', () => { const {getByRole} = renderIntoDocument( `
diff --git a/src/queries/role.ts b/src/queries/role.ts index 30b7f249..98b08848 100644 --- a/src/queries/role.ts +++ b/src/queries/role.ts @@ -10,6 +10,7 @@ import { } from 'aria-query' import { computeAriaSelected, + computeAriaBusy, computeAriaChecked, computeAriaPressed, computeAriaCurrent, @@ -47,6 +48,7 @@ const queryAllByRole: AllByRole = ( description, queryFallbacks = false, selected, + busy, checked, pressed, current, @@ -72,6 +74,16 @@ const queryAllByRole: AllByRole = ( } } + if (busy !== undefined) { + // guard against unknown roles + if ( + allRoles.get(role as ARIARoleDefinitionKey)?.props['aria-busy'] === + undefined + ) { + throw new Error(`"aria-busy" is not supported on role "${role}".`) + } + } + if (checked !== undefined) { // guard against unknown roles if ( @@ -203,6 +215,9 @@ const queryAllByRole: AllByRole = ( if (selected !== undefined) { return selected === computeAriaSelected(element) } + if (busy !== undefined) { + return busy === computeAriaBusy(element) + } if (checked !== undefined) { return checked === computeAriaChecked(element) } diff --git a/src/role-helpers.js b/src/role-helpers.js index 05d216f6..bc134f27 100644 --- a/src/role-helpers.js +++ b/src/role-helpers.js @@ -240,6 +240,15 @@ function computeAriaSelected(element) { return checkBooleanAttribute(element, 'aria-selected') } +/** + * @param {Element} element - + * @returns {boolean} - + */ +function computeAriaBusy(element) { + // https://www.w3.org/TR/wai-aria-1.1/#aria-busy + return element.getAttribute('aria-busy') === 'true' +} + /** * @param {Element} element - * @returns {boolean | undefined} - false/true if (not)checked, undefined if not checked-able @@ -369,6 +378,7 @@ export { prettyRoles, isInaccessible, computeAriaSelected, + computeAriaBusy, computeAriaChecked, computeAriaPressed, computeAriaCurrent, diff --git a/types/queries.d.ts b/types/queries.d.ts index a24af651..c6ce9054 100644 --- a/types/queries.d.ts +++ b/types/queries.d.ts @@ -80,6 +80,11 @@ export interface ByRoleOptions { * selected in the accessibility tree, i.e., `aria-selected="true"` */ selected?: boolean + /** + * If true only includes elements in the query set that are marked as + * busy in the accessibility tree, i.e., `aria-busy="true"` + */ + busy?: boolean /** * If true only includes elements in the query set that are marked as * checked in the accessibility tree, i.e., `aria-checked="true"`