Bug 1582409 - ensure that we handle SVGs with role=img correctly when running text-label checks. r=nchevobbe

Differential Revision: https://phabricator.services.mozilla.com/D55976

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Yura Zenevich 2019-12-05 16:21:23 +00:00
parent 826897618a
commit b0376a86df
5 changed files with 143 additions and 22 deletions

View File

@ -30,6 +30,13 @@ loader.lazyRequireGetter(
true
);
loader.lazyRequireGetter(
this,
"getAriaRoles",
"devtools/server/actors/utils/accessibility",
true
);
const {
accessibility: {
AUDIT_TYPE: { KEYBOARD },
@ -127,27 +134,6 @@ function isInvalidNode(node) {
);
}
/**
* Get role attribute for an accessible object if specified for its
* corresponding DOMNode.
*
* @param {nsIAccessible} accessible
* Accessible for which to determine its role attribute value.
*
* @returns {null|String}
* Role attribute value if specified.
*/
function getAriaRoles(accessible) {
try {
return accessible.attributes.getStringProperty("xml-roles");
} catch (e) {
// No xml-roles. nsPersistentProperties throws if the attribute for a key
// is not found.
}
return null;
}
/**
* Determine if accessible is focusable with the keyboard.
*

View File

@ -5,6 +5,14 @@
"use strict";
const { Ci } = require("chrome");
loader.lazyRequireGetter(
this,
"getAriaRoles",
"devtools/server/actors/utils/accessibility",
true
);
const {
accessibility: {
AUDIT_TYPE: { TEXT_LABEL },
@ -137,6 +145,23 @@ const dialogRule = shouldHaveNonEmptyNameRule.bind(null, DIALOG_NO_NAME);
*/
const imageRule = function(accessible) {
const name = getAccessibleName(accessible);
const { DOMNode } = accessible;
if (
DOMNode instanceof DOMNode.ownerGlobal.SVGElement &&
DOMNode.ownerSVGElement
) {
let ownerSVGAccessible = accessible.parent;
while (ownerSVGAccessible.DOMNode.ownerSVGElement) {
ownerSVGAccessible = ownerSVGAccessible.parent;
}
const ariaRoles = getAriaRoles(ownerSVGAccessible);
if (ariaRoles && ariaRoles.includes("img")) {
// Do not require a defined name if a wrapping SVG has a role="img".
return null;
}
}
return name != null ? null : { score: FAIL, issue: IMAGE_NO_NAME };
};

View File

@ -103,7 +103,29 @@ function isWebRenderEnabled(win) {
return false;
}
/**
* Get role attribute for an accessible object if specified for its
* corresponding DOMNode.
*
* @param {nsIAccessible} accessible
* Accessible for which to determine its role attribute value.
*
* @returns {null|String}
* Role attribute value if specified.
*/
function getAriaRoles(accessible) {
try {
return accessible.attributes.getStringProperty("xml-roles");
} catch (e) {
// No xml-roles. nsPersistentProperties throws if the attribute for a key
// is not found.
}
return null;
}
exports.getAriaRoles = getAriaRoles;
exports.isDefunct = isDefunct;
exports.isWebRenderEnabled = isWebRenderEnabled;
exports.loadSheetForBackgroundCalculation = loadSheetForBackgroundCalculation;
exports.removeSheetForBackgroundCalculation = removeSheetForBackgroundCalculation;
exports.isWebRenderEnabled = isWebRenderEnabled;

View File

@ -1062,6 +1062,66 @@ add_task(async function() {
{ score: FAIL, issue: TOOLBAR_NO_NAME },
],
["Non-unique aria toolbar with aria-labelledby", "#toolbar-4", null],
["SVGElement with role=img that has a title", "#svg-1", null],
[
"SVGElement with no name and with ownerSVGElement with role=img that has a title",
"#svg-2",
null,
],
["SVGElement without role=img that has a title", "#svg-3", null],
[
"SVGElement with no name and with ownerSVGElement without role=img",
"#svg-4",
{ score: FAIL, issue: IMAGE_NO_NAME },
],
[
"SVGElement with role=img and no name",
"#svg-5",
{ score: FAIL, issue: IMAGE_NO_NAME },
],
[
"SVGElement with no name and with ownerSVGElement with role=img",
"#svg-6",
null,
],
[
"SVGElement with no name",
"#svg-7",
{ score: FAIL, issue: IMAGE_NO_NAME },
],
[
"SVGElement with no name and with ownerSVGElement with no name",
"#svg-8",
{ score: FAIL, issue: IMAGE_NO_NAME },
],
["SVGElement with a name", "#svg-9", null],
[
"SVGElement with a name and with ownerSVGElement with a name",
"#svg-10",
null,
],
["SVGElement with a title", "#svg-11", null],
[
"SVGElement with a name and with ownerSVGElement with a title",
"#svg-12",
null,
],
["SVGElement with role=img that has a title", "#svg-13", null],
[
"SVGElement with a name and with ownerSVGElement with role=img that has a title",
"#svg-14",
null,
],
[
"SVGElement with role=img and no title",
"#svg-15",
{ score: FAIL, issue: IMAGE_NO_NAME },
],
[
"SVGElement with a name and with ownerSVGElement with role=img and no title",
"#svg-16",
null,
],
];
for (const [description, selector, expected] of tests) {

View File

@ -433,5 +433,33 @@
<span id="toolbar-3" role="toolbar" aria-labelledby="toolbar-3-label"></span>
<p id="toolbar-4-label">Toolbar</p>
<span id="toolbar-4" role="toolbar" aria-labelledby="toolbar-4-label"></span>
<svg id="svg-1" role="img" viewbox="0 0 100 10" height="10px">
<title id="siteLogoTitle">Site Logo</title>
<rect id="svg-2" x="0" y="00" width="100" height="10" fill="red"></rect>
</svg>
<svg id="svg-3" viewbox="0 0 100 10" height="10px">
<title id="siteLogoTitle">Site Logo</title>
<rect id="svg-4" x="0" y="00" width="100" height="10" fill="red"></rect>
</svg>
<svg id="svg-5" role="img" viewbox="0 0 100 10" height="10px">
<rect id="svg-6" x="0" y="00" width="100" height="10" fill="red"></rect>
</svg>
<svg id="svg-7" viewbox="0 0 100 10" height="10px">
<rect id="svg-8" x="0" y="00" width="100" height="10" fill="red"></rect>
</svg>
<svg id="svg-9" aria-label="foo" viewbox="0 0 100 10" height="10px">
<rect id="svg-10" aria-label="bar" x="0" y="00" width="100" height="10" fill="red"></rect>
</svg>
<svg id="svg-11" viewbox="0 0 100 10" height="10px">
<title id="siteLogoTitle">Site Logo</title>
<rect id="svg-12" aria-label="foo" x="0" y="00" width="100" height="10" fill="red"></rect>
</svg>
<svg id="svg-13" role="img" viewbox="0 0 100 10" height="10px">
<title id="siteLogoTitle">Site Logo</title>
<rect aria-label="foo" id="svg-14" x="0" y="00" width="100" height="10" fill="red"></rect>
</svg>
<svg id="svg-15" role="img" viewbox="0 0 100 10" height="10px">
<rect aria-label="foo" id="svg-16" x="0" y="00" width="100" height="10" fill="red"></rect>
</svg>
</body>
</html>