Skip to content

Commit

Permalink
feat(suggestions): add option to get specific query suggestions (#627)
Browse files Browse the repository at this point in the history
  • Loading branch information
smeijer committed Jun 13, 2020
1 parent b9900f8 commit 30a1ee8
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 10 deletions.
92 changes: 92 additions & 0 deletions src/__tests__/suggestions.js
Expand Up @@ -353,3 +353,95 @@ test('getSuggestedQuery returns rich data for tooling', () => {

expect(getSuggestedQuery(div).toString()).toEqual(`getByText(/cancel/i)`)
})

test('getSuggestedQuery can return specified methods in addition to the best', () => {
const {container} = render(`
<label for="username">label</label>
<input
id="username"
name="name"
placeholder="placeholder"
data-testid="testid"
title="title"
alt="alt"
value="value"
type="text"
/>
<button>button</button>
`)

const input = container.querySelector('input')
const button = container.querySelector('button')

expect(getSuggestedQuery(input, 'get', 'Role')).toMatchObject({
queryName: 'Role',
queryMethod: 'getByRole',
queryArgs: ['textbox', {name: /label/i}],
variant: 'get',
})

expect(getSuggestedQuery(input, 'get', 'LabelText')).toMatchObject({
queryName: 'LabelText',
queryMethod: 'getByLabelText',
queryArgs: [/label/i],
variant: 'get',
})

expect(getSuggestedQuery(input, 'get', 'PlaceholderText')).toMatchObject({
queryName: 'PlaceholderText',
queryMethod: 'getByPlaceholderText',
queryArgs: [/placeholder/i],
variant: 'get',
})

expect(getSuggestedQuery(button, 'get', 'Text')).toMatchObject({
queryName: 'Text',
queryMethod: 'getByText',
queryArgs: [/button/],
variant: 'get',
})

expect(getSuggestedQuery(input, 'get', 'DisplayValue')).toMatchObject({
queryName: 'DisplayValue',
queryMethod: 'getByDisplayValue',
queryArgs: [/value/i],
variant: 'get',
})

expect(getSuggestedQuery(input, 'get', 'AltText')).toMatchObject({
queryName: 'AltText',
queryMethod: 'getByAltText',
queryArgs: [/alt/],
variant: 'get',
})

expect(getSuggestedQuery(input, 'get', 'Title')).toMatchObject({
queryName: 'Title',
queryMethod: 'getByTitle',
queryArgs: [/title/i],
variant: 'get',
})

expect(getSuggestedQuery(input, 'get', 'TestId')).toMatchObject({
queryName: 'TestId',
queryMethod: 'getByTestId',
queryArgs: ['testid'],
variant: 'get',
})

// return undefined if requested query can't be made
expect(getSuggestedQuery(button, 'get', 'TestId')).toBeUndefined()
})

test('getSuggestedQuery does not create suggestions for script and style elements', () => {
const {container} = render(`
<script data-testid="script"></script>
<style data-testid="style"></style>
`)

const script = container.querySelector('script')
const style = container.querySelector('style')

expect(getSuggestedQuery(script, 'get', 'TestId')).toBeUndefined()
expect(getSuggestedQuery(style, 'get', 'TestId')).toBeUndefined()
})
37 changes: 27 additions & 10 deletions src/suggestions.js
Expand Up @@ -35,7 +35,11 @@ function getRegExpMatcher(string) {
}

function makeSuggestion(queryName, content, {variant = 'get', name}) {
const queryArgs = [queryName === 'Role' ? content : getRegExpMatcher(content)]
const queryArgs = [
queryName === 'Role' || queryName === 'TestId'
? content
: getRegExpMatcher(content),
]

if (name) {
queryArgs.push({name: new RegExp(escapeRegExp(name.toLowerCase()), 'i')})
Expand Down Expand Up @@ -64,45 +68,58 @@ function makeSuggestion(queryName, content, {variant = 'get', name}) {
}
}

export function getSuggestedQuery(element, variant) {
function canSuggest(currentMethod, requestedMethod, data) {
return data && (!requestedMethod || requestedMethod === currentMethod)
}

export function getSuggestedQuery(element, variant, method) {
// don't create suggestions for script and style elements
if (element.matches(DEFAULT_IGNORE_TAGS)) {
return undefined
}

const role =
element.getAttribute('role') ?? getImplicitAriaRoles(element)?.[0]
if (role) {
if (canSuggest('Role', method, role)) {
return makeSuggestion('Role', role, {
variant,
name: computeAccessibleName(element),
})
}

const labelText = getLabelTextFor(element)
if (labelText) {
if (canSuggest('LabelText', method, labelText)) {
return makeSuggestion('LabelText', labelText, {variant})
}

const placeholderText = element.getAttribute('placeholder')
if (placeholderText) {
if (canSuggest('PlaceholderText', method, placeholderText)) {
return makeSuggestion('PlaceholderText', placeholderText, {variant})
}

const textContent = normalize(getNodeText(element))
if (textContent && !element.matches(DEFAULT_IGNORE_TAGS)) {
if (canSuggest('Text', method, textContent)) {
return makeSuggestion('Text', textContent, {variant})
}

if (element.value) {
if (canSuggest('DisplayValue', method, element.value)) {
return makeSuggestion('DisplayValue', normalize(element.value), {variant})
}

const alt = element.getAttribute('alt')
if (alt) {
if (canSuggest('AltText', method, alt)) {
return makeSuggestion('AltText', alt, {variant})
}

const title = element.getAttribute('title')

if (title) {
if (canSuggest('Title', method, title)) {
return makeSuggestion('Title', title, {variant})
}

const testId = element.getAttribute('data-testid')
if (canSuggest('TestId', method, testId)) {
return makeSuggestion('TestId', testId, {variant})
}

return undefined
}

0 comments on commit 30a1ee8

Please sign in to comment.