From 69f778b71b4c78f89334dcb0c75bedc2005609f5 Mon Sep 17 00:00:00 2001
From: Ava Gaiety W
Date: Mon, 22 Apr 2024 11:11:12 -0500
Subject: [PATCH 01/14] fix(aria-roles): correct abstract roles (types) for
aria-roles
Too many aria roles were set to widget or otherwise were incorrect, added a comment source for where I got my information for which abstract roles were the type of which roles
Refs: #4371
---
lib/standards/aria-roles.js | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/lib/standards/aria-roles.js b/lib/standards/aria-roles.js
index 340fdb9b14..0359909671 100644
--- a/lib/standards/aria-roles.js
+++ b/lib/standards/aria-roles.js
@@ -1,4 +1,5 @@
// Source: https://www.w3.org/TR/wai-aria-1.1/#roles
+// Source for abstract roles: https://www.w3.org/TR/wai-aria/#abstract_roles and https://www.w3.org/WAI/ARIA/1.2/class-diagram/rdf_model.svg
/* easiest way to see allowed roles is to filter out the global ones
from the list of inherited states and properties. The dpub spec
@@ -17,13 +18,13 @@
*/
const ariaRoles = {
alert: {
- type: 'widget',
+ type: 'structure',
// Spec difference: Aria-expanded removed in 1.2
allowedAttrs: ['aria-expanded'],
superclassRole: ['section']
},
alertdialog: {
- type: 'widget',
+ type: 'window',
// Spec difference: Aria-expanded removed in 1.2
allowedAttrs: ['aria-expanded', 'aria-modal'],
superclassRole: ['alert', 'dialog'],
@@ -31,7 +32,7 @@ const ariaRoles = {
},
application: {
// Note: spec difference
- type: 'landmark',
+ type: 'structure',
// Note: aria-expanded is not in the 1.1 spec but is
// consistently supported in ATs and was added in 1.2
allowedAttrs: ['aria-activedescendant', 'aria-expanded'],
@@ -119,7 +120,7 @@ const ariaRoles = {
nameFromContent: true
},
combobox: {
- type: 'widget',
+ type: 'composite',
requiredAttrs: ['aria-expanded', 'aria-controls'],
allowedAttrs: [
'aria-owns',
@@ -169,7 +170,7 @@ const ariaRoles = {
prohibitedAttrs: ['aria-label', 'aria-labelledby']
},
dialog: {
- type: 'widget',
+ type: 'window',
// Spec difference: Aria-expanded removed in 1.2
allowedAttrs: ['aria-expanded', 'aria-modal'],
superclassRole: ['window'],
@@ -301,7 +302,7 @@ const ariaRoles = {
superclassRole: ['section']
},
listbox: {
- type: 'widget',
+ type: 'composite',
requiredOwned: ['group', 'option'],
allowedAttrs: [
'aria-multiselectable',
@@ -328,7 +329,7 @@ const ariaRoles = {
nameFromContent: true
},
log: {
- type: 'widget',
+ type: 'structure',
// Spec difference: Aria-expanded removed in 1.2
allowedAttrs: ['aria-expanded'],
superclassRole: ['section']
@@ -340,7 +341,7 @@ const ariaRoles = {
superclassRole: ['landmark']
},
marquee: {
- type: 'widget',
+ type: 'structure',
// Spec difference: Aria-expanded removed in 1.2
allowedAttrs: ['aria-expanded'],
superclassRole: ['section']
@@ -696,7 +697,7 @@ const ariaRoles = {
accessibleNameRequired: true
},
status: {
- type: 'widget',
+ type: 'structure',
// Spec difference: Aria-expanded removed in 1.2
allowedAttrs: ['aria-expanded'],
superclassRole: ['section']
@@ -816,7 +817,7 @@ const ariaRoles = {
superclassRole: ['section']
},
timer: {
- type: 'widget',
+ type: 'structure',
// Spec difference: Aria-expanded removed in 1.2
allowedAttrs: ['aria-expanded'],
superclassRole: ['status']
From ffe37f6f3dfe58f945718581dcdc5c2aef74f498 Mon Sep 17 00:00:00 2001
From: Ava Gaiety W
Date: Mon, 22 Apr 2024 12:48:42 -0500
Subject: [PATCH 02/14] fix(aria-roles): table with role application is
structure
Previously there was a test to confirm a table with role of application was a data table, but the spec indicates that has an anstract role of structure meaning this should be a structure table instead
This commit is just a test correction
Refs: #4421
---
test/commons/table/is-data-table.js | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/test/commons/table/is-data-table.js b/test/commons/table/is-data-table.js
index c3607faf0b..d78c25e7bb 100644
--- a/test/commons/table/is-data-table.js
+++ b/test/commons/table/is-data-table.js
@@ -32,6 +32,14 @@ describe('table.isDataTable', function () {
assert.isFalse(axe.commons.table.isDataTable(node));
});
+ it('should be false if the table has role=application, which is an astract role of structure', function () {
+ fixture.innerHTML = '
';
+
+ var node = fixture.querySelector('table');
+ axe.testUtils.flatTreeSetup(fixture.firstChild);
+ assert.isFalse(axe.commons.table.isDataTable(node));
+ });
+
it('should be true if the table is inside an editable area', function () {
fixture.innerHTML =
'
' +
@@ -71,13 +79,6 @@ describe('table.isDataTable', function () {
});
describe('should be true if the table has a landmark role', function () {
- it('application', function () {
- fixture.innerHTML = '
';
-
- var node = fixture.querySelector('table');
- axe.testUtils.flatTreeSetup(fixture.firstChild);
- assert.isTrue(axe.commons.table.isDataTable(node));
- });
it('banner', function () {
fixture.innerHTML = '
';
From aa1aa20043b03bb24783a46e040931804f2a1c5a Mon Sep 17 00:00:00 2001
From: Ava Gaiety W
Date: Mon, 22 Apr 2024 13:17:17 -0500
Subject: [PATCH 03/14] fix(aria-roles): inline widgets consider composite type
widget not inline rule corrected isWidgetType check to consider composite widget types
---
lib/rules/widget-not-inline-matches.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lib/rules/widget-not-inline-matches.js b/lib/rules/widget-not-inline-matches.js
index 61e5f22706..1e6a7602da 100644
--- a/lib/rules/widget-not-inline-matches.js
+++ b/lib/rules/widget-not-inline-matches.js
@@ -18,7 +18,8 @@ const matchesFns = [
];
function isWidgetType(vNode) {
- return getRoleType(vNode) === 'widget';
+ const roleType = getRoleType(vNode);
+ return roleType === 'widget' || roleType === 'composite';
}
function isNotAreaElement(vNode) {
From 2d185f65e11c79cddcd48ac66a672866e3f083a3 Mon Sep 17 00:00:00 2001
From: Ava Gaiety W
Date: Thu, 25 Apr 2024 08:14:31 -0500
Subject: [PATCH 04/14] fix(aria-roles): address pr comments
- learned sometimes we intentionally spec change
- added `window` as a supported type, and `composite` which was missing from the readme
- undid my change to `isWidgetType`
Refs: #4371
---
doc/standards-object.md | 6 ++++--
lib/rules/widget-not-inline-matches.js | 3 +--
lib/standards/aria-roles.js | 10 ++++++----
3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/doc/standards-object.md b/doc/standards-object.md
index a439b1ed41..cd34776d96 100644
--- a/doc/standards-object.md
+++ b/doc/standards-object.md
@@ -67,9 +67,11 @@ The [`ariaRoles`](../lib/standards/aria-roles.js) object defines valid ARIA role
- `type` - string(required). [The role type](https://www.w3.org/TR/wai-aria-1.1/#roles_categorization). Valid types are:
- `abstract`
- - `widget`
- - `structure`
+ - `composite`
- `landmark`
+ - `structure`
+ - `widget`
+ - `window`
- `requiredContext` - array(optional). List of required parent roles.
- `requiredOwned` - array(optional). List of required owned roles.
- `requiredAttrs` - array(optional). List of required attributes.
diff --git a/lib/rules/widget-not-inline-matches.js b/lib/rules/widget-not-inline-matches.js
index 1e6a7602da..61e5f22706 100644
--- a/lib/rules/widget-not-inline-matches.js
+++ b/lib/rules/widget-not-inline-matches.js
@@ -18,8 +18,7 @@ const matchesFns = [
];
function isWidgetType(vNode) {
- const roleType = getRoleType(vNode);
- return roleType === 'widget' || roleType === 'composite';
+ return getRoleType(vNode) === 'widget';
}
function isNotAreaElement(vNode) {
diff --git a/lib/standards/aria-roles.js b/lib/standards/aria-roles.js
index 0359909671..7a6d325773 100644
--- a/lib/standards/aria-roles.js
+++ b/lib/standards/aria-roles.js
@@ -1,5 +1,5 @@
// Source: https://www.w3.org/TR/wai-aria-1.1/#roles
-// Source for abstract roles: https://www.w3.org/TR/wai-aria/#abstract_roles and https://www.w3.org/WAI/ARIA/1.2/class-diagram/rdf_model.svg
+// Source for abstract roles (types): https://www.w3.org/TR/wai-aria/#abstract_roles
/* easiest way to see allowed roles is to filter out the global ones
from the list of inherited states and properties. The dpub spec
@@ -32,7 +32,7 @@ const ariaRoles = {
},
application: {
// Note: spec difference
- type: 'structure',
+ type: 'landmark',
// Note: aria-expanded is not in the 1.1 spec but is
// consistently supported in ATs and was added in 1.2
allowedAttrs: ['aria-activedescendant', 'aria-expanded'],
@@ -120,7 +120,8 @@ const ariaRoles = {
nameFromContent: true
},
combobox: {
- type: 'composite',
+ // Note: spec difference
+ type: 'widget',
requiredAttrs: ['aria-expanded', 'aria-controls'],
allowedAttrs: [
'aria-owns',
@@ -302,7 +303,8 @@ const ariaRoles = {
superclassRole: ['section']
},
listbox: {
- type: 'composite',
+ // Note: spec difference
+ type: 'widget',
requiredOwned: ['group', 'option'],
allowedAttrs: [
'aria-multiselectable',
From 417e6b1a03d3359db37d87a67f5b2ee9687107c2 Mon Sep 17 00:00:00 2001
From: Ava Gaiety W
Date: Thu, 25 Apr 2024 08:23:20 -0500
Subject: [PATCH 05/14] fix(aria-roles): reverted test change as well
test change was only for data tables, but we didn't want to keep that type change
Refs: #4371
---
test/commons/table/is-data-table.js | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/test/commons/table/is-data-table.js b/test/commons/table/is-data-table.js
index d78c25e7bb..c3607faf0b 100644
--- a/test/commons/table/is-data-table.js
+++ b/test/commons/table/is-data-table.js
@@ -32,14 +32,6 @@ describe('table.isDataTable', function () {
assert.isFalse(axe.commons.table.isDataTable(node));
});
- it('should be false if the table has role=application, which is an astract role of structure', function () {
- fixture.innerHTML = '
';
-
- var node = fixture.querySelector('table');
- axe.testUtils.flatTreeSetup(fixture.firstChild);
- assert.isFalse(axe.commons.table.isDataTable(node));
- });
-
it('should be true if the table is inside an editable area', function () {
fixture.innerHTML =
'
' +
@@ -79,6 +71,13 @@ describe('table.isDataTable', function () {
});
describe('should be true if the table has a landmark role', function () {
+ it('application', function () {
+ fixture.innerHTML = '
';
+
+ var node = fixture.querySelector('table');
+ axe.testUtils.flatTreeSetup(fixture.firstChild);
+ assert.isTrue(axe.commons.table.isDataTable(node));
+ });
it('banner', function () {
fixture.innerHTML = '
';
From facd65f6f528122ba9c748e587ae3cf1ebd2a22a Mon Sep 17 00:00:00 2001
From: Ava Gaiety W
Date: Thu, 25 Apr 2024 13:35:08 -0500
Subject: [PATCH 06/14] fix(aria-roles): exception for focus-order-semantics
add `window` to has-widget-role, renamed
Refs: #4371
---
.../has-widget-or-window-role-evaluate.js | 26 +
...le.json => has-widget-or-window-role.json} | 4 +-
lib/checks/aria/has-widget-role-evaluate.js | 20 -
lib/rules/focus-order-semantics.json | 2 +-
locales/_template.json | 2 +-
test/checks/aria/has-widget-or-window-role.js | 118 ++++
test/checks/aria/has-widget-role.js | 572 ------------------
7 files changed, 148 insertions(+), 596 deletions(-)
create mode 100644 lib/checks/aria/has-widget-or-window-role-evaluate.js
rename lib/checks/aria/{has-widget-role.json => has-widget-or-window-role.json} (67%)
delete mode 100644 lib/checks/aria/has-widget-role-evaluate.js
create mode 100644 test/checks/aria/has-widget-or-window-role.js
delete mode 100644 test/checks/aria/has-widget-role.js
diff --git a/lib/checks/aria/has-widget-or-window-role-evaluate.js b/lib/checks/aria/has-widget-or-window-role-evaluate.js
new file mode 100644
index 0000000000..676b7d6f62
--- /dev/null
+++ b/lib/checks/aria/has-widget-or-window-role-evaluate.js
@@ -0,0 +1,26 @@
+import { getRoleType } from '../../commons/aria';
+
+const acceptedRoles = {
+ widget: true,
+ composite: true,
+ window: true
+};
+
+/**
+ * Check if an elements `role` attribute uses any widget, composite, window abstract role values.
+ *
+ * Widget roles are taken from the `ariaRoles` standards object from the roles `type` property.
+ *
+ * @memberof checks
+ * @return {Boolean} True if the element uses a `widget`, `composite`, or `window` abstract role (type). False otherwise.
+ */
+// # TODO: change to abstract role for widget and window
+function hasWidgetOrWindowRoleEvaluate(node) {
+ const role = node.getAttribute('role');
+ if (role === null) {
+ return false;
+ }
+ return !!acceptedRoles[getRoleType(role)];
+}
+
+export default hasWidgetOrWindowRoleEvaluate;
diff --git a/lib/checks/aria/has-widget-role.json b/lib/checks/aria/has-widget-or-window-role.json
similarity index 67%
rename from lib/checks/aria/has-widget-role.json
rename to lib/checks/aria/has-widget-or-window-role.json
index bda9ad343c..be3f30f7d2 100644
--- a/lib/checks/aria/has-widget-role.json
+++ b/lib/checks/aria/has-widget-or-window-role.json
@@ -1,6 +1,6 @@
{
- "id": "has-widget-role",
- "evaluate": "has-widget-role-evaluate",
+ "id": "has-widget-or-window-role",
+ "evaluate": "has-widget-or-window-role-evaluate",
"options": [],
"metadata": {
"impact": "minor",
diff --git a/lib/checks/aria/has-widget-role-evaluate.js b/lib/checks/aria/has-widget-role-evaluate.js
deleted file mode 100644
index c3344ef207..0000000000
--- a/lib/checks/aria/has-widget-role-evaluate.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import { getRoleType } from '../../commons/aria';
-
-/**
- * Check if an elements `role` attribute uses any widget or composite role values.
- *
- * Widget roles are taken from the `ariaRoles` standards object from the roles `type` property.
- *
- * @memberof checks
- * @return {Boolean} True if the element uses a `widget` or `composite` role. False otherwise.
- */
-function hasWidgetRoleEvaluate(node) {
- const role = node.getAttribute('role');
- if (role === null) {
- return false;
- }
- const roleType = getRoleType(role);
- return roleType === 'widget' || roleType === 'composite';
-}
-
-export default hasWidgetRoleEvaluate;
diff --git a/lib/rules/focus-order-semantics.json b/lib/rules/focus-order-semantics.json
index 8c73c2b9f8..65bc657253 100644
--- a/lib/rules/focus-order-semantics.json
+++ b/lib/rules/focus-order-semantics.json
@@ -9,6 +9,6 @@
"help": "Elements in the focus order should have an appropriate role"
},
"all": [],
- "any": ["has-widget-role", "valid-scrollable-semantics"],
+ "any": ["has-widget-or-window-role", "valid-scrollable-semantics"],
"none": []
}
diff --git a/locales/_template.json b/locales/_template.json
index 6ea35122f6..2c09e751c9 100644
--- a/locales/_template.json
+++ b/locales/_template.json
@@ -576,7 +576,7 @@
},
"fail": "Element does not have global ARIA attribute"
},
- "has-widget-role": {
+ "has-widget-or-window-role": {
"pass": "Element has a widget role.",
"fail": "Element does not have a widget role."
},
diff --git a/test/checks/aria/has-widget-or-window-role.js b/test/checks/aria/has-widget-or-window-role.js
new file mode 100644
index 0000000000..2adae9971e
--- /dev/null
+++ b/test/checks/aria/has-widget-or-window-role.js
@@ -0,0 +1,118 @@
+describe('has-widget-or-window-role', function () {
+ 'use strict';
+
+ let node;
+ const fixture = document.getElementById('fixture');
+ const checkContext = axe.testUtils.MockCheckContext();
+ const evaluate = currentNode =>
+ axe.testUtils
+ .getCheckEvaluate('has-widget-or-window-role')
+ .call(checkContext, currentNode);
+ const roles = {
+ widget: {
+ button: true,
+ checkbox: true,
+ gridcell: true,
+ link: true,
+ menuitem: true,
+ menuitemcheckbox: true,
+ menuitemradio: true,
+ option: true,
+ progressbar: true,
+ radio: true,
+ scrollbar: true,
+ searchbox: true,
+ slider: true,
+ spinbutton: true,
+ switch: true,
+ tab: true,
+ tabpanel: true,
+ textbox: true,
+ treeitem: true
+ },
+ composite: {
+ combobox: true,
+ grid: true,
+ listbox: true,
+ menu: true,
+ menubar: true,
+ radiogroup: true,
+ tablist: true,
+ tree: true,
+ treegrid: true,
+
+ application: false,
+ article: false,
+ cell: false,
+ columnheader: false,
+ definition: false,
+ directory: false,
+ document: false,
+ feed: false,
+ figure: false,
+ group: false,
+ heading: false,
+ img: false,
+ list: false,
+ listitem: false,
+ math: false,
+ none: false,
+ note: false,
+ presentation: false,
+ row: false,
+ rowgroup: false,
+ rowheader: false,
+ table: false,
+ term: false,
+ toolbar: false
+ },
+ window: {
+ alertdialog: true,
+ dialog: true
+ },
+ landmark: {
+ banner: false,
+ complimentary: false,
+ contentinfo: false,
+ form: false,
+ name: false,
+ navigation: false,
+ region: false,
+ search: false
+ }
+ };
+
+ afterEach(function () {
+ node.innerHTML = '';
+ checkContext._data = null;
+ });
+
+ it('should return false for elements with no role', function () {
+ node = document.createElement('div');
+ fixture.appendChild(node);
+
+ assert.isFalse(evaluate(node));
+ });
+
+ it('should return false for elements with nonsensical roles', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'buttonbuttonbutton');
+ fixture.appendChild(node);
+
+ assert.isFalse(evaluate(node));
+ });
+
+ Object.keys(roles).forEach(category => {
+ describe(category, function () {
+ Object.keys(roles[category]).forEach(role => {
+ it(`should return ${roles[category][role]} for role="${role}"`, function () {
+ node = document.createElement('div');
+ node.setAttribute('role', role);
+ fixture.appendChild(node);
+
+ assert.equal(evaluate(node), roles[category][role]);
+ });
+ });
+ });
+ });
+});
diff --git a/test/checks/aria/has-widget-role.js b/test/checks/aria/has-widget-role.js
deleted file mode 100644
index f7324cadc9..0000000000
--- a/test/checks/aria/has-widget-role.js
+++ /dev/null
@@ -1,572 +0,0 @@
-describe('has-widget-role', function () {
- 'use strict';
-
- var fixture = document.getElementById('fixture');
- var node;
- var checkContext = axe.testUtils.MockCheckContext();
-
- afterEach(function () {
- node.innerHTML = '';
- checkContext._data = null;
- });
-
- it('should return false for elements with no role', function () {
- node = document.createElement('div');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for elements with nonsensical roles', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'buttonbuttonbutton');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- // Widget roles
- it('should return true for role=button', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'button');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=checkbox', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'checkbox');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=gridcell', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'gridcell');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=link', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'link');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=menuitem', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'menuitem');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=menuitemcheckbox', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'menuitemcheckbox');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=menuitemradio', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'menuitemradio');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=option', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'option');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=progressbar', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'progressbar');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=radio', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'radio');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=scrollbar', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'scrollbar');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=searchbox', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'searchbox');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=slider', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'slider');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=spinbutton', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'spinbutton');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=switch', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'switch');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=tab', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'tab');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=tabpanel', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'tabpanel');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=textbox', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'textbox');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=treeitem', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'treeitem');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- // Composite widget roles
- it('should return true for role=combobox', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'combobox');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=grid', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'grid');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=listbox', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'listbox');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=menu', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'menu');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=menubar', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'menubar');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=radiogroup', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'radiogroup');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=tablist', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'tablist');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=tree', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'tree');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return true for role=treegrid', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'treegrid');
- fixture.appendChild(node);
- assert.isTrue(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=application', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'application');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=article', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'article');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=cell', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'cell');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=columnheader', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'columnheader');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=definition', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'definition');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=directory', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'directory');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=document', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'document');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=feed', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'feed');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=figure', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'figure');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=group', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'group');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=heading', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'heading');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=img', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'img');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=list', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'list');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=listitem', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'listitem');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=math', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'math');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=none', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'none');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=note', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'note');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=presentation', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'presentation');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=row', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'row');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=rowgroup', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'rowgroup');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=rowheader', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'rowheader');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=table', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'table');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=term', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'term');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=toolbar', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'toolbar');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- // Landmark Roles
- it('should return false for role=banner', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'banner');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=complementary', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'complementary');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=contentinfo', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'contentinfo');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=form', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'form');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=main', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'main');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=navigation', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'navigation');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=region', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'region');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-
- it('should return false for role=search', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'search');
- fixture.appendChild(node);
- assert.isFalse(
- axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
- );
- });
-});
From bfa95ae2ff233de32390777f735cd35ef1e50fa4 Mon Sep 17 00:00:00 2001
From: Ava Gaiety W
Date: Thu, 25 Apr 2024 14:35:45 -0500
Subject: [PATCH 07/14] fix(aria-roles): updated locales
better pass/fail english message, removed outdated translations
Refs: #4371
---
lib/checks/aria/has-widget-or-window-role.json | 4 ++--
locales/_template.json | 4 ++--
locales/da.json | 4 ----
locales/de.json | 4 ----
locales/el.json | 4 ----
locales/es.json | 4 ----
locales/eu.json | 4 ----
locales/fr.json | 4 ----
locales/he.json | 4 ----
locales/it.json | 4 ----
locales/ja.json | 4 ----
locales/ko.json | 4 ----
locales/no_NB.json | 4 ----
locales/pl.json | 4 ----
locales/pt_BR.json | 4 ----
locales/zh_CN.json | 4 ----
locales/zh_TW.json | 4 ----
17 files changed, 4 insertions(+), 64 deletions(-)
diff --git a/lib/checks/aria/has-widget-or-window-role.json b/lib/checks/aria/has-widget-or-window-role.json
index be3f30f7d2..f5fed0b464 100644
--- a/lib/checks/aria/has-widget-or-window-role.json
+++ b/lib/checks/aria/has-widget-or-window-role.json
@@ -5,8 +5,8 @@
"metadata": {
"impact": "minor",
"messages": {
- "pass": "Element has a widget role.",
- "fail": "Element does not have a widget role."
+ "pass": "Element has a widget or window role.",
+ "fail": "Element does not have a widget or window role."
}
}
}
diff --git a/locales/_template.json b/locales/_template.json
index 2c09e751c9..cbdf75ed68 100644
--- a/locales/_template.json
+++ b/locales/_template.json
@@ -577,8 +577,8 @@
"fail": "Element does not have global ARIA attribute"
},
"has-widget-or-window-role": {
- "pass": "Element has a widget role.",
- "fail": "Element does not have a widget role."
+ "pass": "Element has a widget or window role.",
+ "fail": "Element does not have a widget or window role."
},
"invalidrole": {
"pass": "ARIA role is valid",
diff --git a/locales/da.json b/locales/da.json
index 56c9a5ccd7..a8f54214ed 100644
--- a/locales/da.json
+++ b/locales/da.json
@@ -365,10 +365,6 @@
"plural": "'aria-errormessage'-værdi ${data.values}` bør bruge en teknik til at annoncere beskeden (fx 'aria-live', 'aria-describedby', 'role=alert', osv.)"
}
},
- "has-widget-role": {
- "pass": "Elementet har en 'widget'-rolle.",
- "fail": "Elementet har ikke en 'widget'-rolle."
- },
"invalidrole": {
"pass": "ARIA-rollen er korrekt",
"fail": "Rollen skal være en af de mulige ARIA-roller"
diff --git a/locales/de.json b/locales/de.json
index 8f35d0c653..bd8a24b0a0 100644
--- a/locales/de.json
+++ b/locales/de.json
@@ -576,10 +576,6 @@
},
"fail": "Das Element hat keine globalen ARIA Attribute."
},
- "has-widget-role": {
- "pass": "Element hat eine widget-Rolle.",
- "fail": "Das Element besitzt keine widget-Rolle."
- },
"invalidrole": {
"pass": "ARIA Rolle ist gültig.",
"fail": {
diff --git a/locales/el.json b/locales/el.json
index f8f805c424..4355fafeb1 100644
--- a/locales/el.json
+++ b/locales/el.json
@@ -539,10 +539,6 @@
},
"fail": "Το στοιχείο δεν έχει καθολικό χαρακτηριστικό ARIA"
},
- "has-widget-role": {
- "pass": "Το στοιχείο έχει ρόλο widget.",
- "fail": "Το στοιχείο δεν έχει ρόλο widget."
- },
"invalidrole": {
"pass": "Ο ρόλος ARIA είναι έγκυρος",
"fail": {
diff --git a/locales/es.json b/locales/es.json
index 7a0b5c0b3f..1f5aace76e 100644
--- a/locales/es.json
+++ b/locales/es.json
@@ -356,10 +356,6 @@
"plural": "En aria-errormessage, valor ${data.values}`, se debe usar una técnica para anunciar el mensaje (p. ej., aria-live, aria-describedby, role=alert, etc.)"
}
},
- "has-widget-role": {
- "pass": "El elemento tiene un rol de widget.",
- "fail": "El elemento no tiene un rol de widget."
- },
"invalidrole": {
"pass": "El rol ARIA es válido",
"fail": "El rol debe ser uno de los roles ARIA válidos"
diff --git a/locales/eu.json b/locales/eu.json
index 03b534cfc7..e4130d3756 100644
--- a/locales/eu.json
+++ b/locales/eu.json
@@ -356,10 +356,6 @@
"plural": "aria-errormessagen, bailioa ${data.values}`, mezua iragartzeko teknika bat erabili behar da (adibidez: aria-live, aria-describedby, role = alert, etab.)."
}
},
- "has-widget-role": {
- "pass": "Elementuak widget rola du.",
- "fail": "Elementuak ez du widget rolik."
- },
"invalidrole": {
"pass": "ARIA rola baliozkoa da",
"fail": "Rolak baliozko ARIA rola izan behar du"
diff --git a/locales/fr.json b/locales/fr.json
index 9bd71725e4..b570785184 100644
--- a/locales/fr.json
+++ b/locales/fr.json
@@ -519,10 +519,6 @@
},
"fail": "L’élément n’a pas d’attribut ARIA global"
},
- "has-widget-role": {
- "pass": "L’élément a un rôle widget.",
- "fail": "L’élément n’a pas de rôle widget."
- },
"invalidrole": {
"pass": "Le rôle ARIA est valide",
"fail": {
diff --git a/locales/he.json b/locales/he.json
index fd0d2eaa50..5502bac62d 100644
--- a/locales/he.json
+++ b/locales/he.json
@@ -529,10 +529,6 @@
},
"fail": "לאלמנט אין תכונת ARIA גלובלית: "
},
- "has-widget-role": {
- "pass": "לאלמנט יש תפקיד של וגדג'ט.",
- "fail": "לאלמנט אין תפקיד של וגדג'ט."
- },
"invalidrole": {
"pass": "תפקיד ARIA קביל",
"fail": {
diff --git a/locales/it.json b/locales/it.json
index 6f1b723259..6aa14e6090 100644
--- a/locales/it.json
+++ b/locales/it.json
@@ -573,10 +573,6 @@
},
"fail": "L'elemento non ha un attributo ARIA globale"
},
- "has-widget-role": {
- "pass": "L'elemento ha un ruolo widget.",
- "fail": "L'elemento non ha un ruolo widget."
- },
"invalidrole": {
"pass": "Il ruolo ARIA è valido",
"fail": {
diff --git a/locales/ja.json b/locales/ja.json
index 161fdba32e..ce1f6e0ebe 100644
--- a/locales/ja.json
+++ b/locales/ja.json
@@ -575,10 +575,6 @@
},
"fail": "要素にはグローバルなARIA属性が指定されていません"
},
- "has-widget-role": {
- "pass": "要素にはwidgetロールが存在します",
- "fail": "要素にはwidgetロールが存在しません"
- },
"invalidrole": {
"pass": "ARIAロールが有効です",
"fail": {
diff --git a/locales/ko.json b/locales/ko.json
index 9c304d1d7f..d86ffeed5b 100644
--- a/locales/ko.json
+++ b/locales/ko.json
@@ -524,10 +524,6 @@
},
"fail": "엘리먼트가 전역 ARIA 어트리뷰트를 가지고 있지 않습니다."
},
- "has-widget-role": {
- "pass": "엘리먼트가 위젯 역할(role)을 가지고 있습니다.",
- "fail": "엘리먼트가 위젯 역할(role)을 가지고 있지 않습니다."
- },
"invalidrole": {
"pass": "ARIA 역할(role)이 유효합니다.",
"fail": {
diff --git a/locales/no_NB.json b/locales/no_NB.json
index 4dbf8dbe9d..ed73ec0bb4 100644
--- a/locales/no_NB.json
+++ b/locales/no_NB.json
@@ -365,10 +365,6 @@
"plural": "'aria-errormessage'-verdier ${data.values}` skal bruke en metode for å annonsere beskeden (f.eks. 'aria-live', 'aria-describedby', 'role=alert', osv.)"
}
},
- "has-widget-role": {
- "pass": "Elementet har en 'widget'-rolle.",
- "fail": "Elementet har ikke en 'widget'-rolle."
- },
"invalidrole": {
"pass": "ARIA-rollen er korrekt",
"fail": "Rollen skal være en av de mulige ARIA-roller"
diff --git a/locales/pl.json b/locales/pl.json
index 1caafcabda..7c2f2d1f76 100644
--- a/locales/pl.json
+++ b/locales/pl.json
@@ -575,10 +575,6 @@
},
"fail": "Element nie ma ogólnego atrybutu ARIA"
},
- "has-widget-role": {
- "pass": "Element ma rolę widżetu.",
- "fail": "Element nie ma roli widżetu."
- },
"invalidrole": {
"pass": "Rola ARIA jest poprawna.",
"fail": {
diff --git a/locales/pt_BR.json b/locales/pt_BR.json
index 404d5ab293..68d4cf2da9 100644
--- a/locales/pt_BR.json
+++ b/locales/pt_BR.json
@@ -504,10 +504,6 @@
},
"fail": "O elemento não tem atributo ARIA global"
},
- "has-widget-role": {
- "pass": "Elemento tem um 'role' de 'widget'.",
- "fail": "Elemento não tem um 'role' de 'widget'."
- },
"invalidrole": {
"pass": "O ARIA 'role' é válido",
"fail": {
diff --git a/locales/zh_CN.json b/locales/zh_CN.json
index ef5e6876dc..089cf0ce34 100644
--- a/locales/zh_CN.json
+++ b/locales/zh_CN.json
@@ -576,10 +576,6 @@
},
"fail": "元素没有全局 ARIA 属性"
},
- "has-widget-role": {
- "pass": "元素有小部件角色",
- "fail": "元素没有小部件角色"
- },
"invalidrole": {
"pass": "ARIA 角色有效",
"fail": {
diff --git a/locales/zh_TW.json b/locales/zh_TW.json
index 37a9d3262b..ba6c50f4c8 100644
--- a/locales/zh_TW.json
+++ b/locales/zh_TW.json
@@ -573,10 +573,6 @@
},
"fail": "元素沒有全域 ARIA 屬性"
},
- "has-widget-role": {
- "pass": "元素具有小部件角色",
- "fail": "元素沒有小部件角色"
- },
"invalidrole": {
"pass": "ARIA 角色有效",
"fail": {
From a07c4882ba5fed7f44b845a613b035e65c153a6a Mon Sep 17 00:00:00 2001
From: Ava Gaiety W
Date: Mon, 29 Apr 2024 08:25:25 -0500
Subject: [PATCH 08/14] Revert "fix(aria-roles): exception for
focus-order-semantics"
Addresses some feedback from Wilco in the PR that this isn't the change
we want
This reverts commit facd65f6f528122ba9c748e587ae3cf1ebd2a22a.
---
.../has-widget-or-window-role-evaluate.js | 26 -
lib/checks/aria/has-widget-role-evaluate.js | 20 +
...-window-role.json => has-widget-role.json} | 4 +-
lib/rules/focus-order-semantics.json | 2 +-
locales/_template.json | 6 +-
test/checks/aria/has-widget-or-window-role.js | 118 ----
test/checks/aria/has-widget-role.js | 572 ++++++++++++++++++
7 files changed, 598 insertions(+), 150 deletions(-)
delete mode 100644 lib/checks/aria/has-widget-or-window-role-evaluate.js
create mode 100644 lib/checks/aria/has-widget-role-evaluate.js
rename lib/checks/aria/{has-widget-or-window-role.json => has-widget-role.json} (69%)
delete mode 100644 test/checks/aria/has-widget-or-window-role.js
create mode 100644 test/checks/aria/has-widget-role.js
diff --git a/lib/checks/aria/has-widget-or-window-role-evaluate.js b/lib/checks/aria/has-widget-or-window-role-evaluate.js
deleted file mode 100644
index 676b7d6f62..0000000000
--- a/lib/checks/aria/has-widget-or-window-role-evaluate.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import { getRoleType } from '../../commons/aria';
-
-const acceptedRoles = {
- widget: true,
- composite: true,
- window: true
-};
-
-/**
- * Check if an elements `role` attribute uses any widget, composite, window abstract role values.
- *
- * Widget roles are taken from the `ariaRoles` standards object from the roles `type` property.
- *
- * @memberof checks
- * @return {Boolean} True if the element uses a `widget`, `composite`, or `window` abstract role (type). False otherwise.
- */
-// # TODO: change to abstract role for widget and window
-function hasWidgetOrWindowRoleEvaluate(node) {
- const role = node.getAttribute('role');
- if (role === null) {
- return false;
- }
- return !!acceptedRoles[getRoleType(role)];
-}
-
-export default hasWidgetOrWindowRoleEvaluate;
diff --git a/lib/checks/aria/has-widget-role-evaluate.js b/lib/checks/aria/has-widget-role-evaluate.js
new file mode 100644
index 0000000000..c3344ef207
--- /dev/null
+++ b/lib/checks/aria/has-widget-role-evaluate.js
@@ -0,0 +1,20 @@
+import { getRoleType } from '../../commons/aria';
+
+/**
+ * Check if an elements `role` attribute uses any widget or composite role values.
+ *
+ * Widget roles are taken from the `ariaRoles` standards object from the roles `type` property.
+ *
+ * @memberof checks
+ * @return {Boolean} True if the element uses a `widget` or `composite` role. False otherwise.
+ */
+function hasWidgetRoleEvaluate(node) {
+ const role = node.getAttribute('role');
+ if (role === null) {
+ return false;
+ }
+ const roleType = getRoleType(role);
+ return roleType === 'widget' || roleType === 'composite';
+}
+
+export default hasWidgetRoleEvaluate;
diff --git a/lib/checks/aria/has-widget-or-window-role.json b/lib/checks/aria/has-widget-role.json
similarity index 69%
rename from lib/checks/aria/has-widget-or-window-role.json
rename to lib/checks/aria/has-widget-role.json
index f5fed0b464..9f79d1487a 100644
--- a/lib/checks/aria/has-widget-or-window-role.json
+++ b/lib/checks/aria/has-widget-role.json
@@ -1,6 +1,6 @@
{
- "id": "has-widget-or-window-role",
- "evaluate": "has-widget-or-window-role-evaluate",
+ "id": "has-widget-role",
+ "evaluate": "has-widget-role-evaluate",
"options": [],
"metadata": {
"impact": "minor",
diff --git a/lib/rules/focus-order-semantics.json b/lib/rules/focus-order-semantics.json
index 65bc657253..8c73c2b9f8 100644
--- a/lib/rules/focus-order-semantics.json
+++ b/lib/rules/focus-order-semantics.json
@@ -9,6 +9,6 @@
"help": "Elements in the focus order should have an appropriate role"
},
"all": [],
- "any": ["has-widget-or-window-role", "valid-scrollable-semantics"],
+ "any": ["has-widget-role", "valid-scrollable-semantics"],
"none": []
}
diff --git a/locales/_template.json b/locales/_template.json
index cbdf75ed68..6ea35122f6 100644
--- a/locales/_template.json
+++ b/locales/_template.json
@@ -576,9 +576,9 @@
},
"fail": "Element does not have global ARIA attribute"
},
- "has-widget-or-window-role": {
- "pass": "Element has a widget or window role.",
- "fail": "Element does not have a widget or window role."
+ "has-widget-role": {
+ "pass": "Element has a widget role.",
+ "fail": "Element does not have a widget role."
},
"invalidrole": {
"pass": "ARIA role is valid",
diff --git a/test/checks/aria/has-widget-or-window-role.js b/test/checks/aria/has-widget-or-window-role.js
deleted file mode 100644
index 2adae9971e..0000000000
--- a/test/checks/aria/has-widget-or-window-role.js
+++ /dev/null
@@ -1,118 +0,0 @@
-describe('has-widget-or-window-role', function () {
- 'use strict';
-
- let node;
- const fixture = document.getElementById('fixture');
- const checkContext = axe.testUtils.MockCheckContext();
- const evaluate = currentNode =>
- axe.testUtils
- .getCheckEvaluate('has-widget-or-window-role')
- .call(checkContext, currentNode);
- const roles = {
- widget: {
- button: true,
- checkbox: true,
- gridcell: true,
- link: true,
- menuitem: true,
- menuitemcheckbox: true,
- menuitemradio: true,
- option: true,
- progressbar: true,
- radio: true,
- scrollbar: true,
- searchbox: true,
- slider: true,
- spinbutton: true,
- switch: true,
- tab: true,
- tabpanel: true,
- textbox: true,
- treeitem: true
- },
- composite: {
- combobox: true,
- grid: true,
- listbox: true,
- menu: true,
- menubar: true,
- radiogroup: true,
- tablist: true,
- tree: true,
- treegrid: true,
-
- application: false,
- article: false,
- cell: false,
- columnheader: false,
- definition: false,
- directory: false,
- document: false,
- feed: false,
- figure: false,
- group: false,
- heading: false,
- img: false,
- list: false,
- listitem: false,
- math: false,
- none: false,
- note: false,
- presentation: false,
- row: false,
- rowgroup: false,
- rowheader: false,
- table: false,
- term: false,
- toolbar: false
- },
- window: {
- alertdialog: true,
- dialog: true
- },
- landmark: {
- banner: false,
- complimentary: false,
- contentinfo: false,
- form: false,
- name: false,
- navigation: false,
- region: false,
- search: false
- }
- };
-
- afterEach(function () {
- node.innerHTML = '';
- checkContext._data = null;
- });
-
- it('should return false for elements with no role', function () {
- node = document.createElement('div');
- fixture.appendChild(node);
-
- assert.isFalse(evaluate(node));
- });
-
- it('should return false for elements with nonsensical roles', function () {
- node = document.createElement('div');
- node.setAttribute('role', 'buttonbuttonbutton');
- fixture.appendChild(node);
-
- assert.isFalse(evaluate(node));
- });
-
- Object.keys(roles).forEach(category => {
- describe(category, function () {
- Object.keys(roles[category]).forEach(role => {
- it(`should return ${roles[category][role]} for role="${role}"`, function () {
- node = document.createElement('div');
- node.setAttribute('role', role);
- fixture.appendChild(node);
-
- assert.equal(evaluate(node), roles[category][role]);
- });
- });
- });
- });
-});
diff --git a/test/checks/aria/has-widget-role.js b/test/checks/aria/has-widget-role.js
new file mode 100644
index 0000000000..f7324cadc9
--- /dev/null
+++ b/test/checks/aria/has-widget-role.js
@@ -0,0 +1,572 @@
+describe('has-widget-role', function () {
+ 'use strict';
+
+ var fixture = document.getElementById('fixture');
+ var node;
+ var checkContext = axe.testUtils.MockCheckContext();
+
+ afterEach(function () {
+ node.innerHTML = '';
+ checkContext._data = null;
+ });
+
+ it('should return false for elements with no role', function () {
+ node = document.createElement('div');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for elements with nonsensical roles', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'buttonbuttonbutton');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ // Widget roles
+ it('should return true for role=button', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'button');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=checkbox', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'checkbox');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=gridcell', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'gridcell');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=link', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'link');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=menuitem', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'menuitem');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=menuitemcheckbox', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'menuitemcheckbox');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=menuitemradio', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'menuitemradio');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=option', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'option');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=progressbar', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'progressbar');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=radio', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'radio');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=scrollbar', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'scrollbar');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=searchbox', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'searchbox');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=slider', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'slider');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=spinbutton', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'spinbutton');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=switch', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'switch');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=tab', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'tab');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=tabpanel', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'tabpanel');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=textbox', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'textbox');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=treeitem', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'treeitem');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ // Composite widget roles
+ it('should return true for role=combobox', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'combobox');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=grid', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'grid');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=listbox', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'listbox');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=menu', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'menu');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=menubar', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'menubar');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=radiogroup', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'radiogroup');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=tablist', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'tablist');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=tree', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'tree');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return true for role=treegrid', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'treegrid');
+ fixture.appendChild(node);
+ assert.isTrue(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=application', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'application');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=article', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'article');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=cell', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'cell');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=columnheader', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'columnheader');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=definition', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'definition');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=directory', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'directory');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=document', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'document');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=feed', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'feed');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=figure', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'figure');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=group', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'group');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=heading', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'heading');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=img', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'img');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=list', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'list');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=listitem', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'listitem');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=math', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'math');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=none', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'none');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=note', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'note');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=presentation', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'presentation');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=row', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'row');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=rowgroup', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'rowgroup');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=rowheader', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'rowheader');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=table', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'table');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=term', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'term');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=toolbar', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'toolbar');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ // Landmark Roles
+ it('should return false for role=banner', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'banner');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=complementary', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'complementary');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=contentinfo', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'contentinfo');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=form', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'form');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=main', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'main');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=navigation', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'navigation');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=region', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'region');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+
+ it('should return false for role=search', function () {
+ node = document.createElement('div');
+ node.setAttribute('role', 'search');
+ fixture.appendChild(node);
+ assert.isFalse(
+ axe.testUtils.getCheckEvaluate('has-widget-role').call(checkContext, node)
+ );
+ });
+});
From f11c03fc73f6a932e320415d8a060dbd17b4a98a Mon Sep 17 00:00:00 2001
From: Ava Gaiety W
Date: Mon, 29 Apr 2024 08:39:24 -0500
Subject: [PATCH 09/14] fix(aria-roles): support window role in
valid-scrollable-semantics
reflected in focus-order-semantics
---
.../valid-scrollable-semantics-evaluate.js | 2 ++
.../checks/aria/valid-scrollable-semantics.js | 24 +++++++++++++++++++
.../focus-order-semantics.html | 5 ++++
.../focus-order-semantics.json | 4 +++-
4 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/lib/checks/aria/valid-scrollable-semantics-evaluate.js b/lib/checks/aria/valid-scrollable-semantics-evaluate.js
index 7c3615dbcc..933bd3e69a 100644
--- a/lib/checks/aria/valid-scrollable-semantics-evaluate.js
+++ b/lib/checks/aria/valid-scrollable-semantics-evaluate.js
@@ -16,11 +16,13 @@ const VALID_TAG_NAMES_FOR_SCROLLABLE_REGIONS = {
* appropriate for scrollable elements found in the focus order.
*/
const VALID_ROLES_FOR_SCROLLABLE_REGIONS = {
+ alertdialog: true,
application: true,
article: true,
banner: false,
complementary: true,
contentinfo: true,
+ dialog: true,
form: true,
main: true,
navigation: true,
diff --git a/test/checks/aria/valid-scrollable-semantics.js b/test/checks/aria/valid-scrollable-semantics.js
index 26ea72533a..63c7f1d6fe 100644
--- a/test/checks/aria/valid-scrollable-semantics.js
+++ b/test/checks/aria/valid-scrollable-semantics.js
@@ -106,6 +106,18 @@ describe('valid-scrollable-semantics', function () {
);
});
+ it('should return true for role=alertdialog', function () {
+ var node = document.createElement('div');
+ node.setAttribute('role', 'alertdialog');
+ fixture.appendChild(node);
+ flatTreeSetup(fixture);
+ assert.isTrue(
+ axe.testUtils
+ .getCheckEvaluate('valid-scrollable-semantics')
+ .call(checkContext, node)
+ );
+ });
+
it('should return true for role=article', function () {
var node = document.createElement('div');
node.setAttribute('role', 'article');
@@ -118,6 +130,18 @@ describe('valid-scrollable-semantics', function () {
);
});
+ it('should return true for role=dialog', function () {
+ var node = document.createElement('div');
+ node.setAttribute('role', 'dialog');
+ fixture.appendChild(node);
+ flatTreeSetup(fixture);
+ assert.isTrue(
+ axe.testUtils
+ .getCheckEvaluate('valid-scrollable-semantics')
+ .call(checkContext, node)
+ );
+ });
+
it('should return true for nav elements', function () {
var node = document.createElement('nav');
fixture.appendChild(node);
diff --git a/test/integration/rules/focus-order-semantics/focus-order-semantics.html b/test/integration/rules/focus-order-semantics/focus-order-semantics.html
index 7ac09790ae..3a95bd5cea 100644
--- a/test/integration/rules/focus-order-semantics/focus-order-semantics.html
+++ b/test/integration/rules/focus-order-semantics/focus-order-semantics.html
@@ -32,6 +32,11 @@
Valid landmark roles for scrollable containers
+
Valid window roles for scrollable containers
+
+
+
+
Valid scrollable HTML tags for scrollable regions, not selected by this
rule
diff --git a/test/integration/rules/focus-order-semantics/focus-order-semantics.json b/test/integration/rules/focus-order-semantics/focus-order-semantics.json
index dac1ba8f13..cc1365bbe5 100644
--- a/test/integration/rules/focus-order-semantics/focus-order-semantics.json
+++ b/test/integration/rules/focus-order-semantics/focus-order-semantics.json
@@ -11,7 +11,9 @@
["#pass7"],
["#pass8"],
["#pass9"],
- ["#pass10"]
+ ["#pass10"],
+ ["#pass11"],
+ ["#pass12"]
],
"violations": [
["#violation1"],
From d85631696321b0c2def1336d070f188011b779bc Mon Sep 17 00:00:00 2001
From: Ava Gaiety W
Date: Mon, 29 Apr 2024 08:52:50 -0500
Subject: [PATCH 10/14] fix(aria-roles): window roles and marque/timer
expectations in focus-order-semantics
addressing more pr feedback
---
lib/checks/aria/valid-scrollable-semantics-evaluate.js | 1 +
.../rules/focus-order-semantics/focus-order-semantics.html | 7 +++++--
.../rules/focus-order-semantics/focus-order-semantics.json | 7 +++++--
3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/lib/checks/aria/valid-scrollable-semantics-evaluate.js b/lib/checks/aria/valid-scrollable-semantics-evaluate.js
index 933bd3e69a..755cbf4724 100644
--- a/lib/checks/aria/valid-scrollable-semantics-evaluate.js
+++ b/lib/checks/aria/valid-scrollable-semantics-evaluate.js
@@ -16,6 +16,7 @@ const VALID_TAG_NAMES_FOR_SCROLLABLE_REGIONS = {
* appropriate for scrollable elements found in the focus order.
*/
const VALID_ROLES_FOR_SCROLLABLE_REGIONS = {
+ alert: true,
alertdialog: true,
application: true,
article: true,
diff --git a/test/integration/rules/focus-order-semantics/focus-order-semantics.html b/test/integration/rules/focus-order-semantics/focus-order-semantics.html
index 3a95bd5cea..296b1cb939 100644
--- a/test/integration/rules/focus-order-semantics/focus-order-semantics.html
+++ b/test/integration/rules/focus-order-semantics/focus-order-semantics.html
@@ -19,6 +19,8 @@
Invalid landmark roles for scrollable containers
+
+
Valid landmark roles for scrollable containers
@@ -31,11 +33,12 @@
Valid landmark roles for scrollable containers
+
Valid window roles for scrollable containers
-
-
+
+
Valid scrollable HTML tags for scrollable regions, not selected by this
diff --git a/test/integration/rules/focus-order-semantics/focus-order-semantics.json b/test/integration/rules/focus-order-semantics/focus-order-semantics.json
index cc1365bbe5..0cfe89330d 100644
--- a/test/integration/rules/focus-order-semantics/focus-order-semantics.json
+++ b/test/integration/rules/focus-order-semantics/focus-order-semantics.json
@@ -13,12 +13,15 @@
["#pass9"],
["#pass10"],
["#pass11"],
- ["#pass12"]
+ ["#pass12"],
+ ["#pass13"]
],
"violations": [
["#violation1"],
["#violation2"],
["#violation3"],
- ["#violation4"]
+ ["#violation4"],
+ ["#violation5"],
+ ["#violation6"]
]
}
From dc966d3a5de35d0c4e1946ba8c1096b9f70763c7 Mon Sep 17 00:00:00 2001
From: Ava Gaiety W
Date: Mon, 29 Apr 2024 08:54:15 -0500
Subject: [PATCH 11/14] Revert "fix(aria-roles): updated locales"
This reverts commit bfa95ae2ff233de32390777f735cd35ef1e50fa4.
---
lib/checks/aria/has-widget-role.json | 4 ++--
locales/da.json | 4 ++++
locales/de.json | 4 ++++
locales/el.json | 4 ++++
locales/es.json | 4 ++++
locales/eu.json | 4 ++++
locales/fr.json | 4 ++++
locales/he.json | 4 ++++
locales/it.json | 4 ++++
locales/ja.json | 4 ++++
locales/ko.json | 4 ++++
locales/no_NB.json | 4 ++++
locales/pl.json | 4 ++++
locales/pt_BR.json | 4 ++++
locales/zh_CN.json | 4 ++++
locales/zh_TW.json | 4 ++++
16 files changed, 62 insertions(+), 2 deletions(-)
diff --git a/lib/checks/aria/has-widget-role.json b/lib/checks/aria/has-widget-role.json
index 9f79d1487a..bda9ad343c 100644
--- a/lib/checks/aria/has-widget-role.json
+++ b/lib/checks/aria/has-widget-role.json
@@ -5,8 +5,8 @@
"metadata": {
"impact": "minor",
"messages": {
- "pass": "Element has a widget or window role.",
- "fail": "Element does not have a widget or window role."
+ "pass": "Element has a widget role.",
+ "fail": "Element does not have a widget role."
}
}
}
diff --git a/locales/da.json b/locales/da.json
index a8f54214ed..56c9a5ccd7 100644
--- a/locales/da.json
+++ b/locales/da.json
@@ -365,6 +365,10 @@
"plural": "'aria-errormessage'-værdi ${data.values}` bør bruge en teknik til at annoncere beskeden (fx 'aria-live', 'aria-describedby', 'role=alert', osv.)"
}
},
+ "has-widget-role": {
+ "pass": "Elementet har en 'widget'-rolle.",
+ "fail": "Elementet har ikke en 'widget'-rolle."
+ },
"invalidrole": {
"pass": "ARIA-rollen er korrekt",
"fail": "Rollen skal være en af de mulige ARIA-roller"
diff --git a/locales/de.json b/locales/de.json
index bd8a24b0a0..8f35d0c653 100644
--- a/locales/de.json
+++ b/locales/de.json
@@ -576,6 +576,10 @@
},
"fail": "Das Element hat keine globalen ARIA Attribute."
},
+ "has-widget-role": {
+ "pass": "Element hat eine widget-Rolle.",
+ "fail": "Das Element besitzt keine widget-Rolle."
+ },
"invalidrole": {
"pass": "ARIA Rolle ist gültig.",
"fail": {
diff --git a/locales/el.json b/locales/el.json
index 4355fafeb1..f8f805c424 100644
--- a/locales/el.json
+++ b/locales/el.json
@@ -539,6 +539,10 @@
},
"fail": "Το στοιχείο δεν έχει καθολικό χαρακτηριστικό ARIA"
},
+ "has-widget-role": {
+ "pass": "Το στοιχείο έχει ρόλο widget.",
+ "fail": "Το στοιχείο δεν έχει ρόλο widget."
+ },
"invalidrole": {
"pass": "Ο ρόλος ARIA είναι έγκυρος",
"fail": {
diff --git a/locales/es.json b/locales/es.json
index 1f5aace76e..7a0b5c0b3f 100644
--- a/locales/es.json
+++ b/locales/es.json
@@ -356,6 +356,10 @@
"plural": "En aria-errormessage, valor ${data.values}`, se debe usar una técnica para anunciar el mensaje (p. ej., aria-live, aria-describedby, role=alert, etc.)"
}
},
+ "has-widget-role": {
+ "pass": "El elemento tiene un rol de widget.",
+ "fail": "El elemento no tiene un rol de widget."
+ },
"invalidrole": {
"pass": "El rol ARIA es válido",
"fail": "El rol debe ser uno de los roles ARIA válidos"
diff --git a/locales/eu.json b/locales/eu.json
index e4130d3756..03b534cfc7 100644
--- a/locales/eu.json
+++ b/locales/eu.json
@@ -356,6 +356,10 @@
"plural": "aria-errormessagen, bailioa ${data.values}`, mezua iragartzeko teknika bat erabili behar da (adibidez: aria-live, aria-describedby, role = alert, etab.)."
}
},
+ "has-widget-role": {
+ "pass": "Elementuak widget rola du.",
+ "fail": "Elementuak ez du widget rolik."
+ },
"invalidrole": {
"pass": "ARIA rola baliozkoa da",
"fail": "Rolak baliozko ARIA rola izan behar du"
diff --git a/locales/fr.json b/locales/fr.json
index b570785184..9bd71725e4 100644
--- a/locales/fr.json
+++ b/locales/fr.json
@@ -519,6 +519,10 @@
},
"fail": "L’élément n’a pas d’attribut ARIA global"
},
+ "has-widget-role": {
+ "pass": "L’élément a un rôle widget.",
+ "fail": "L’élément n’a pas de rôle widget."
+ },
"invalidrole": {
"pass": "Le rôle ARIA est valide",
"fail": {
diff --git a/locales/he.json b/locales/he.json
index 5502bac62d..fd0d2eaa50 100644
--- a/locales/he.json
+++ b/locales/he.json
@@ -529,6 +529,10 @@
},
"fail": "לאלמנט אין תכונת ARIA גלובלית: "
},
+ "has-widget-role": {
+ "pass": "לאלמנט יש תפקיד של וגדג'ט.",
+ "fail": "לאלמנט אין תפקיד של וגדג'ט."
+ },
"invalidrole": {
"pass": "תפקיד ARIA קביל",
"fail": {
diff --git a/locales/it.json b/locales/it.json
index 6aa14e6090..6f1b723259 100644
--- a/locales/it.json
+++ b/locales/it.json
@@ -573,6 +573,10 @@
},
"fail": "L'elemento non ha un attributo ARIA globale"
},
+ "has-widget-role": {
+ "pass": "L'elemento ha un ruolo widget.",
+ "fail": "L'elemento non ha un ruolo widget."
+ },
"invalidrole": {
"pass": "Il ruolo ARIA è valido",
"fail": {
diff --git a/locales/ja.json b/locales/ja.json
index ce1f6e0ebe..161fdba32e 100644
--- a/locales/ja.json
+++ b/locales/ja.json
@@ -575,6 +575,10 @@
},
"fail": "要素にはグローバルなARIA属性が指定されていません"
},
+ "has-widget-role": {
+ "pass": "要素にはwidgetロールが存在します",
+ "fail": "要素にはwidgetロールが存在しません"
+ },
"invalidrole": {
"pass": "ARIAロールが有効です",
"fail": {
diff --git a/locales/ko.json b/locales/ko.json
index d86ffeed5b..9c304d1d7f 100644
--- a/locales/ko.json
+++ b/locales/ko.json
@@ -524,6 +524,10 @@
},
"fail": "엘리먼트가 전역 ARIA 어트리뷰트를 가지고 있지 않습니다."
},
+ "has-widget-role": {
+ "pass": "엘리먼트가 위젯 역할(role)을 가지고 있습니다.",
+ "fail": "엘리먼트가 위젯 역할(role)을 가지고 있지 않습니다."
+ },
"invalidrole": {
"pass": "ARIA 역할(role)이 유효합니다.",
"fail": {
diff --git a/locales/no_NB.json b/locales/no_NB.json
index ed73ec0bb4..4dbf8dbe9d 100644
--- a/locales/no_NB.json
+++ b/locales/no_NB.json
@@ -365,6 +365,10 @@
"plural": "'aria-errormessage'-verdier ${data.values}` skal bruke en metode for å annonsere beskeden (f.eks. 'aria-live', 'aria-describedby', 'role=alert', osv.)"
}
},
+ "has-widget-role": {
+ "pass": "Elementet har en 'widget'-rolle.",
+ "fail": "Elementet har ikke en 'widget'-rolle."
+ },
"invalidrole": {
"pass": "ARIA-rollen er korrekt",
"fail": "Rollen skal være en av de mulige ARIA-roller"
diff --git a/locales/pl.json b/locales/pl.json
index 7c2f2d1f76..1caafcabda 100644
--- a/locales/pl.json
+++ b/locales/pl.json
@@ -575,6 +575,10 @@
},
"fail": "Element nie ma ogólnego atrybutu ARIA"
},
+ "has-widget-role": {
+ "pass": "Element ma rolę widżetu.",
+ "fail": "Element nie ma roli widżetu."
+ },
"invalidrole": {
"pass": "Rola ARIA jest poprawna.",
"fail": {
diff --git a/locales/pt_BR.json b/locales/pt_BR.json
index 68d4cf2da9..404d5ab293 100644
--- a/locales/pt_BR.json
+++ b/locales/pt_BR.json
@@ -504,6 +504,10 @@
},
"fail": "O elemento não tem atributo ARIA global"
},
+ "has-widget-role": {
+ "pass": "Elemento tem um 'role' de 'widget'.",
+ "fail": "Elemento não tem um 'role' de 'widget'."
+ },
"invalidrole": {
"pass": "O ARIA 'role' é válido",
"fail": {
diff --git a/locales/zh_CN.json b/locales/zh_CN.json
index 089cf0ce34..ef5e6876dc 100644
--- a/locales/zh_CN.json
+++ b/locales/zh_CN.json
@@ -576,6 +576,10 @@
},
"fail": "元素没有全局 ARIA 属性"
},
+ "has-widget-role": {
+ "pass": "元素有小部件角色",
+ "fail": "元素没有小部件角色"
+ },
"invalidrole": {
"pass": "ARIA 角色有效",
"fail": {
diff --git a/locales/zh_TW.json b/locales/zh_TW.json
index ba6c50f4c8..37a9d3262b 100644
--- a/locales/zh_TW.json
+++ b/locales/zh_TW.json
@@ -573,6 +573,10 @@
},
"fail": "元素沒有全域 ARIA 屬性"
},
+ "has-widget-role": {
+ "pass": "元素具有小部件角色",
+ "fail": "元素沒有小部件角色"
+ },
"invalidrole": {
"pass": "ARIA 角色有效",
"fail": {
From 9b15ae0bccbe1dccc637c2de13085f6b7da7f74b Mon Sep 17 00:00:00 2001
From: Ava Gaiety W
Date: Mon, 29 Apr 2024 09:00:43 -0500
Subject: [PATCH 12/14] fix(aria-roles): log and status allowed in
focus-order-semantics
extends prior work by accounting for all standards aria roles changes
---
lib/checks/aria/valid-scrollable-semantics-evaluate.js | 4 +++-
.../rules/focus-order-semantics/focus-order-semantics.html | 6 ++++--
.../rules/focus-order-semantics/focus-order-semantics.json | 4 +++-
3 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/lib/checks/aria/valid-scrollable-semantics-evaluate.js b/lib/checks/aria/valid-scrollable-semantics-evaluate.js
index 755cbf4724..fef446f35e 100644
--- a/lib/checks/aria/valid-scrollable-semantics-evaluate.js
+++ b/lib/checks/aria/valid-scrollable-semantics-evaluate.js
@@ -25,10 +25,12 @@ const VALID_ROLES_FOR_SCROLLABLE_REGIONS = {
contentinfo: true,
dialog: true,
form: true,
+ log: true,
main: true,
navigation: true,
region: true,
- search: false
+ search: false,
+ status: true
};
/**
diff --git a/test/integration/rules/focus-order-semantics/focus-order-semantics.html b/test/integration/rules/focus-order-semantics/focus-order-semantics.html
index 296b1cb939..9e8593a408 100644
--- a/test/integration/rules/focus-order-semantics/focus-order-semantics.html
+++ b/test/integration/rules/focus-order-semantics/focus-order-semantics.html
@@ -34,11 +34,13 @@
Valid landmark roles for scrollable containers
+
+
Valid window roles for scrollable containers
-
-
+
+
Valid scrollable HTML tags for scrollable regions, not selected by this
diff --git a/test/integration/rules/focus-order-semantics/focus-order-semantics.json b/test/integration/rules/focus-order-semantics/focus-order-semantics.json
index 0cfe89330d..b9ed3b20c1 100644
--- a/test/integration/rules/focus-order-semantics/focus-order-semantics.json
+++ b/test/integration/rules/focus-order-semantics/focus-order-semantics.json
@@ -14,7 +14,9 @@
["#pass10"],
["#pass11"],
["#pass12"],
- ["#pass13"]
+ ["#pass13"],
+ ["#pass14"],
+ ["#pass15"]
],
"violations": [
["#violation1"],
From 5594d8f1ff45703bed81e4a137afb42b6449d0ee Mon Sep 17 00:00:00 2001
From: Ava Gaiety W
Date: Mon, 29 Apr 2024 12:50:21 -0500
Subject: [PATCH 13/14] fix(aria-roles): target-size tests consider changed
aria roles
last feedback yay
---
.../rules/target-size/target-size.html | 35 +++++++++++++++++++
.../rules/target-size/target-size.json | 7 ++++
2 files changed, 42 insertions(+)
diff --git a/test/integration/rules/target-size/target-size.html b/test/integration/rules/target-size/target-size.html
index 3c4b0be940..d3cef72ee3 100644
--- a/test/integration/rules/target-size/target-size.html
+++ b/test/integration/rules/target-size/target-size.html
@@ -28,6 +28,41 @@