diff --git a/lib/checks/aria/aria-prohibited-attr-evaluate.js b/lib/checks/aria/aria-prohibited-attr-evaluate.js index ff843065fd..c4e7085761 100644 --- a/lib/checks/aria/aria-prohibited-attr-evaluate.js +++ b/lib/checks/aria/aria-prohibited-attr-evaluate.js @@ -26,14 +26,12 @@ import standards from '../../standards'; * @memberof checks * @return {Boolean} True if the element uses any prohibited ARIA attributes. False otherwise. */ -function ariaProhibitedAttrEvaluate(node, options = {}, virtualNode) { - const extraElementsAllowedAriaLabel = options.elementsAllowedAriaLabel || []; - - const prohibitedList = listProhibitedAttrs( - virtualNode, - extraElementsAllowedAriaLabel - ); +export default function ariaProhibitedAttrEvaluate(node, options = {}, virtualNode) { + const elementsAllowedAriaLabel = options?.elementsAllowedAriaLabel || []; + const { nodeName } = virtualNode.props; + const role = getRole(virtualNode, { chromium: true }); + const prohibitedList = listProhibitedAttrs(role, nodeName, elementsAllowedAriaLabel); const prohibited = prohibitedList.filter(attrName => { if (!virtualNode.attrNames.includes(attrName)) { return false; @@ -45,24 +43,26 @@ function ariaProhibitedAttrEvaluate(node, options = {}, virtualNode) { return false; } - this.data(prohibited); - const hasTextContent = sanitize(subtreeText(virtualNode)) !== ''; - // Don't fail if there is text content to announce - return hasTextContent ? undefined : true; + let messageKey = virtualNode.hasAttr('role') ? 'hasRole' : 'noRole'; + messageKey += prohibited.length > 1 ? 'Plural' : 'Singular'; + this.data({ role, nodeName, messageKey, prohibited }); + + // `subtreeDescendant` to override namedFromContents + const textContent = subtreeText(virtualNode, { subtreeDescendant: true }); + if (sanitize(textContent) !== '') { + // Don't fail if there is text content to announce + return undefined; + } + return true; } -function listProhibitedAttrs(virtualNode, elementsAllowedAriaLabel) { - const role = getRole(virtualNode, { chromium: true }); +function listProhibitedAttrs(role, nodeName, elementsAllowedAriaLabel) { const roleSpec = standards.ariaRoles[role]; if (roleSpec) { return roleSpec.prohibitedAttrs || []; } - - const { nodeName } = virtualNode.props; if (!!role || elementsAllowedAriaLabel.includes(nodeName)) { return []; } return ['aria-label', 'aria-labelledby']; } - -export default ariaProhibitedAttrEvaluate; diff --git a/lib/checks/aria/aria-prohibited-attr.json b/lib/checks/aria/aria-prohibited-attr.json index fd2f3e72bc..21e8a007f9 100644 --- a/lib/checks/aria/aria-prohibited-attr.json +++ b/lib/checks/aria/aria-prohibited-attr.json @@ -8,8 +8,18 @@ "impact": "serious", "messages": { "pass": "ARIA attribute is allowed", - "fail": "ARIA attribute: ${data.values} is not allowed. Use a different role attribute or element.", - "incomplete": "ARIA attribute: ${data.values} is not well supported. Use a different role attribute or element." + "fail": { + "hasRolePlural": "${data.prohibited} attributes cannot be used with role \"${data.role}\".", + "hasRoleSingular": "${data.prohibited} attribute cannot be used with role \"${data.role}\".", + "noRolePlural": "${data.prohibited} attributes cannot be used on a ${data.nodeName} with no valid role attribute.", + "noRoleSingular": "${data.prohibited} attribute cannot be used on a ${data.nodeName} with no valid role attribute." + }, + "incomplete": { + "hasRoleSingular": "${data.prohibited} attribute is not well supported with role \"${data.role}\".", + "hasRolePlural": "${data.prohibited} attributes are not well supported with role \"${data.role}\".", + "noRoleSingular": "${data.prohibited} attribute is not well supported on a ${data.nodeName} with no valid role attribute.", + "noRolePlural": "${data.prohibited} attributes are not well supported on a ${data.nodeName} with no valid role attribute." + } } } } diff --git a/test/checks/aria/aria-prohibited-attr.js b/test/checks/aria/aria-prohibited-attr.js index 4900b6e3f5..6e7a492b74 100644 --- a/test/checks/aria/aria-prohibited-attr.js +++ b/test/checks/aria/aria-prohibited-attr.js @@ -9,25 +9,47 @@ describe('aria-prohibited-attr', function() { checkContext.reset(); }); - it('should return true for prohibited attributes', function() { + it('should return true for prohibited attributes and no content', function() { var params = checkSetup( - '