diff --git a/src/__tests__/to-have-value.js b/src/__tests__/to-have-value.js index 80cc7828..bc8e6493 100644 --- a/src/__tests__/to-have-value.js +++ b/src/__tests__/to-have-value.js @@ -203,4 +203,14 @@ Received: foo `) }) + + test('handles value of aria-valuenow', () => { + const valueToCheck = 70 + const {queryByTestId} = render(` +
+ `) + + expect(queryByTestId('meter')).toHaveValue(valueToCheck) + expect(queryByTestId('meter')).not.toHaveValue(valueToCheck + 1) + }) }) diff --git a/src/utils.js b/src/utils.js index cdbb1088..900fca14 100644 --- a/src/utils.js +++ b/src/utils.js @@ -197,18 +197,31 @@ function getInputValue(inputElement) { } } +const rolesSupportingValues = ['meter', 'progressbar', 'slider', 'spinbutton'] +function getAccessibleValue(element) { + if (!rolesSupportingValues.includes(element.getAttribute('role'))) { + return + } + // We want same behavior as accessing the `value` property + // eslint-disable-next-line consistent-return + return Number(element.getAttribute('aria-valuenow')) +} + function getSingleElementValue(element) { /* istanbul ignore if */ if (!element) { return undefined } + switch (element.tagName.toLowerCase()) { case 'input': return getInputValue(element) case 'select': return getSelectValue(element) - default: - return element.value + default: { + const accessibleValue = getAccessibleValue(element) + return element.value ?? accessibleValue + } } }