Skip to content

Commit 7f8c100

Browse files
Kent C. DoddsKent C. Dodds
Kent C. Dodds
authored and
Kent C. Dodds
committed
fix(getBy*): throw an error if more than one element is found (#229)
Closes #202 BREAKING CHANGE: All `getBy` and `findBy` query variants now will throw an error if more than one element is returned. If this is expected, then use `getAllBy` (or `findAllBy`) instead.
1 parent 253d677 commit 7f8c100

16 files changed

+567
-407
lines changed

src/__tests__/element-queries.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ test('get throws a useful error message', () => {
8686
</div>"
8787
`)
8888
expect(() => getByRole('LucyRicardo')).toThrowErrorMatchingInlineSnapshot(`
89-
"Unable to find an element by role=LucyRicardo
89+
"Unable to find an element by [role=LucyRicardo]
9090
9191
<div>
9292
<div />

src/__tests__/get-by-errors.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import cases from 'jest-in-case'
2+
import {render} from './helpers/test-utils'
3+
4+
cases(
5+
'getBy* queries throw an error when there are multiple elements returned',
6+
({name, query, html}) => {
7+
const utils = render(html)
8+
expect(() => utils[name](query)).toThrow(/multiple elements/i)
9+
},
10+
{
11+
getByLabelText: {
12+
query: /his/,
13+
html: `<div aria-label="his"></div><div aria-label="history"></div>`,
14+
},
15+
getByPlaceholderText: {
16+
query: /his/,
17+
html: `<input placeholder="his" /><input placeholder="history" />`,
18+
},
19+
getByText: {
20+
query: /his/,
21+
html: `<div>his</div><div>history</div>`,
22+
},
23+
getByAltText: {
24+
query: /his/,
25+
html: `<img alt="his" src="his.png" /><img alt="history" src="history.png" />`,
26+
},
27+
getByTitle: {
28+
query: /his/,
29+
html: `<div title="his"></div><div title="history"></div>`,
30+
},
31+
getByDisplayValue: {
32+
query: /his/,
33+
html: `<input value="his" /><select><option value="history">history</option></select>`,
34+
},
35+
getByRole: {
36+
query: /his/,
37+
html: `<div role="his"></div><div role="history"></div>`,
38+
},
39+
getByTestId: {
40+
query: /his/,
41+
html: `<div data-testid="his"></div><div data-testid="history"></div>`,
42+
},
43+
},
44+
)
45+
46+
cases(
47+
'queryBy* queries throw an error when there are multiple elements returned',
48+
({name, query, html}) => {
49+
const utils = render(html)
50+
expect(() => utils[name](query)).toThrow(/multiple elements/i)
51+
},
52+
{
53+
queryByLabelText: {
54+
query: /his/,
55+
html: `<div aria-label="his"></div><div aria-label="history"></div>`,
56+
},
57+
queryByPlaceholderText: {
58+
query: /his/,
59+
html: `<input placeholder="his" /><input placeholder="history" />`,
60+
},
61+
queryByText: {
62+
query: /his/,
63+
html: `<div>his</div><div>history</div>`,
64+
},
65+
queryByAltText: {
66+
query: /his/,
67+
html: `<img alt="his" src="his.png" /><img alt="history" src="history.png" />`,
68+
},
69+
queryByTitle: {
70+
query: /his/,
71+
html: `<div title="his"></div><div title="history"></div>`,
72+
},
73+
queryByDisplayValue: {
74+
query: /his/,
75+
html: `<input value="his" /><select><option value="history">history</option></select>`,
76+
},
77+
queryByRole: {
78+
query: /his/,
79+
html: `<div role="his"></div><div role="history"></div>`,
80+
},
81+
queryByTestId: {
82+
query: /his/,
83+
html: `<div data-testid="his"></div><div data-testid="history"></div>`,
84+
},
85+
},
86+
)

src/__tests__/misc.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {render} from './helpers/test-utils'
2+
import {queryByAttribute} from '..'
3+
4+
// we used to use queryByAttribute internally, but we don't anymore. Some people
5+
// use it as an undocumented part of the API, so we'll keep it around.
6+
test('queryByAttribute', () => {
7+
const {container} = render(
8+
'<div data-foo="bar"></div><div data-foo="rubar"></div>',
9+
)
10+
expect(queryByAttribute('data-foo', container, 'bar')).not.toBeNull()
11+
expect(queryByAttribute('blah', container, 'sup')).toBeNull()
12+
expect(() => queryByAttribute('data-foo', container, /bar/)).toThrow(
13+
/multiple/,
14+
)
15+
})

0 commit comments

Comments
 (0)