Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(rule): aria-allowed-role #945

Merged
merged 38 commits into from
Aug 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
63c947b
feat: initial work for new rule > aria-allowed-role
jeeyyy Jun 6, 2018
7298f15
fix: aria-allowed-role rule
jeeyyy Jun 7, 2018
ee23a9d
chore: merge from > develop
jeeyyy Jun 7, 2018
03af3af
fix: integration test fixes.
jeeyyy Jun 7, 2018
9646b5b
chore: merge from > develop
jeeyyy Jun 7, 2018
5a040ef
refactor: amends based on review.
jeeyyy Jun 8, 2018
4642828
fix: merge from develop
jeeyyy Jun 25, 2018
099c8d1
fix: update aria.isAllowedRole check to be self sufficient.
jeeyyy Jun 26, 2018
75331d1
fix: merge from develop
jeeyyy Jun 29, 2018
56df2df
fix: update checks based on review comments
jeeyyy Jul 4, 2018
3cbd477
fix: editorial fixes based on review
jeeyyy Jul 4, 2018
604b4ea
fix: refactored roleMap to have allowedElements
jeeyyy Jul 6, 2018
2570ae1
test: update integration tests
jeeyyy Jul 9, 2018
788dca2
test: deprecate old test unncessary due to refactor
jeeyyy Jul 9, 2018
078c75c
fix: merge from develop
jeeyyy Jul 9, 2018
f725e21
fix: refactor based on code review
jeeyyy Jul 16, 2018
256db5d
test: update unit/ integration tests
jeeyyy Jul 17, 2018
5b44d65
Merge branch 'develop' into new-rule-aria-allowed-role
jeeyyy Jul 17, 2018
79b00e0
refactor: change pass/ fail messages to respect plurals
jeeyyy Jul 17, 2018
b893dc7
refactor: update rule description
jeeyyy Jul 18, 2018
4c3261d
Merge branch 'develop' into new-rule-aria-allowed-role
jeeyyy Jul 28, 2018
9b686ea
Merge branch 'develop' into new-rule-aria-allowed-role
jeeyyy Jul 30, 2018
5cd376a
fix: updates based on review
jeeyyy Jul 31, 2018
8384f65
test: add more integration tests
jeeyyy Jul 31, 2018
9e31d79
Merge branch 'develop' into new-rule-aria-allowed-role
jeeyyy Jul 31, 2018
257a789
fix: swap node.matches with axe.utils.matchesSelector method
jeeyyy Aug 3, 2018
5ecb795
chore: Merge branch 'develop' into new-rule-aria-allowed-role
jeeyyy Aug 3, 2018
a6d5bba
Merge branch 'develop' into new-rule-aria-allowed-role
jeeyyy Aug 3, 2018
02c15cf
fix: updates based on review
jeeyyy Aug 6, 2018
3502365
Merge branch 'develop' into new-rule-aria-allowed-role
jeeyyy Aug 6, 2018
d69a797
Merge branch 'develop' into new-rule-aria-allowed-role
jeeyyy Aug 7, 2018
87929c7
fix: improve test and refactor based on review
jeeyyy Aug 8, 2018
7a0df2c
Merge branch 'develop' into new-rule-aria-allowed-role
jeeyyy Aug 8, 2018
2d86762
fix: enhance no role and any role as per aria spec
jeeyyy Aug 11, 2018
8f16a86
test: add tests for aria-allowed-role related functions
jeeyyy Aug 11, 2018
d72a247
Merge branch 'develop' into new-rule-aria-allowed-role
jeeyyy Aug 12, 2018
ac0ba14
test: fix tests allowedElement object structure
jeeyyy Aug 14, 2018
2777dbc
chore: merge from develop
jeeyyy Aug 16, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/rule-descriptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
| accesskeys | Ensures every accesskey attribute value is unique | Serious | best-practice, cat.keyboard | true |
| area-alt | Ensures <area> elements of image maps have alternate text | Critical | cat.text-alternatives, wcag2a, wcag111, section508, section508.22.a | true |
| aria-allowed-attr | Ensures ARIA attributes are allowed for an element's role | Critical | cat.aria, wcag2a, wcag412 | true |
| aria-allowed-role | Ensures role attribute has an appropriate value for the element | Minor | cat.aria, best-practice | true |
| aria-dpub-role-fallback | Ensures unsupported DPUB roles are only used on elements with implicit fallback roles | Moderate | cat.aria, wcag2a, wcag131 | true |
| aria-hidden-body | Ensures aria-hidden='true' is not present on the document body. | Critical | cat.aria, wcag2a, wcag412 | true |
| aria-required-attr | Ensures elements with ARIA roles have all required ARIA attributes | Critical | cat.aria, wcag2a, wcag412 | true |
Expand Down
23 changes: 23 additions & 0 deletions lib/checks/aria/aria-allowed-role.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Implements allowed roles defined at:
* https://www.w3.org/TR/html-aria/#docconformance
* https://www.w3.org/TR/SVG2/struct.html#implicit-aria-semantics
*/
const { allowImplicit = true, ignoredTags = [] } = options || {};
const tagName = node.nodeName.toUpperCase();

// check if the element should be ignored, by an user setting
if (ignoredTags.map(t => t.toUpperCase()).includes(tagName)) {
return true;
}

const unallowedRoles = axe.commons.aria.getElementUnallowedRoles(
node,
allowImplicit
);

if (unallowedRoles.length) {
this.data(unallowedRoles);
return false;
}
return true;
15 changes: 15 additions & 0 deletions lib/checks/aria/aria-allowed-role.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"id": "aria-allowed-role",
"evaluate": "aria-allowed-role.js",
"options": {
"allowImplicit": true,
"ignoredTags": []
},
"metadata": {
"impact": "minor",
"messages": {
"pass": "ARIA role is allowed for given element",
"fail": "role{{=it.data && it.data.length > 1 ? 's' : ''}} {{=it.data.join(', ')}} {{=it.data && it.data.length > 1 ? 'are' : ' is'}} not allowed for given element"
}
}
}
80 changes: 80 additions & 0 deletions lib/commons/aria/get-element-unallowed-roles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/* global aria */
/**
* gets all unallowed roles for a given node
* @method getElementUnallowedRoles
* @param {Object} node HTMLElement to validate
* @param {String} tagName tag name of a node
* @param {String} allowImplicit option to allow implicit roles, defaults to true
* @return {Array<String>} retruns an array of roles that are not allowed on the given node
*/
aria.getElementUnallowedRoles = function getElementUnallowedRoles(
node,
allowImplicit
) {
/**
* Get roles applied to a given node
* @param {HTMLElement} node HTMLElement
* @return {Array<String>} return an array of roles applied to the node, if no roles, return an empty array.
*/
// TODO: not moving this to outer namespace yet, work with wilco to see overlap with his PR(WIP) - aria.getRole
function getRoleSegments(node) {
let roles = [];
if (!node) {
return roles;
}
if (node.hasAttribute('role')) {
const nodeRoles = axe.utils.tokenList(
node.getAttribute('role').toLowerCase()
);
roles = roles.concat(nodeRoles);
}
if (node.hasAttributeNS('http://www.idpf.org/2007/ops', 'type')) {
const epubRoles = axe.utils
.tokenList(
node
.getAttributeNS('http://www.idpf.org/2007/ops', 'type')
.toLowerCase()
)
.map(role => `doc-${role}`);
roles = roles.concat(epubRoles);
}
return roles;
}

const tagName = node.nodeName.toUpperCase();

// by pass custom elements
if (!axe.utils.isHtmlElement(node)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we shouldn't move this into the matcher instead; make these nodes inapplicable instead of passing them. Seems slightly more appropriate. Maybe just create a ticket for it?

return [];
}

const roleSegments = getRoleSegments(node);
const implicitRole = axe.commons.aria.implicitRole(node);

// stores all roles that are not allowed for a specific element most often an element only has one explicit role
const unallowedRoles = roleSegments.filter(role => {
if (!axe.commons.aria.isValidRole(role)) {
// do not check made-up/ fake roles
return false;
}

// check if an implicit role may be set explicit following a setting
if (!allowImplicit && role === implicitRole) {
// edge case: setting implicit role row on tr element is allowed when child of table[role='grid']
if (
!(
role === 'row' &&
tagName === 'TR' &&
axe.utils.matchesSelector(node, 'table[role="grid"] > tr')
)
) {
return true;
}
}
if (!aria.isAriaRoleAllowedOnElement(node, role)) {
return true;
}
});

return unallowedRoles;
};
Loading