Skip to content

Commit d6d41f9

Browse files
authored
feat(config): add getElementError config option (#452)
closes #360
1 parent cf57dcd commit d6d41f9

File tree

5 files changed

+43
-11
lines changed

5 files changed

+43
-11
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`getByLabelText query will throw the custom error returned by config.getElementError 1`] = `"My custom error: Unable to find a label with the text of: TEST QUERY"`;
4+
5+
exports[`getByText query will throw the custom error returned by config.getElementError 1`] = `"My custom error: Unable to find an element with the text: TEST QUERY. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible."`;

src/__tests__/get-by-errors.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import cases from 'jest-in-case'
2+
import {screen} from '../'
3+
import {configure, getConfig} from '../config'
24
import {render} from './helpers/test-utils'
35

6+
const originalConfig = getConfig()
7+
beforeEach(() => {
8+
configure(originalConfig)
9+
})
10+
411
cases(
512
'getBy* queries throw an error when there are multiple elements returned',
613
({name, query, html}) => {
@@ -39,6 +46,19 @@ cases(
3946
},
4047
)
4148

49+
test.each([['getByText'], ['getByLabelText']])(
50+
'%s query will throw the custom error returned by config.getElementError',
51+
query => {
52+
const getElementError = jest.fn(
53+
(message, _container) => new Error(`My custom error: ${message}`),
54+
)
55+
configure({getElementError})
56+
document.body.innerHTML = '<div>Hello</div>'
57+
expect(() => screen[query]('TEST QUERY')).toThrowErrorMatchingSnapshot()
58+
expect(getElementError).toBeCalledTimes(1)
59+
},
60+
)
61+
4262
cases(
4363
'queryBy* queries throw an error when there are multiple elements returned',
4464
({name, query, html}) => {

src/config.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import {prettyDOM} from './pretty-dom'
2+
13
// It would be cleaner for this to live inside './queries', but
24
// other parts of the code assume that all exports from
35
// './queries' are query functions.
@@ -14,6 +16,13 @@ let config = {
1416
asyncWrapper: cb => cb(),
1517
// default value for the `hidden` option in `ByRole` queries
1618
defaultHidden: false,
19+
20+
// called when getBy* queries fail. (message, container) => Error
21+
getElementError(message, container) {
22+
return new Error(
23+
[message, prettyDOM(container)].filter(Boolean).join('\n\n'),
24+
)
25+
},
1726
}
1827

1928
export function configure(newConfig) {

src/queries/label-text.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
import {getConfig} from '../config'
12
import {
23
fuzzyMatches,
34
matches,
45
makeNormalizer,
5-
getElementError,
66
queryAllByAttribute,
77
makeFindQuery,
88
makeSingleQuery,
@@ -104,12 +104,12 @@ function getAllByLabelText(container, text, ...rest) {
104104
if (!els.length) {
105105
const labels = queryAllLabelsByText(container, text, ...rest)
106106
if (labels.length) {
107-
throw getElementError(
107+
throw getConfig().getElementError(
108108
`Found a label with the text of: ${text}, however no form control was found associated to that label. Make sure you're using the "for" attribute or "aria-labelledby" attribute correctly.`,
109109
container,
110110
)
111111
} else {
112-
throw getElementError(
112+
throw getConfig().getElementError(
113113
`Unable to find a label with the text of: ${text}`,
114114
container,
115115
)

src/query-helpers.js

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
import {prettyDOM} from './pretty-dom'
21
import {fuzzyMatches, matches, makeNormalizer} from './matches'
32
import {waitForElement} from './wait-for-element'
4-
5-
function getElementError(message, container) {
6-
return new Error([message, prettyDOM(container)].filter(Boolean).join('\n\n'))
7-
}
3+
import {getConfig} from './config'
84

95
function getMultipleElementsFoundError(message, container) {
10-
return getElementError(
6+
return getConfig().getElementError(
117
`${message}\n\n(If this is intentional, then use the \`*AllBy*\` variant of the query (like \`queryAllByText\`, \`getAllByText\`, or \`findAllByText\`)).`,
128
container,
139
)
@@ -59,7 +55,10 @@ function makeGetAllQuery(allQuery, getMissingError) {
5955
return (container, ...args) => {
6056
const els = allQuery(container, ...args)
6157
if (!els.length) {
62-
throw getElementError(getMissingError(container, ...args), container)
58+
throw getConfig().getElementError(
59+
getMissingError(container, ...args),
60+
container,
61+
)
6362
}
6463
return els
6564
}
@@ -86,7 +85,6 @@ function buildQueries(queryAllBy, getMultipleError, getMissingError) {
8685
}
8786

8887
export {
89-
getElementError,
9088
getMultipleElementsFoundError,
9189
queryAllByAttribute,
9290
queryByAttribute,

0 commit comments

Comments
 (0)