diff --git a/lib/commons/aria/ariadescribedby-text.js b/lib/commons/aria/ariadescribedby-text.js new file mode 100644 index 000000000..d81252d5a --- /dev/null +++ b/lib/commons/aria/ariadescribedby-text.js @@ -0,0 +1,46 @@ +/** + * Get the accessible name based on aria-describedby + * + * @deprecated Do not use Element directly. Pass VirtualNode instead + * @param {VirtualNode|Element} element + * @param {Object} context + * @property {Bool} inLabelledByContext Whether or not the lookup is part of aria-describedby reference + * @property {Bool} inControlContext Whether or not the lookup is part of a native label reference + * @property {Element} startNode First node in accessible name computation + * @property {Bool} debug Enable logging for formControlValue + * @return {string} Concatenated text value for referenced elements + */ +function ariadescribedbyText(element, context = {}) { + const { vNode } = axe.utils.nodeLookup(element); + if (vNode?.props.nodeType !== 1) { + return ''; + } + + if ( + vNode.props.nodeType !== 1 || + context.inLabelledByContext || + context.inControlContext || + !vNode.attr('aria-describedby') + ) { + return ''; + } + + const refs = axe.commons.dom + .idrefs(vNode, 'aria-describedby') + .filter(elm => elm); + return refs.reduce((accessibleName, elm) => { + const accessibleNameAdd = axe.commons.text.accessibleText(elm, { + // Prevent the infinite reference loop: + inLabelledByContext: true, + startNode: context.startNode || vNode, + ...context + }); + + if (!accessibleName) { + return accessibleNameAdd; + } + return `${accessibleName} ${accessibleNameAdd}`; + }, ''); +} + +export default ariadescribedbyText; diff --git a/lib/commons/aria/index.js b/lib/commons/aria/index.js index 9eb5bb3a8..86d310ee8 100644 --- a/lib/commons/aria/index.js +++ b/lib/commons/aria/index.js @@ -6,6 +6,7 @@ export { default as allowedAttr } from './allowed-attr'; export { default as arialabelText } from './arialabel-text'; export { default as arialabelledbyText } from './arialabelledby-text'; +export { default as ariadescribedbyText } from './ariadescribedby-text'; export { default as getAccessibleRefs } from './get-accessible-refs'; export { default as getElementUnallowedRoles } from './get-element-unallowed-roles'; export { default as getExplicitRole } from './get-explicit-role';