Skip to content

Commit 402288f

Browse files
airjp73Aaron Pettengill
and
Aaron Pettengill
authored
fix: Only return first child element in label query (#520)
* fix: Only return first child element in label query * fix: Link to spec and correct terminology Co-authored-by: Aaron Pettengill <aaron.pettengill@echoman.com>
1 parent 672f231 commit 402288f

File tree

2 files changed

+39
-6
lines changed

2 files changed

+39
-6
lines changed

src/__tests__/element-queries.js

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,8 @@ test('can filter results of label query based on selector', () => {
229229
expect(result[0].id).toBe('input1')
230230
})
231231

232-
test('can find any form control when label text is inside other elements', () => {
233-
const {getAllByLabelText} = render(`
232+
test('can find any labelable element when label text is inside other elements', () => {
233+
const {getByLabelText} = render(`
234234
<label>
235235
<span>Test</span>
236236
<span>Label</span>
@@ -244,8 +244,40 @@ test('can find any form control when label text is inside other elements', () =>
244244
</label>
245245
`)
246246

247-
const result = getAllByLabelText('Test Label')
248-
expect(result).toHaveLength(7)
247+
const nodeTypes = [
248+
'button',
249+
'input',
250+
'meter',
251+
'output',
252+
'progress',
253+
'select',
254+
'textarea',
255+
]
256+
nodeTypes.forEach(nodeType => {
257+
expect(getByLabelText('Test Label', {selector: nodeType}).nodeName).toEqual(
258+
nodeType.toUpperCase(),
259+
)
260+
})
261+
})
262+
263+
// According to the spec, the first descendant of a label that is a labelable element is the labeled control
264+
// https://html.spec.whatwg.org/multipage/forms.html#the-label-element
265+
test('returns the labelable element control inside a label', () => {
266+
const {getByLabelText} = render(`
267+
<label>
268+
<span>Test</span>
269+
<span>Label</span>
270+
<button />
271+
<input />
272+
<meter />
273+
<output />
274+
<progress />
275+
<select />
276+
<textarea />
277+
</label>
278+
`)
279+
280+
expect(getByLabelText('Test Label').nodeName).toEqual('BUTTON')
249281
})
250282

251283
test('can find non-input elements when aria-labelledby a label', () => {

src/queries/label-text.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,10 @@ function queryAllByLabelText(
7474
// <label>text: <input /></label>
7575
const formControlSelector =
7676
'button, input, meter, output, progress, select, textarea'
77-
Array.from(
77+
const labelledFormControl = Array.from(
7878
label.querySelectorAll(formControlSelector),
79-
).forEach(element => elementsForLabel.push(element))
79+
).filter(element => element.matches(selector))[0]
80+
if (labelledFormControl) elementsForLabel.push(labelledFormControl)
8081
}
8182
return matchedElements.concat(elementsForLabel)
8283
}, [])

0 commit comments

Comments
 (0)