Skip to content

Commit facd65f

Browse files
committed
fix(aria-roles): exception for focus-order-semantics
add `window` to has-widget-role, renamed Refs: #4371
1 parent 417e6b1 commit facd65f

File tree

7 files changed

+148
-596
lines changed

7 files changed

+148
-596
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { getRoleType } from '../../commons/aria';
2+
3+
const acceptedRoles = {
4+
widget: true,
5+
composite: true,
6+
window: true
7+
};
8+
9+
/**
10+
* Check if an elements `role` attribute uses any widget, composite, window abstract role values.
11+
*
12+
* Widget roles are taken from the `ariaRoles` standards object from the roles `type` property.
13+
*
14+
* @memberof checks
15+
* @return {Boolean} True if the element uses a `widget`, `composite`, or `window` abstract role (type). False otherwise.
16+
*/
17+
// # TODO: change to abstract role for widget and window
18+
function hasWidgetOrWindowRoleEvaluate(node) {
19+
const role = node.getAttribute('role');
20+
if (role === null) {
21+
return false;
22+
}
23+
return !!acceptedRoles[getRoleType(role)];
24+
}
25+
26+
export default hasWidgetOrWindowRoleEvaluate;

lib/checks/aria/has-widget-role.json renamed to lib/checks/aria/has-widget-or-window-role.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"id": "has-widget-role",
3-
"evaluate": "has-widget-role-evaluate",
2+
"id": "has-widget-or-window-role",
3+
"evaluate": "has-widget-or-window-role-evaluate",
44
"options": [],
55
"metadata": {
66
"impact": "minor",

lib/checks/aria/has-widget-role-evaluate.js

Lines changed: 0 additions & 20 deletions
This file was deleted.

lib/rules/focus-order-semantics.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99
"help": "Elements in the focus order should have an appropriate role"
1010
},
1111
"all": [],
12-
"any": ["has-widget-role", "valid-scrollable-semantics"],
12+
"any": ["has-widget-or-window-role", "valid-scrollable-semantics"],
1313
"none": []
1414
}

locales/_template.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@
576576
},
577577
"fail": "Element does not have global ARIA attribute"
578578
},
579-
"has-widget-role": {
579+
"has-widget-or-window-role": {
580580
"pass": "Element has a widget role.",
581581
"fail": "Element does not have a widget role."
582582
},
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
describe('has-widget-or-window-role', function () {
2+
'use strict';
3+
4+
let node;
5+
const fixture = document.getElementById('fixture');
6+
const checkContext = axe.testUtils.MockCheckContext();
7+
const evaluate = currentNode =>
8+
axe.testUtils
9+
.getCheckEvaluate('has-widget-or-window-role')
10+
.call(checkContext, currentNode);
11+
const roles = {
12+
widget: {
13+
button: true,
14+
checkbox: true,
15+
gridcell: true,
16+
link: true,
17+
menuitem: true,
18+
menuitemcheckbox: true,
19+
menuitemradio: true,
20+
option: true,
21+
progressbar: true,
22+
radio: true,
23+
scrollbar: true,
24+
searchbox: true,
25+
slider: true,
26+
spinbutton: true,
27+
switch: true,
28+
tab: true,
29+
tabpanel: true,
30+
textbox: true,
31+
treeitem: true
32+
},
33+
composite: {
34+
combobox: true,
35+
grid: true,
36+
listbox: true,
37+
menu: true,
38+
menubar: true,
39+
radiogroup: true,
40+
tablist: true,
41+
tree: true,
42+
treegrid: true,
43+
44+
application: false,
45+
article: false,
46+
cell: false,
47+
columnheader: false,
48+
definition: false,
49+
directory: false,
50+
document: false,
51+
feed: false,
52+
figure: false,
53+
group: false,
54+
heading: false,
55+
img: false,
56+
list: false,
57+
listitem: false,
58+
math: false,
59+
none: false,
60+
note: false,
61+
presentation: false,
62+
row: false,
63+
rowgroup: false,
64+
rowheader: false,
65+
table: false,
66+
term: false,
67+
toolbar: false
68+
},
69+
window: {
70+
alertdialog: true,
71+
dialog: true
72+
},
73+
landmark: {
74+
banner: false,
75+
complimentary: false,
76+
contentinfo: false,
77+
form: false,
78+
name: false,
79+
navigation: false,
80+
region: false,
81+
search: false
82+
}
83+
};
84+
85+
afterEach(function () {
86+
node.innerHTML = '';
87+
checkContext._data = null;
88+
});
89+
90+
it('should return false for elements with no role', function () {
91+
node = document.createElement('div');
92+
fixture.appendChild(node);
93+
94+
assert.isFalse(evaluate(node));
95+
});
96+
97+
it('should return false for elements with nonsensical roles', function () {
98+
node = document.createElement('div');
99+
node.setAttribute('role', 'buttonbuttonbutton');
100+
fixture.appendChild(node);
101+
102+
assert.isFalse(evaluate(node));
103+
});
104+
105+
Object.keys(roles).forEach(category => {
106+
describe(category, function () {
107+
Object.keys(roles[category]).forEach(role => {
108+
it(`should return ${roles[category][role]} for role="${role}"`, function () {
109+
node = document.createElement('div');
110+
node.setAttribute('role', role);
111+
fixture.appendChild(node);
112+
113+
assert.equal(evaluate(node), roles[category][role]);
114+
});
115+
});
116+
});
117+
});
118+
});

0 commit comments

Comments
 (0)