Skip to content

Commit

Permalink
fix: more improvements to suggestions (#599)
Browse files Browse the repository at this point in the history
* fix: don't suggest query that would result in different element

* fix: escape regexp in suggestions
  • Loading branch information
benmonro committed Jun 1, 2020
1 parent bec190b commit caf76e3
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 8 deletions.
28 changes: 28 additions & 0 deletions src/__tests__/suggestions.js
Expand Up @@ -35,6 +35,18 @@ test('respects ignores', () => {
).not.toThrowError()
})

test('does not suggest query that would give a different element', () => {
renderIntoDocument(`
<div data-testid="foo"><img src="foo" /></div>
<div data-testid="bar"><a href="/foo"><div role="figure"><img src="foo" /></div></a></div>
<a data-testid="baz"><h1>link text</h1></a>
`)

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(`<button data-testid="foo">submit</button>`)

Expand All @@ -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(`<label><span>bar</span><input title="foo" /></label>`)

expect(() => screen.getByTitle('foo')).toThrowError(/getByLabelText\("bar"\)/)
})

test('should not suggest if there would be mixed suggestions', () => {
renderIntoDocument(`
<button data-testid="foo">submit</button>
Expand Down Expand Up @@ -145,6 +163,16 @@ test('should suggest img role w/ alt text', () => {
)
})

test('escapes regular expressions in suggestion', () => {
renderIntoDocument(
`<img src="foo.png" alt="The Problem (picture of a question mark)" data-testid="foo" />`,
)

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(
`<label for="foo">Username</label><input data-testid="foo" id="foo" />`,
Expand Down
18 changes: 10 additions & 8 deletions 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()

Expand All @@ -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),
Expand Down

0 comments on commit caf76e3

Please sign in to comment.