From 94f3e3ff62c4abc5d71d1383ee5bce0a2005c2e6 Mon Sep 17 00:00:00 2001
From: LB
Date: Wed, 23 Oct 2024 14:48:47 +1000
Subject: [PATCH] [fix] Refine implicit role of `select` to include `combobox`
scenarios
Encode implicit roles for `select` elements based on roles defined in https://www.w3.org/TR/html-aria/#el-select
- `select` (with a multiple attribute or a size attribute having value greater than 1) will have the implicit role 'listbox'
- `select` (with NO multiple attribute and NO size attribute having value greater than 1) will have the implicit role 'combobox'
Fixes #949
---
__tests__/src/rules/no-redundant-roles-test.js | 7 +++++++
src/util/implicitRoles/select.js | 16 +++++++++++++---
2 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/__tests__/src/rules/no-redundant-roles-test.js b/__tests__/src/rules/no-redundant-roles-test.js
index 60cc2185e..bdcb57bb8 100644
--- a/__tests__/src/rules/no-redundant-roles-test.js
+++ b/__tests__/src/rules/no-redundant-roles-test.js
@@ -41,12 +41,19 @@ const alwaysValid = [
{ code: '' },
{ code: '' },
{ code: '', settings: componentsSettings },
+ { code: '' },
];
const neverValid = [
{ code: '', errors: [expectedError('button', 'button')] },
{ code: '', errors: [expectedError('body', 'document')] },
{ code: '', settings: componentsSettings, errors: [expectedError('button', 'button')] },
+ { code: '', errors: [expectedError('select', 'combobox')] },
+ { code: '', errors: [expectedError('select', 'combobox')] },
+ { code: '', errors: [expectedError('select', 'combobox')] },
+ { code: '', errors: [expectedError('select', 'listbox')] },
+ { code: '', errors: [expectedError('select', 'listbox')] },
+ { code: '', errors: [expectedError('select', 'listbox')] },
];
ruleTester.run(`${ruleName}:recommended`, rule, {
diff --git a/src/util/implicitRoles/select.js b/src/util/implicitRoles/select.js
index 9f23296c0..343126cb9 100644
--- a/src/util/implicitRoles/select.js
+++ b/src/util/implicitRoles/select.js
@@ -1,6 +1,16 @@
+import { getProp, getLiteralPropValue } from 'jsx-ast-utils';
+
/**
- * Returns the implicit role for a select tag.
+ * Returns the implicit role for a select tag depending on attributes.
+ *
+ * @see https://www.w3.org/TR/html-aria/#el-select
*/
-export default function getImplicitRoleForSelect() {
- return 'listbox';
+export default function getImplicitRoleForSelect(attributes) {
+ const multiple = getProp(attributes, 'multiple');
+ if (multiple) return 'listbox';
+
+ const size = getProp(attributes, 'size') && getLiteralPropValue(getProp(attributes, 'size'));
+ if (size && (Number(size) > 1)) return 'listbox';
+
+ return 'combobox';
}