diff --git a/src/__tests__/element-queries.js b/src/__tests__/element-queries.js
index 8a8bc35f..253a64a4 100644
--- a/src/__tests__/element-queries.js
+++ b/src/__tests__/element-queries.js
@@ -412,6 +412,7 @@ test('queryAllByRole returns semantic html elements', () => {
+
`)
@@ -433,6 +434,9 @@ test('queryAllByRole returns semantic html elements', () => {
expect(queryAllByRole(/rowgroup/i)).toHaveLength(2)
expect(queryAllByRole(/(table)|(textbox)/i)).toHaveLength(3)
expect(queryAllByRole(/img/i)).toHaveLength(1)
+ expect(queryAllByRole('meter')).toHaveLength(1)
+ expect(queryAllByRole('progressbar')).toHaveLength(0)
+ expect(queryAllByRole('progressbar', {queryFallbacks: true})).toHaveLength(1)
})
test('getAll* matchers return an array', () => {
@@ -471,6 +475,7 @@ test('getAll* matchers return an array', () => {
+
,
`)
expect(getAllByAltText(/finding.*poster$/i)).toHaveLength(2)
@@ -482,6 +487,8 @@ test('getAll* matchers return an array', () => {
expect(getAllByDisplayValue(/cars$/)).toHaveLength(2)
expect(getAllByText(/^where/i)).toHaveLength(1)
expect(getAllByRole(/container/i)).toHaveLength(1)
+ expect(getAllByRole('meter')).toHaveLength(1)
+ expect(getAllByRole('progressbar', {queryFallbacks: true})).toHaveLength(1)
})
test('getAll* matchers throw for 0 matches', () => {
@@ -658,6 +665,18 @@ test('using jest helpers to check element role', () => {
expect(getByRole('dialog')).toHaveTextContent('Contents')
})
+test('using jest helpers to check element fallback roles', () => {
+ const {getByRole} = render(`
+
+ Contents
+
+ `)
+
+ expect(getByRole('progressbar', {queryFallbacks: true})).toHaveTextContent(
+ 'Contents',
+ )
+})
+
test('test the debug helper prints the dom state here', () => {
const originalDebugPrintLimit = process.env.DEBUG_PRINT_LIMIT
const Large = `
diff --git a/src/__tests__/queries.find.js b/src/__tests__/queries.find.js
index facceba2..d3d59832 100644
--- a/src/__tests__/queries.find.js
+++ b/src/__tests__/queries.find.js
@@ -33,6 +33,7 @@ test('find asynchronously finds elements', async () => {
+
`)
await expect(findByLabelText('test-label')).resolves.toBeTruthy()
@@ -56,6 +57,15 @@ test('find asynchronously finds elements', async () => {
await expect(findByRole('dialog')).resolves.toBeTruthy()
await expect(findAllByRole('dialog')).resolves.toHaveLength(1)
+ await expect(findByRole('meter')).resolves.toBeTruthy()
+ await expect(findAllByRole('meter')).resolves.toHaveLength(1)
+ await expect(
+ findByRole('progressbar', {queryFallbacks: true}),
+ ).resolves.toBeTruthy()
+ await expect(
+ findAllByRole('progressbar', {queryFallbacks: true}),
+ ).resolves.toHaveLength(1)
+
await expect(findByTestId('test-id')).resolves.toBeTruthy()
await expect(findAllByTestId('test-id')).resolves.toHaveLength(1)
})
diff --git a/src/queries/role.js b/src/queries/role.js
index dfc8a331..55e50e10 100644
--- a/src/queries/role.js
+++ b/src/queries/role.js
@@ -21,6 +21,7 @@ function queryAllByRole(
hidden = getConfig().defaultHidden,
trim,
normalizer,
+ queryFallbacks = false,
} = {},
) {
const matcher = exact ? matches : fuzzyMatches
@@ -40,7 +41,20 @@ function queryAllByRole(
const isRoleSpecifiedExplicitly = node.hasAttribute('role')
if (isRoleSpecifiedExplicitly) {
- return matcher(node.getAttribute('role'), node, role, matchNormalizer)
+ const roleValue = node.getAttribute('role')
+ if (queryFallbacks) {
+ return roleValue
+ .split(' ')
+ .filter(Boolean)
+ .some(text => matcher(text, node, role, matchNormalizer))
+ }
+ // if a custom normalizer is passed then let normalizer handle the role value
+ if (normalizer) {
+ return matcher(roleValue, node, role, matchNormalizer)
+ }
+ // other wise only send the first word to match
+ const [firstWord] = roleValue.split(' ')
+ return matcher(firstWord, node, role, matchNormalizer)
}
const implicitRoles = getImplicitAriaRoles(node)