Skip to content

Commit

Permalink
fix(ByLabelText): support IE and other legacy browsers (#726)
Browse files Browse the repository at this point in the history
* fix(ByLabelText): support IE

Polyfill HTMLInputElement.labels to support IE and other legacy browsers. Closes #723.

* fix: ensure mocks are restored

* test: remove unnecessary test cases

Co-authored-by: Maxwell Newlands <maxwelln@spotify.com>
  • Loading branch information
maxnewlands and maxnewlands committed Aug 5, 2020
1 parent 54aebf7 commit f83f8e9
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 5 deletions.
16 changes: 16 additions & 0 deletions src/__tests__/element-queries.js
Expand Up @@ -1182,3 +1182,19 @@ test('return a proper error message when no label is found and there is an aria-
</div>"
`)
})

// https://github.com/testing-library/dom-testing-library/issues/723
it('gets form controls by label text on IE and other legacy browsers', () => {
// Simulate lack of support for HTMLInputElement.prototype.labels
jest
.spyOn(HTMLInputElement.prototype, 'labels', 'get')
.mockReturnValue(undefined)

const {getByLabelText} = renderIntoDocument(`
<label>
Label text
<input id="input-id" />
</label>
`)
expect(getByLabelText('Label text').id).toBe('input-id')
})
25 changes: 21 additions & 4 deletions src/queries/label-text.js
Expand Up @@ -72,9 +72,9 @@ function queryAllByLabelText(
const matcher = exact ? matches : fuzzyMatches
const matchNormalizer = makeNormalizer({collapseWhitespace, trim, normalizer})
const matchingLabelledElements = Array.from(container.querySelectorAll('*'))
.filter(
element => element.labels || element.hasAttribute('aria-labelledby'),
)
.filter(element => {
return getLabels(element) || element.hasAttribute('aria-labelledby')
})
.reduce((labelledElements, labelledElement) => {
const labelsId = labelledElement.getAttribute('aria-labelledby')
? labelledElement.getAttribute('aria-labelledby').split(' ')
Expand All @@ -86,7 +86,7 @@ function queryAllByLabelText(
)
return labellingElement ? getLabelContent(labellingElement) : ''
})
: Array.from(labelledElement.labels).map(label => {
: Array.from(getLabels(labelledElement)).map(label => {
const textToMatch = getLabelContent(label)
const formControlSelector =
'button, input, meter, output, progress, select, textarea'
Expand Down Expand Up @@ -235,3 +235,20 @@ export {
findAllByLabelText,
findByLabelText,
}

// Based on https://github.com/eps1lon/dom-accessibility-api/pull/352
function getLabels(element) {
if (element.labels !== undefined) return element.labels

if (!isLabelable(element)) return null

const labels = element.ownerDocument.querySelectorAll('label')
return Array.from(labels).filter(label => label.control === element)
}

function isLabelable(element) {
return (
element.tagName.match(/BUTTON|METER|OUTPUT|PROGRESS|SELECT|TEXTAREA/) ||
(element.tagName === 'INPUT' && element.getAttribute('type') !== 'hidden')
)
}
2 changes: 1 addition & 1 deletion tests/setup-env.js
Expand Up @@ -37,5 +37,5 @@ beforeAll(() => {
})

afterAll(() => {
console.warn.mockRestore()
jest.restoreAllMocks()
})

0 comments on commit f83f8e9

Please sign in to comment.