From bcf6150e2e8b57f2d17fe83edf840dfc4521e5c5 Mon Sep 17 00:00:00 2001 From: AdnoC Date: Wed, 18 Dec 2019 14:40:03 -0500 Subject: [PATCH] fix(aria-required-children): allow comboboxes with more popup roles --- lib/checks/aria/required-children.js | 22 +++++++++++++++++----- lib/commons/aria/index.js | 2 +- test/checks/aria/required-children.js | 20 ++++++++++++++++++++ 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/lib/checks/aria/required-children.js b/lib/checks/aria/required-children.js index 2151908d6e..18f137a430 100644 --- a/lib/checks/aria/required-children.js +++ b/lib/checks/aria/required-children.js @@ -78,11 +78,23 @@ function missingRequiredChildren(node, childRoles, all, role) { missing.splice(textboxIndex, 1); } - // remove 'listbox' from missing roles if combobox is collapsed - var listboxIndex = missing.indexOf('listbox'); - var expanded = node.getAttribute('aria-expanded'); - if (listboxIndex >= 0 && (!expanded || expanded === 'false')) { - missing.splice(listboxIndex, 1); + const expandedChildRoles = ['listbox', 'tree', 'grid', 'dialog']; + const expandedValue = node.getAttribute('aria-expanded'); + const expanded = expandedValue && expandedValue !== 'false'; + const popupRole = node.getAttribute('aria-haspopup') || 'listbox'; + + for (let index = 0; index < expandedChildRoles.length; index++) { + const expandedChildRole = expandedChildRoles[index]; + // keep the specified popup type required if expanded + if (expanded && expandedChildRole === popupRole) { + continue; + } + + // remove 'listbox' and company from missing roles if combobox is collapsed + const missingIndex = missing.indexOf(expandedChildRole); + if (missingIndex >= 0) { + missing.splice(missingIndex, 1); + } } } diff --git a/lib/commons/aria/index.js b/lib/commons/aria/index.js index f0fac21db0..c95eddccf6 100644 --- a/lib/commons/aria/index.js +++ b/lib/commons/aria/index.js @@ -433,7 +433,7 @@ lookupTable.role = { required: ['aria-expanded'] }, owned: { - all: ['listbox', 'textbox'] + all: ['listbox', 'tree', 'grid', 'dialog', 'textbox'] }, nameFrom: ['author'], context: null, diff --git a/test/checks/aria/required-children.js b/test/checks/aria/required-children.js index e447590bd4..ed3d60e22a 100644 --- a/test/checks/aria/required-children.js +++ b/test/checks/aria/required-children.js @@ -206,6 +206,26 @@ describe('aria-required-children', function() { ); }); + it('should pass an expanded combobox when the required popup role matches', function() { + var params = checkSetup( + '

Textbox

' + ); + assert.isTrue( + checks['aria-required-children'].evaluate.apply(checkContext, params) + ); + }); + + it('should fail an expanded combobox when the required role is missing on children', function() { + var params = checkSetup( + '

Textbox

' + ); + assert.isFalse( + checks['aria-required-children'].evaluate.apply(checkContext, params) + ); + + assert.deepEqual(checkContext._data, ['grid']); + }); + it('should pass one indirectly aria-owned child when one required', function() { var params = checkSetup( '
Nothing here.
'