Skip to content

Commit

Permalink
fix(aria-required-children): trigger reviewEmpty with hidden children (
Browse files Browse the repository at this point in the history
…#4012)

* fix(aria-required-children): trigger reviewEmpty with hidden children

* 🤖 Automated formatting fixes

* Fix code block
  • Loading branch information
WilcoFiers authored May 12, 2023
1 parent 704043e commit a19b6cb
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 233 deletions.
30 changes: 19 additions & 11 deletions lib/checks/aria/aria-required-children-evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
import { getGlobalAriaAttrs } from '../../commons/standards';
import {
hasContentVirtual,
idrefs,
isFocusable,
isVisibleToScreenReaders
} from '../../commons/dom';
Expand Down Expand Up @@ -35,7 +34,7 @@ export default function ariaRequiredChildrenEvaluate(
return true;
}

const ownedRoles = getOwnedRoles(virtualNode, required);
const { ownedRoles, ownedElements } = getOwnedRoles(virtualNode, required);
const unallowed = ownedRoles.filter(({ role }) => !required.includes(role));

if (unallowed.length) {
Expand Down Expand Up @@ -65,12 +64,7 @@ export default function ariaRequiredChildrenEvaluate(
this.data(missing);

// Only review empty nodes when a node is both empty and does not have an aria-owns relationship
if (
reviewEmpty.includes(role) &&
!hasContentVirtual(virtualNode, false, true) &&
!ownedRoles.length &&
(!virtualNode.hasAttr('aria-owns') || !idrefs(node, 'aria-owns').length)
) {
if (reviewEmpty.includes(role) && !ownedElements.some(isContent)) {
return undefined;
}

Expand All @@ -82,7 +76,10 @@ export default function ariaRequiredChildrenEvaluate(
*/
function getOwnedRoles(virtualNode, required) {
const ownedRoles = [];
const ownedElements = getOwnedVirtual(virtualNode);
const ownedElements = getOwnedVirtual(virtualNode).filter(vNode => {
return vNode.props.nodeType !== 1 || isVisibleToScreenReaders(vNode);
});

for (let i = 0; i < ownedElements.length; i++) {
const ownedElement = ownedElements[i];
if (ownedElement.props.nodeType !== 1) {
Expand All @@ -100,7 +97,6 @@ function getOwnedRoles(virtualNode, required) {
// this means intermediate roles between a required parent and
// child will fail the check
if (
!isVisibleToScreenReaders(ownedElement) ||
(!role && !hasGlobalAriaOrFocusable) ||
(['group', 'rowgroup'].includes(role) &&
required.some(requiredRole => requiredRole === role))
Expand All @@ -115,7 +111,7 @@ function getOwnedRoles(virtualNode, required) {
}
}

return ownedRoles;
return { ownedRoles, ownedElements };
}

/**
Expand Down Expand Up @@ -171,3 +167,15 @@ function getUnallowedSelector(vNode, attr) {

return nodeName;
}

/**
* Check if the node has content, or is itself content
* @param {VirtualNode} vNode
* @returns {Boolean}
*/
function isContent(vNode) {
if (vNode.props.nodeType === 3) {
return vNode.props.nodeValue.trim().length > 0;
}
return hasContentVirtual(vNode, false, true);
}
14 changes: 12 additions & 2 deletions lib/standards/aria-roles.js
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,12 @@ const ariaRoles = {
type: 'widget',
requiredContext: ['menu', 'menubar', 'group'],
requiredAttrs: ['aria-checked'],
allowedAttrs: ['aria-expanded', 'aria-posinset', 'aria-readonly', 'aria-setsize'],
allowedAttrs: [
'aria-expanded',
'aria-posinset',
'aria-readonly',
'aria-setsize'
],
superclassRole: ['checkbox', 'menuitem'],
accessibleNameRequired: true,
nameFromContent: true,
Expand All @@ -388,7 +393,12 @@ const ariaRoles = {
type: 'widget',
requiredContext: ['menu', 'menubar', 'group'],
requiredAttrs: ['aria-checked'],
allowedAttrs: ['aria-expanded', 'aria-posinset', 'aria-readonly', 'aria-setsize'],
allowedAttrs: [
'aria-expanded',
'aria-posinset',
'aria-readonly',
'aria-setsize'
],
superclassRole: ['menuitemcheckbox', 'radio'],
accessibleNameRequired: true,
nameFromContent: true,
Expand Down
Loading

0 comments on commit a19b6cb

Please sign in to comment.