Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: suggestions for which query to use #586

Merged
merged 34 commits into from May 29, 2020
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
0cf9fd9
feat: suggestions for which query to use
May 25, 2020
7cb52ba
coverage bumped
May 25, 2020
e0b7f69
Merge branch 'master' into feature/suggestions
benmonro May 25, 2020
75c492c
more tests, label text working
May 25, 2020
51c377c
more cases for labelText
May 25, 2020
be480ad
removed commented out code
May 25, 2020
63b26cb
added *ByDisplayValue
May 25, 2020
a0dc8f9
all queries supported now
May 26, 2020
5ee9649
cleanup
May 26, 2020
625ce15
added types for suggestions
May 26, 2020
1db13e6
export suggestions from index
May 26, 2020
30e64e2
fixed a couple lint warnings
May 26, 2020
e3bdcff
Update src/__tests__/suggestions.js
benmonro May 29, 2020
a9394b0
Update src/config.js
benmonro May 29, 2020
b496f09
Update src/__tests__/suggestions.js
benmonro May 29, 2020
32883e7
Update src/config.js
benmonro May 29, 2020
7354bc7
Update src/suggestions.js
benmonro May 29, 2020
effdd92
Update src/query-helpers.js
benmonro May 29, 2020
0d5c6e4
PR feedback
May 29, 2020
7ec23c2
refactor to getLabelFor
May 29, 2020
515bee0
Merge branch 'feature/suggestions' of https://github.com/benmonro/dom…
benmonro May 29, 2020
cf78610
formatting
benmonro May 29, 2020
042bd93
added support for suggest:false
benmonro May 29, 2020
e536d05
case ignored regex
benmonro May 29, 2020
8fb28da
using full query name for get & getAll & query
benmonro May 29, 2020
18b1813
suggest on labeltext
benmonro May 29, 2020
2a741e9
suggest on queryAllBy
benmonro May 29, 2020
ac9e9df
more tests
benmonro May 29, 2020
53460df
rename showSuggs to throwSuggs
benmonro May 29, 2020
fa69912
PR feedback
benmonro May 29, 2020
8861c24
Merge branch 'master' into feature/suggestions
benmonro May 29, 2020
7ec0b97
matches.d.ts
benmonro May 29, 2020
51618bd
Merge branch 'feature/suggestions' of https://github.com/benmonro/dom…
benmonro May 29, 2020
9cec773
Update types/matches.d.ts
benmonro May 29, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
256 changes: 256 additions & 0 deletions src/__tests__/suggestions.js
@@ -0,0 +1,256 @@
import {configure} from '../config'
import {screen} from '..'
import {renderIntoDocument} from './helpers/test-utils'

beforeAll(() => {
configure({throwSuggestions: true})
})

afterAll(() => {
configure({throwSuggestions: false})
})

test('does not suggest when using getByRole', () => {
renderIntoDocument(`<button data-testid="foo">submit</button>`)

expect(() => screen.getByRole('button', {name: /submit/i})).not.toThrowError()
})

test('should not suggest when nothing available', () => {
renderIntoDocument(`<span data-testid="foo" />`)

expect(() => screen.queryByTestId('foo')).not.toThrowError()
})

test(`should not suggest if the suggestion would give different results`, () => {
renderIntoDocument(`
<input type="text" data-testid="foo" /><span data-testid="foo" />
`)

expect(() =>
screen.getAllByTestId('foo', {suggest: false}),
).not.toThrowError()
})

test('should not suggest if there would be mixed suggestions', () => {
renderIntoDocument(`
<button data-testid="foo">submit</button>
<label for="foo">Username</label><input data-testid="foo" id="foo" />`)

expect(() => screen.getAllByTestId('foo')).not.toThrowError()
})

test('should not suggest when suggest is turned off for a query', () => {
renderIntoDocument(`
<button data-testid="foo">submit</button>
<button data-testid="foot">another</button>`)

expect(() => screen.getByTestId('foo', {suggest: false})).not.toThrowError()
expect(() =>
screen.getAllByTestId(/foo/, {suggest: false}),
).not.toThrowError()
})

test('should suggest getByRole when used with getBy', () => {
renderIntoDocument(`<button data-testid="foo">submit</button>`)

expect(() => screen.getByTestId('foo')).toThrowErrorMatchingInlineSnapshot(`
"A better query is available, try this:
getByRole("button", {name: /submit/i})


<body>
<button
data-testid="foo"
>
submit
</button>
</body>"
`)
})

test('should suggest getAllByRole when used with getAllByTestId', () => {
renderIntoDocument(`
<button data-testid="foo">submit</button>
<button data-testid="foo">submit</button>`)

expect(() => screen.getAllByTestId('foo'))
.toThrowErrorMatchingInlineSnapshot(`
"A better query is available, try this:
getAllByRole("button", {name: /submit/i})


<body>


<button
data-testid="foo"
>
submit
</button>


<button
data-testid="foo"
>
submit
</button>
</body>"
`)
})
test('should suggest findByRole when used with findByTestId', async () => {
renderIntoDocument(`
<button data-testid="foo">submit</button>
<button data-testid="foot">submit</button>
`)

await expect(screen.findByTestId('foo')).rejects.toThrowError(
/findByRole\("button", \{name: \/submit\/i\}\)/,
)
await expect(screen.findAllByTestId(/foo/)).rejects.toThrowError(
/findAllByRole\("button", \{name: \/submit\/i\}\)/,
)
})

test('should suggest img role w/ alt text', () => {
renderIntoDocument(`<img data-testid="img" alt="Incredibles 2 Poster" />`)

expect(() => screen.getByAltText('Incredibles 2 Poster')).toThrowError(
/getByRole\("img", \{name: \/incredibles 2 poster\/i\}\)/,
)
})

test('should suggest getByLabelText when no role available', () => {
renderIntoDocument(
`<label for="foo">Username</label><input data-testid="foo" id="foo" />`,
)
expect(() => screen.getByTestId('foo')).toThrowError(
/getByLabelText\("Username"\)/,
)
})

test(`should suggest getByLabel on non form elements`, () => {
renderIntoDocument(`
<div data-testid="foo" aria-labelledby="section-one-header">
<span id="section-one-header">Section One</span>
<p>some content</p>
</div>
`)

expect(() => screen.getByTestId('foo')).toThrowError(
/getByLabelText\("Section One"\)/,
)
})

test.each([
`<label id="username-label">Username</label><input aria-labelledby="username-label" type="text" />`,
`<label><span>Username</span><input type="text" /></label>`,
`<label for="foo">Username</label><input id="foo" type="text" />`,
])('%s\nshould suggest getByRole over', async html => {
renderIntoDocument(html)

expect(() => screen.getByLabelText('Username')).toThrowError(
/getByRole\("textbox", \{name: \/username\/i\}\)/,
)
expect(() => screen.getAllByLabelText('Username')).toThrowError(
/getAllByRole\("textbox", \{name: \/username\/i\}\)/,
)

expect(() => screen.queryByLabelText('Username')).toThrowError(
/queryByRole\("textbox", \{name: \/username\/i\}\)/,
)
expect(() => screen.queryAllByLabelText('Username')).toThrowError(
/queryAllByRole\("textbox", \{name: \/username\/i\}\)/,
)

await expect(screen.findByLabelText('Username')).rejects.toThrowError(
/findByRole\("textbox", \{name: \/username\/i\}\)/,
)
await expect(screen.findAllByLabelText(/Username/)).rejects.toThrowError(
/findAllByRole\("textbox", \{name: \/username\/i\}\)/,
)
})

test(`should suggest label over placeholder text`, () => {
renderIntoDocument(
`<label for="foo">Username</label><input id="foo" data-testid="foo" placeholder="Username" />`,
)

expect(() => screen.getByPlaceholderText('Username')).toThrowError(
/getByLabelText\("Username"\)/,
)
})

test(`should suggest getByPlaceholderText`, () => {
renderIntoDocument(`<input data-testid="foo" placeholder="Username" />`)

expect(() => screen.getByTestId('foo')).toThrowError(
/getByPlaceholderText\("Username"\)/,
)
})

test(`should suggest getByText for simple elements`, () => {
renderIntoDocument(`<div data-testid="foo">hello there</div>`)

expect(() => screen.getByTestId('foo')).toThrowError(
/getByText\("hello there"\)/,
)
})

test(`should suggest getByDisplayValue`, () => {
renderIntoDocument(`<input id="lastName" data-testid="lastName" />`)

document.getElementById('lastName').value = 'Prine' // RIP John Prine

expect(() => screen.getByTestId('lastName')).toThrowError(
/getByDisplayValue\("Prine"\)/,
)
})

test(`should suggest getByAltText`, () => {
renderIntoDocument(`
<input data-testid="input" alt="last name" />
<map name="workmap">
<area data-testid="area" shape="rect" coords="34,44,270,350" alt="Computer">
</map>
`)

expect(() => screen.getByTestId('input')).toThrowError(
/getByAltText\("last name"\)/,
)
expect(() => screen.getByTestId('area')).toThrowError(
/getByAltText\("Computer"\)/,
)
})

test(`should suggest getByTitle`, () => {
renderIntoDocument(`
<span title="Delete" data-testid="delete"></span>
<svg>
<title data-testid="svg">Close</title>
<g><path /></g>
</svg>`)

expect(() => screen.getByTestId('delete')).toThrowError(
/getByTitle\("Delete"\)/,
)
expect(() => screen.getAllByTestId('delete')).toThrowError(
/getAllByTitle\("Delete"\)/,
)
expect(() => screen.queryByTestId('delete')).toThrowError(
/queryByTitle\("Delete"\)/,
)
expect(() => screen.queryAllByTestId('delete')).toThrowError(
/queryAllByTitle\("Delete"\)/,
)
expect(() => screen.queryAllByTestId('delete')).toThrowError(
/queryAllByTitle\("Delete"\)/,
)
expect(() => screen.queryAllByTestId('delete')).toThrowError(
/queryAllByTitle\("Delete"\)/,
)

// Since `ByTitle` and `ByText` will both return the <title> element
// `getByText` will always be the suggested query as it is higher up the list.
expect(() => screen.getByTestId('svg')).toThrowError(/getByText\("Close"\)/)
})
5 changes: 4 additions & 1 deletion src/config.js
Expand Up @@ -16,9 +16,12 @@ let config = {
asyncWrapper: cb => cb(),
// default value for the `hidden` option in `ByRole` queries
defaultHidden: false,
//showOriginalStackTrace flag to show the full error stack traces for async errors
// showOriginalStackTrace flag to show the full error stack traces for async errors
showOriginalStackTrace: false,

// throw errors w/ suggestions for better queries. Opt in so off by default.
throwSuggestions: false,

// called when getBy* queries fail. (message, container) => Error
getElementError(message, container) {
const error = new Error(
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Expand Up @@ -16,6 +16,7 @@ export * from './query-helpers'
export {getRoles, logRoles, isInaccessible} from './role-helpers'
export * from './pretty-dom'
export {configure} from './config'
export * from './suggestions'

export {
// "within" reads better in user-code
Expand Down
9 changes: 8 additions & 1 deletion src/queries/alt-text.js
@@ -1,4 +1,5 @@
import {matches, fuzzyMatches, makeNormalizer, buildQueries} from './all-utils'
import {wrapAllByQueryWithSuggestion} from '../query-helpers'

function queryAllByAltText(
container,
Expand All @@ -16,6 +17,12 @@ const getMultipleError = (c, alt) =>
`Found multiple elements with the alt text: ${alt}`
const getMissingError = (c, alt) =>
`Unable to find an element with the alt text: ${alt}`

const queryAllByAltTextWithSuggestions = wrapAllByQueryWithSuggestion(
queryAllByAltText,
queryAllByAltText.name,
'queryAll',
)
const [
queryByAltText,
getAllByAltText,
Expand All @@ -26,7 +33,7 @@ const [

export {
queryByAltText,
queryAllByAltText,
queryAllByAltTextWithSuggestions as queryAllByAltText,
getByAltText,
getAllByAltText,
findAllByAltText,
Expand Down
10 changes: 9 additions & 1 deletion src/queries/display-value.js
Expand Up @@ -5,6 +5,7 @@ import {
makeNormalizer,
buildQueries,
} from './all-utils'
import {wrapAllByQueryWithSuggestion} from '../query-helpers'

function queryAllByDisplayValue(
container,
Expand Down Expand Up @@ -33,6 +34,13 @@ const getMultipleError = (c, value) =>
`Found multiple elements with the display value: ${value}.`
const getMissingError = (c, value) =>
`Unable to find an element with the display value: ${value}.`

const queryAllByDisplayValueWithSuggestions = wrapAllByQueryWithSuggestion(
queryAllByDisplayValue,
queryAllByDisplayValue.name,
'queryAll',
)

const [
queryByDisplayValue,
getAllByDisplayValue,
Expand All @@ -43,7 +51,7 @@ const [

export {
queryByDisplayValue,
queryAllByDisplayValue,
queryAllByDisplayValueWithSuggestions as queryAllByDisplayValue,
getByDisplayValue,
getAllByDisplayValue,
findAllByDisplayValue,
Expand Down