diff --git a/src/__tests__/suggestions.js b/src/__tests__/suggestions.js
index 485299d5..e0ecd51c 100644
--- a/src/__tests__/suggestions.js
+++ b/src/__tests__/suggestions.js
@@ -35,6 +35,18 @@ test('respects ignores', () => {
).not.toThrowError()
})
+test('does not suggest query that would give a different element', () => {
+ renderIntoDocument(`
+
+
+ link text
+ `)
+
+ expect(() => screen.getByTestId('foo')).not.toThrowError()
+ expect(() => screen.getByTestId('bar')).not.toThrowError()
+ expect(() => screen.getByTestId('baz')).not.toThrowError()
+})
+
test('does not suggest when using getByRole', () => {
renderIntoDocument(``)
@@ -57,6 +69,12 @@ test(`should not suggest if the suggestion would give different results`, () =>
).not.toThrowError()
})
+test('should suggest by label over title', () => {
+ renderIntoDocument(``)
+
+ expect(() => screen.getByTitle('foo')).toThrowError(/getByLabelText\("bar"\)/)
+})
+
test('should not suggest if there would be mixed suggestions', () => {
renderIntoDocument(`
@@ -145,6 +163,16 @@ test('should suggest img role w/ alt text', () => {
)
})
+test('escapes regular expressions in suggestion', () => {
+ renderIntoDocument(
+ ``,
+ )
+
+ expect(() => screen.getByTestId('foo')).toThrowError(
+ /getByRole\("img", \{name: \/the problem \\\(picture of a question mark\\\)\/i\}\)/,
+ )
+})
+
test('should suggest getByLabelText when no role available', () => {
renderIntoDocument(
``,
diff --git a/src/suggestions.js b/src/suggestions.js
index 20735889..d67b373b 100644
--- a/src/suggestions.js
+++ b/src/suggestions.js
@@ -1,8 +1,8 @@
import {computeAccessibleName} from 'dom-accessibility-api'
-import {getRoles} from './role-helpers'
import {getDefaultNormalizer} from './matches'
import {getNodeText} from './get-node-text'
import {DEFAULT_IGNORE_TAGS} from './config'
+import {getImplicitAriaRoles} from './role-helpers'
const normalize = getDefaultNormalizer()
@@ -26,23 +26,25 @@ function getLabelTextFor(element) {
}
return undefined
}
-
+function escapeRegExp(string) {
+ return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&') // $& means the whole matched string
+}
function makeSuggestion(queryName, content, {variant, name}) {
return {
queryName,
toString() {
- const options = name ? `, {name: /${name.toLowerCase()}/i}` : ''
+ const options = name
+ ? `, {name: /${escapeRegExp(name.toLowerCase())}/i}`
+ : ''
return `${variant}By${queryName}("${content}"${options})`
},
}
}
export function getSuggestedQuery(element, variant) {
- const roles = getRoles(element)
-
- const roleNames = Object.keys(roles)
- if (roleNames.length) {
- const [role] = roleNames
+ const role =
+ element.getAttribute('role') ?? getImplicitAriaRoles(element)?.[0]
+ if (role) {
return makeSuggestion('Role', role, {
variant,
name: computeAccessibleName(element),