зеркало из https://github.com/mozilla/gecko-dev.git
Bug 854796: Anchor, area elements without href shouldn't have link role, r=Jamie,devtools-reviewers
Per the HTML-AAM spec, a and area elements without href attributes should have generic roles. This revision implements this preference by creating hypertext accessibles when said elements lack href attributes (or click listeners). A byproduct of this change is recognizing that a elements have no intrinsic role mapping; they could be generics or links. This revision handles situations where href or click listeners might appear or dissapear, and recreates the accessibles when necessary. Since image map areas are handled by their containing image maps, this revision specializes HTMLAreaAccessible::NativeRole to account for the discrepancy that we can't account for in the markup map. This revision also changes the relevant WPT test expectations, updates existing tests that this change affects, and adds tests to verify that changing href and click listeners dynamically changes the role appropriately. Differential Revision: https://phabricator.services.mozilla.com/D183550
This commit is contained in:
Родитель
ad3cf4e0b8
Коммит
f8b9470054
|
@ -8,6 +8,12 @@
|
|||
MARKUPMAP(
|
||||
a,
|
||||
[](Element* aElement, LocalAccessible* aContext) -> LocalAccessible* {
|
||||
// An anchor element without an href attribute and without a click
|
||||
// listener should be a generic.
|
||||
if (!aElement->HasAttr(nsGkAtoms::href) &&
|
||||
!nsCoreUtils::HasClickListener(aElement)) {
|
||||
return new HyperTextAccessibleWrap(aElement, aContext->Document());
|
||||
}
|
||||
// Only some roles truly enjoy life as HTMLLinkAccessibles, for
|
||||
// details see closed bug 494807.
|
||||
const nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aElement);
|
||||
|
@ -18,7 +24,7 @@ MARKUPMAP(
|
|||
|
||||
return new HTMLLinkAccessible(aElement, aContext->Document());
|
||||
},
|
||||
roles::LINK)
|
||||
0)
|
||||
|
||||
MARKUPMAP(abbr, New_HyperText, 0)
|
||||
|
||||
|
|
|
@ -442,17 +442,33 @@ nsAccessibilityService::ListenersChanged(nsIArray* aEventChanges) {
|
|||
content == document->DocumentNode()->GetRootElement())) {
|
||||
acc = document;
|
||||
}
|
||||
if (!acc && content->IsElement() &&
|
||||
content->AsElement()->IsHTMLElement(nsGkAtoms::area)) {
|
||||
// For area accessibles, we have to recreate the entire image map,
|
||||
// since the image map accessible manages the tree itself. The click
|
||||
// listener change may require us to update the role for the
|
||||
// accessible associated with the area element.
|
||||
LocalAccessible* areaAcc =
|
||||
document->GetAccessibleEvenIfNotInMap(content);
|
||||
if (areaAcc && areaAcc->LocalParent()) {
|
||||
document->RecreateAccessible(areaAcc->LocalParent()->GetContent());
|
||||
}
|
||||
}
|
||||
if (!acc && nsCoreUtils::HasClickListener(content)) {
|
||||
// Create an accessible for a inaccessible element having click event
|
||||
// handler.
|
||||
document->ContentInserted(content, content->GetNextSibling());
|
||||
} else if (acc) {
|
||||
if (acc->IsHTMLLink() && !acc->AsHTMLLink()->IsLinked()) {
|
||||
// Notify of a LINKED state change if an HTML link gets a click
|
||||
// listener but does not have an href attribute.
|
||||
RefPtr<AccEvent> linkedChangeEvent =
|
||||
new AccStateChangeEvent(acc, states::LINKED);
|
||||
document->FireDelayedEvent(linkedChangeEvent);
|
||||
if ((acc->IsHTMLLink() && !acc->AsHTMLLink()->IsLinked()) ||
|
||||
(content->IsElement() &&
|
||||
content->AsElement()->IsHTMLElement(nsGkAtoms::a) &&
|
||||
!acc->IsHTMLLink())) {
|
||||
// An HTML link without an href attribute should have a generic
|
||||
// role, unless it has a click listener. Since we might have gained
|
||||
// or lost a click listener here, recreate the accessible so that we
|
||||
// can create the correct type of accessible. If it was a link, it
|
||||
// may no longer be one. If it wasn't, it may become one.
|
||||
document->RecreateAccessible(content);
|
||||
}
|
||||
|
||||
// A click listener change might mean losing or gaining an action.
|
||||
|
|
|
@ -1803,6 +1803,33 @@ bool DocAccessible::UpdateAccessibleOnAttrChange(dom::Element* aElement,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::href &&
|
||||
!nsCoreUtils::HasClickListener(aElement)) {
|
||||
// If the href is added or removed for a or area elements without click
|
||||
// listeners, we need to recreate the accessible since the role might have
|
||||
// changed. Without an href or click listener, the accessible must be a
|
||||
// generic.
|
||||
if (aElement->IsHTMLElement(nsGkAtoms::a)) {
|
||||
LocalAccessible* acc = GetAccessible(aElement);
|
||||
if (!acc) {
|
||||
return false;
|
||||
}
|
||||
if (acc->IsHTMLLink() != aElement->HasAttr(nsGkAtoms::href)) {
|
||||
RecreateAccessible(aElement);
|
||||
return true;
|
||||
}
|
||||
} else if (aElement->IsHTMLElement(nsGkAtoms::area)) {
|
||||
// For area accessibles, we have to recreate the entire image map, since
|
||||
// the image map accessible manages the tree itself.
|
||||
LocalAccessible* areaAcc = GetAccessibleEvenIfNotInMap(aElement);
|
||||
if (!areaAcc || !areaAcc->LocalParent()) {
|
||||
return false;
|
||||
}
|
||||
RecreateAccessible(areaAcc->LocalParent()->GetContent());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (aElement->IsHTMLElement(nsGkAtoms::img) && aAttribute == nsGkAtoms::alt) {
|
||||
// If alt text changes on an img element, we may want to create or remove an
|
||||
// accessible for that img.
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "EventTree.h"
|
||||
#include "Role.h"
|
||||
|
||||
#include "nsCoreUtils.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsImageFrame.h"
|
||||
#include "nsImageMap.h"
|
||||
|
@ -105,6 +106,19 @@ HTMLAreaAccessible::HTMLAreaAccessible(nsIContent* aContent,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// HTMLAreaAccessible: LocalAccessible
|
||||
|
||||
role HTMLAreaAccessible::NativeRole() const {
|
||||
// A link element without an href attribute and without a click listener
|
||||
// should be reported as a generic.
|
||||
if (mContent->IsElement()) {
|
||||
dom::Element* element = mContent->AsElement();
|
||||
if (!element->HasAttr(nsGkAtoms::href) &&
|
||||
!nsCoreUtils::HasClickListener(element)) {
|
||||
return roles::TEXT;
|
||||
}
|
||||
}
|
||||
return HTMLLinkAccessible::NativeRole();
|
||||
}
|
||||
|
||||
ENameValueFlag HTMLAreaAccessible::NativeName(nsString& aName) const {
|
||||
ENameValueFlag nameFlag = LocalAccessible::NativeName(aName);
|
||||
if (!aName.IsEmpty()) return nameFlag;
|
||||
|
|
|
@ -61,6 +61,9 @@ class HTMLAreaAccessible final : public HTMLLinkAccessible {
|
|||
return false;
|
||||
}
|
||||
|
||||
// LocalAccessible
|
||||
virtual role NativeRole() const override;
|
||||
|
||||
protected:
|
||||
// LocalAccessible
|
||||
virtual ENameValueFlag NativeName(nsString& aName) const override;
|
||||
|
|
|
@ -92,6 +92,10 @@ addAccessibleTask(
|
|||
src="http://example.com/a11y/accessible/tests/mochitest/moz.png">
|
||||
</a>
|
||||
|
||||
<a id="link4" onmousedown=""></a>
|
||||
<a id="link5" onclick=""></a>
|
||||
<a id="link6" onmouseup=""></a>
|
||||
|
||||
<div>
|
||||
<label for="TextBox_t2" id="label1">
|
||||
<span>Explicit</span>
|
||||
|
@ -117,6 +121,9 @@ addAccessibleTask(
|
|||
await _testActions("link2", ["click"], gClickEvents);
|
||||
await _testActions("link3", ["jump"], gClickEvents);
|
||||
await _testActions("link3img", ["click ancestor"], gClickEvents);
|
||||
await _testActions("link4", ["click"], gClickEvents);
|
||||
await _testActions("link5", ["click"], gClickEvents);
|
||||
await _testActions("link6", ["click"], gClickEvents);
|
||||
await _testActions("label1", ["click"], gClickEvents);
|
||||
await _testActions("p_in_clickable_div", ["click ancestor"], gClickEvents);
|
||||
|
||||
|
@ -171,16 +178,24 @@ addAccessibleTask(
|
|||
await _testActions("onclick_img", ["showlongdesc"]);
|
||||
|
||||
// Remove 'href' from link and test linkable child
|
||||
const link1Acc = findAccessibleChildByID(docAcc, "link1");
|
||||
let link1Acc = findAccessibleChildByID(docAcc, "link1");
|
||||
is(
|
||||
link1Acc.firstChild.getActionName(0),
|
||||
"click ancestor",
|
||||
"linkable child has click ancestor action"
|
||||
);
|
||||
let onRecreation = waitForEvents({
|
||||
expected: [
|
||||
[EVENT_HIDE, link1Acc],
|
||||
[EVENT_SHOW, "link1"],
|
||||
],
|
||||
});
|
||||
await invokeContentTask(browser, [], () => {
|
||||
let link1 = content.document.getElementById("link1");
|
||||
link1.removeAttribute("href");
|
||||
});
|
||||
await onRecreation;
|
||||
link1Acc = findAccessibleChildByID(docAcc, "link1");
|
||||
await untilCacheIs(() => link1Acc.actionCount, 0, "link has no actions");
|
||||
is(link1Acc.firstChild.actionCount, 0, "linkable child's actions removed");
|
||||
|
||||
|
|
|
@ -338,6 +338,7 @@ const markupTests = [
|
|||
<span id="l1">test2</span>
|
||||
<span id="l2">test3</span>
|
||||
<a id="a"
|
||||
href=""
|
||||
aria-label="test1"
|
||||
aria-labelledby="l1 l2"
|
||||
title="test4">test5</a>`,
|
||||
|
@ -350,6 +351,7 @@ const markupTests = [
|
|||
<span id="l1">test2</span>
|
||||
<span id="l2">test3</span>
|
||||
<a id="a-img"
|
||||
href=""
|
||||
aria-label="test1"
|
||||
aria-labelledby="l1 l2"
|
||||
title="test4"><img alt="test5"/></a>`,
|
||||
|
|
|
@ -280,7 +280,7 @@ addAccessibleTask(
|
|||
addAccessibleTask(
|
||||
`<a id="link" href="https://example.com/">Test</a>`,
|
||||
async function (browser, docAcc) {
|
||||
const link = findAccessibleChildByID(docAcc, "link");
|
||||
let link = findAccessibleChildByID(docAcc, "link");
|
||||
is(link.value, "https://example.com/", "link initial value correct");
|
||||
const textLeaf = link.firstChild;
|
||||
is(textLeaf.value, "https://example.com/", "link initial value correct");
|
||||
|
@ -294,11 +294,27 @@ addAccessibleTask(
|
|||
);
|
||||
|
||||
info("Removing link href");
|
||||
let onRecreation = waitForEvents({
|
||||
expected: [
|
||||
[EVENT_HIDE, link],
|
||||
[EVENT_SHOW, "link"],
|
||||
],
|
||||
});
|
||||
await invokeSetAttribute(browser, "link", "href");
|
||||
await onRecreation;
|
||||
link = findAccessibleChildByID(docAcc, "link");
|
||||
await untilCacheIs(() => link.value, "", "link value empty after removal");
|
||||
|
||||
info("Setting link href");
|
||||
onRecreation = waitForEvents({
|
||||
expected: [
|
||||
[EVENT_HIDE, link],
|
||||
[EVENT_SHOW, "link"],
|
||||
],
|
||||
});
|
||||
await invokeSetAttribute(browser, "link", "href", "https://example.com/");
|
||||
await onRecreation;
|
||||
link = findAccessibleChildByID(docAcc, "link");
|
||||
await untilCacheIs(
|
||||
() => link.value,
|
||||
"https://example.com/",
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
</head>
|
||||
<body id="body">
|
||||
<div id="container1"> <img src="http://example.com/a11y/accessible/tests/mochitest/moz.png"> <img id="img1" src="http://example.com/a11y/accessible/tests/mochitest/moz.png"> <img src="http://example.com/a11y/accessible/tests/mochitest/moz.png"> </div>
|
||||
<div id="container2-parent"> <a id="container2"></a> <a><img src="http://example.com/a11y/accessible/tests/mochitest/moz.png"></a> </div>
|
||||
<div id="container2-parent"> <a id="container2" href=""></a> <a href=""><img src="http://example.com/a11y/accessible/tests/mochitest/moz.png"></a> </div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -39,18 +39,6 @@ addAccessibleTask(
|
|||
}
|
||||
);
|
||||
|
||||
function waitForLinkedChange(id, isEnabled) {
|
||||
return waitForEvent(EVENT_STATE_CHANGE, e => {
|
||||
e.QueryInterface(nsIAccessibleStateChangeEvent);
|
||||
return (
|
||||
e.state == STATE_LINKED &&
|
||||
!e.isExtraState &&
|
||||
isEnabled == e.isEnabled &&
|
||||
id == getAccessibleDOMNodeID(e.accessible)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test linked vs unlinked anchor tags
|
||||
*/
|
||||
|
@ -92,36 +80,39 @@ addAccessibleTask(
|
|||
"bare <a> gets correct group role"
|
||||
);
|
||||
|
||||
let stateChanged = waitForLinkedChange("link1", false);
|
||||
let onRecreation = waitForEvent(EVENT_SHOW, "link1");
|
||||
await SpecialPowers.spawn(browser, [], () => {
|
||||
content.document.getElementById("link1").removeAttribute("href");
|
||||
});
|
||||
await stateChanged;
|
||||
await onRecreation;
|
||||
link1 = getNativeInterface(accDoc, "link1");
|
||||
is(
|
||||
link1.getAttributeValue("AXRole"),
|
||||
"AXGroup",
|
||||
"<a> stripped from href gets group role"
|
||||
);
|
||||
|
||||
stateChanged = waitForLinkedChange("link2", false);
|
||||
onRecreation = waitForEvent(EVENT_SHOW, "link2");
|
||||
await SpecialPowers.spawn(browser, [], () => {
|
||||
content.document.getElementById("link2").removeAttribute("onclick");
|
||||
});
|
||||
await stateChanged;
|
||||
await onRecreation;
|
||||
link2 = getNativeInterface(accDoc, "link2");
|
||||
is(
|
||||
link2.getAttributeValue("AXRole"),
|
||||
"AXGroup",
|
||||
"<a> stripped from onclick gets group role"
|
||||
);
|
||||
|
||||
stateChanged = waitForLinkedChange("link3", true);
|
||||
onRecreation = waitForEvent(EVENT_SHOW, "link3");
|
||||
await SpecialPowers.spawn(browser, [], () => {
|
||||
content.document
|
||||
.getElementById("link3")
|
||||
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
|
||||
.setAttribute("href", "http://example.com");
|
||||
});
|
||||
await stateChanged;
|
||||
await onRecreation;
|
||||
link3 = getNativeInterface(accDoc, "link3");
|
||||
is(
|
||||
link3.getAttributeValue("AXRole"),
|
||||
"AXLink",
|
||||
|
@ -212,7 +203,7 @@ addAccessibleTask(
|
|||
link5
|
||||
.getAttributeValue("AXLinkedUIElements")[0]
|
||||
.getAttributeValue("AXTitle"),
|
||||
"I have a name",
|
||||
"",
|
||||
"Link 5 is linked to a named element"
|
||||
);
|
||||
is(
|
||||
|
|
|
@ -14,6 +14,7 @@ skip-if = true || (verify && !debug && (os == 'linux')) #Bug 1445513
|
|||
[browser_css_content_visibility.js]
|
||||
[browser_general.js]
|
||||
[browser_lazy_tabs.js]
|
||||
[browser_link.js]
|
||||
[browser_searchbar.js]
|
||||
[browser_shadowdom.js]
|
||||
[browser_test_nsIAccessibleDocument_URL.js]
|
||||
|
|
|
@ -0,0 +1,208 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/* import-globals-from ../../mochitest/role.js */
|
||||
loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });
|
||||
|
||||
/**
|
||||
* Verify that an anchor element reports a generic role without an href
|
||||
* attribute and reports a LINK role with it present. Verify that these roles
|
||||
* change as the attribute appears and disappears.
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`
|
||||
<a id="link">test</a>
|
||||
`,
|
||||
async function (browser, accDoc) {
|
||||
let link = findAccessibleChildByID(accDoc, "link");
|
||||
is(link.role, ROLE_TEXT, "Checking role of anchor element without href");
|
||||
|
||||
let onHideAndShow = waitForEvents({
|
||||
expected: [
|
||||
[EVENT_HIDE, link],
|
||||
[EVENT_SHOW, "link"],
|
||||
],
|
||||
});
|
||||
info("Adding an href to the anchor element");
|
||||
await invokeContentTask(browser, [], () => {
|
||||
content.document.getElementById("link").setAttribute("href", "#");
|
||||
});
|
||||
await onHideAndShow;
|
||||
|
||||
link = findAccessibleChildByID(accDoc, "link");
|
||||
is(link.role, ROLE_LINK, "Checking role of anchor element with href");
|
||||
|
||||
onHideAndShow = waitForEvents({
|
||||
expected: [
|
||||
[EVENT_HIDE, link],
|
||||
[EVENT_SHOW, "link"],
|
||||
],
|
||||
});
|
||||
info("Removing the href from the anchor element");
|
||||
await invokeContentTask(browser, [], () => {
|
||||
content.document.getElementById("link").removeAttribute("href");
|
||||
});
|
||||
await onHideAndShow;
|
||||
link = findAccessibleChildByID(accDoc, "link");
|
||||
is(link.role, ROLE_TEXT, "Checking role of anchor element without href");
|
||||
},
|
||||
{
|
||||
chrome: true,
|
||||
topLevel: true,
|
||||
iframe: true,
|
||||
remoteIframe: true,
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Verify that an anchor element reports a generic role without a click listener
|
||||
* and reports a LINK role with it present. Verify that these roles change as
|
||||
* the click listener appears.
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`
|
||||
<a id="link">test</a>
|
||||
`,
|
||||
async function (browser, accDoc) {
|
||||
let link = findAccessibleChildByID(accDoc, "link");
|
||||
is(
|
||||
link.role,
|
||||
ROLE_TEXT,
|
||||
"Checking role of anchor element without click listener"
|
||||
);
|
||||
|
||||
let onHideAndShow = waitForEvents({
|
||||
expected: [
|
||||
[EVENT_HIDE, link],
|
||||
[EVENT_SHOW, "link"],
|
||||
],
|
||||
});
|
||||
info("Adding a click listener to the anchor element");
|
||||
await invokeContentTask(browser, [], () => {
|
||||
content.document
|
||||
.getElementById("link")
|
||||
.addEventListener("click", () => {});
|
||||
});
|
||||
await onHideAndShow;
|
||||
|
||||
link = findAccessibleChildByID(accDoc, "link");
|
||||
is(
|
||||
link.role,
|
||||
ROLE_LINK,
|
||||
"Checking role of anchor element with click listener"
|
||||
);
|
||||
},
|
||||
{
|
||||
chrome: true,
|
||||
topLevel: true,
|
||||
iframe: true,
|
||||
remoteIframe: true,
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Verify that an area element reports a generic role without an href
|
||||
* attribute and reports a LINK role with it present. Verify that these roles
|
||||
* change as the attribute appears and disappears.
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`
|
||||
<map name="map">
|
||||
<area id="link">
|
||||
</map>
|
||||
<img id="img" usemap="#map" src="http://example.com/a11y/accessible/tests/mochitest/letters.gif">
|
||||
`,
|
||||
async function (browser, accDoc) {
|
||||
let link = findAccessibleChildByID(accDoc, "link");
|
||||
is(link.role, ROLE_TEXT, "Checking role of area element without href");
|
||||
|
||||
let img = findAccessibleChildByID(accDoc, "img");
|
||||
let onHideAndShow = waitForEvents({
|
||||
expected: [
|
||||
[EVENT_HIDE, img],
|
||||
[EVENT_SHOW, "img"],
|
||||
],
|
||||
});
|
||||
info("Adding an href to the area element");
|
||||
await invokeContentTask(browser, [], () => {
|
||||
content.document.getElementById("link").setAttribute("href", "#");
|
||||
});
|
||||
await onHideAndShow;
|
||||
|
||||
link = findAccessibleChildByID(accDoc, "link");
|
||||
is(link.role, ROLE_LINK, "Checking role of area element with href");
|
||||
|
||||
img = findAccessibleChildByID(accDoc, "img");
|
||||
onHideAndShow = waitForEvents({
|
||||
expected: [
|
||||
[EVENT_HIDE, img],
|
||||
[EVENT_SHOW, "img"],
|
||||
],
|
||||
});
|
||||
info("Removing the href from the area element");
|
||||
await invokeContentTask(browser, [], () => {
|
||||
content.document.getElementById("link").removeAttribute("href");
|
||||
});
|
||||
await onHideAndShow;
|
||||
link = findAccessibleChildByID(accDoc, "link");
|
||||
is(link.role, ROLE_TEXT, "Checking role of area element without href");
|
||||
},
|
||||
{
|
||||
chrome: true,
|
||||
topLevel: true,
|
||||
iframe: true,
|
||||
remoteIframe: true,
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Verify that an area element reports a generic role without a click listener
|
||||
* and reports a LINK role with it present. Verify that these roles change as
|
||||
* the click listener appears.
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`
|
||||
<map name="map">
|
||||
<area id="link">
|
||||
</map>
|
||||
<img id="img" usemap="#map" src="http://example.com/a11y/accessible/tests/mochitest/letters.gif">
|
||||
`,
|
||||
async function (browser, accDoc) {
|
||||
let link = findAccessibleChildByID(accDoc, "link");
|
||||
is(
|
||||
link.role,
|
||||
ROLE_TEXT,
|
||||
"Checking role of area element without click listener"
|
||||
);
|
||||
|
||||
let img = findAccessibleChildByID(accDoc, "img");
|
||||
let onHideAndShow = waitForEvents({
|
||||
expected: [
|
||||
[EVENT_HIDE, img],
|
||||
[EVENT_SHOW, "img"],
|
||||
],
|
||||
});
|
||||
info("Adding a click listener to the area element");
|
||||
await invokeContentTask(browser, [], () => {
|
||||
content.document
|
||||
.getElementById("link")
|
||||
.addEventListener("click", () => {});
|
||||
});
|
||||
await onHideAndShow;
|
||||
|
||||
link = findAccessibleChildByID(accDoc, "link");
|
||||
is(
|
||||
link.role,
|
||||
ROLE_LINK,
|
||||
"Checking role of area element with click listener"
|
||||
);
|
||||
},
|
||||
{
|
||||
chrome: true,
|
||||
topLevel: true,
|
||||
iframe: true,
|
||||
remoteIframe: true,
|
||||
}
|
||||
);
|
|
@ -74,7 +74,7 @@
|
|||
},
|
||||
{
|
||||
ID: "link2",
|
||||
actionName: "click",
|
||||
actionName: "jump",
|
||||
events: CLICK_EVENTS,
|
||||
},
|
||||
{
|
||||
|
@ -86,7 +86,7 @@
|
|||
},
|
||||
{
|
||||
ID: "link3",
|
||||
actionName: "click",
|
||||
actionName: "jump",
|
||||
events: CLICK_EVENTS,
|
||||
},
|
||||
{
|
||||
|
@ -98,7 +98,7 @@
|
|||
},
|
||||
{
|
||||
ID: "link4",
|
||||
actionName: "click",
|
||||
actionName: "jump",
|
||||
events: CLICK_EVENTS,
|
||||
},
|
||||
{
|
||||
|
@ -132,13 +132,13 @@
|
|||
<a href="about:mozilla" id="link1" target="_blank" rel="opener">
|
||||
<img src="../moz.png" id="img1">
|
||||
</a>
|
||||
<a id="link2" onmousedown="">
|
||||
<a id="link2" href="" onmousedown="">
|
||||
<img src="../moz.png" id="img2">
|
||||
</a>
|
||||
<a id="link3" onclick="">
|
||||
<a id="link3" href="" onclick="">
|
||||
<img src="../moz.png" id="img3">
|
||||
</a>
|
||||
<a id="link4" onmouseup="">
|
||||
<a id="link4" href="" onmouseup="">
|
||||
<img src="../moz.png" id="img4">
|
||||
</a>
|
||||
</body>
|
||||
|
|
|
@ -75,10 +75,6 @@
|
|||
getNode("div").removeAttribute("tabindex");
|
||||
await p;
|
||||
|
||||
p = waitForEvent(...focusableStateChange("link", false));
|
||||
getNode("link").removeAttribute("href");
|
||||
await p;
|
||||
|
||||
info("add contenteditable");
|
||||
// Expect editable change on non-input,
|
||||
// and don't expect event on a native input.
|
||||
|
@ -121,8 +117,6 @@
|
|||
|
||||
<div id="div">Hello</div>
|
||||
|
||||
<a id="link" href="#">A link</a>
|
||||
|
||||
<input id="input" value="Hello">
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -138,21 +138,6 @@
|
|||
await p;
|
||||
}
|
||||
|
||||
async function testLinked() {
|
||||
let p = waitForStateChange("link1", STATE_LINKED, false, false);
|
||||
getNode("link1").removeAttribute("href");
|
||||
await p;
|
||||
|
||||
p = waitForStateChange("link2", STATE_LINKED, false, false);
|
||||
getNode("link2").removeAttribute("onclick");
|
||||
await p;
|
||||
|
||||
p = waitForStateChange("link3", STATE_LINKED, true, false);
|
||||
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
|
||||
getNode("link3").setAttribute("href", "http://example.com");
|
||||
await p;
|
||||
}
|
||||
|
||||
async function testHasPopup() {
|
||||
let p = waitForStateChange("popupButton", STATE_HASPOPUP, true, false);
|
||||
getNode("popupButton").setAttribute("aria-haspopup", "true");
|
||||
|
@ -433,8 +418,6 @@
|
|||
|
||||
await testReadonlyUntilEditable();
|
||||
|
||||
await testLinked();
|
||||
|
||||
await testHasPopup();
|
||||
|
||||
await toggleStateChange("textbox", "aria-multiline", EXT_STATE_MULTI_LINE, true);
|
||||
|
@ -537,10 +520,6 @@
|
|||
|
||||
<input id="text1">
|
||||
|
||||
<a id="link1" href="#">I am a link link</a>
|
||||
<a id="link2" onclick="console.log('hi')">I am a link-ish link</a>
|
||||
<a id="link3">I am a non-link link</a>
|
||||
|
||||
<div id="textbox" role="textbox" aria-multiline="false">hello</div>
|
||||
|
||||
<form id="form">
|
||||
|
|
|
@ -142,18 +142,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368
|
|||
// Named anchor, should never have state_linked
|
||||
var namedAnchorAcc = getAccessible("namedAnchor",
|
||||
[nsIAccessibleHyperLink]);
|
||||
testThis("namedAnchor", namedAnchorAcc, ROLE_LINK, 1,
|
||||
"This should never be of state_linked", true, 196, 197);
|
||||
testStates(namedAnchorAcc, STATE_SELECTABLE,
|
||||
0, (STATE_FOCUSABLE | STATE_LINKED));
|
||||
testThis("namedAnchor", namedAnchorAcc, ROLE_TEXT, 1,
|
||||
null, true, 196, 197);
|
||||
testStates(namedAnchorAcc, 0, 0, (STATE_FOCUSABLE | STATE_LINKED));
|
||||
testAction("namedAnchor", namedAnchorAcc, "");
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
// No link (hasn't any attribute), should never have state_linked
|
||||
var noLinkAcc = getAccessible("noLink",
|
||||
[nsIAccessibleHyperLink]);
|
||||
testThis("noLink", noLinkAcc, ROLE_LINK, 1,
|
||||
"This should never be of state_linked", true, 254, 255);
|
||||
testThis("noLink", noLinkAcc, ROLE_TEXT, 1,
|
||||
null, true, 254, 255);
|
||||
testStates(noLinkAcc, 0, 0, (STATE_FOCUSABLE | STATE_LINKED));
|
||||
testAction("noLink", noLinkAcc, "");
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
|
|||
testThis("LinkWithSpan", 116, 5, "Heise Online");
|
||||
|
||||
// Named anchor
|
||||
testThis("namedAnchor", 193, 6, "This should never be of state_linked");
|
||||
testThis("namedAnchor", 193, 6, null);
|
||||
|
||||
// Paragraph with link
|
||||
var p2 = getAccessible("p2", [nsIAccessibleHyperText]);
|
||||
|
|
|
@ -214,7 +214,6 @@
|
|||
|
||||
// strange cases
|
||||
testStates("aria_link_link", STATE_LINKED);
|
||||
testStates("aria_link_anchor", STATE_SELECTABLE);
|
||||
|
||||
// some landmarks that break accessibility for these native elements
|
||||
// Note that these are illegal uses by web authors as per WAI-ARIA in HTML
|
||||
|
@ -553,7 +552,6 @@
|
|||
|
||||
<!-- strange edge case: please don't do this in the wild -->
|
||||
<a id="aria_link_link" role="link" href="foo">link</a>
|
||||
<a id="aria_link_anchor" role="link" name="link_anchor">link</a>
|
||||
|
||||
<!-- landmarks: links -->
|
||||
<a id="aria_application_link" role="application" href="foo">app</a>
|
||||
|
|
|
@ -187,7 +187,7 @@
|
|||
on the image cache state and what optimizations layout was able to
|
||||
apply. -->
|
||||
<div id="container1"><img src="../moz.png"> <img id="img1" src="../moz.png"> <img src="../moz.png"></div>
|
||||
<div><a id="container2"></a> <a><img src="../moz.png"></a></div>
|
||||
<div><a id="container2" href=""></a> <a href=""><img src="../moz.png"></a></div>
|
||||
|
||||
<div id="container3">
|
||||
<div id="c3_inner" role="presentation">
|
||||
|
|
|
@ -16,7 +16,6 @@ const {
|
|||
[KEYBOARD]: {
|
||||
FOCUSABLE_NO_SEMANTICS,
|
||||
FOCUSABLE_POSITIVE_TABINDEX,
|
||||
INTERACTIVE_NO_ACTION,
|
||||
INTERACTIVE_NOT_FOCUSABLE,
|
||||
MOUSE_INTERACTIVE_ONLY,
|
||||
NO_FOCUS_VISIBLE,
|
||||
|
@ -61,10 +60,7 @@ add_task(async function () {
|
|||
[
|
||||
"Interactive accesible (link with no attributes) with no accessible actions.",
|
||||
"#link-1",
|
||||
{
|
||||
score: FAIL,
|
||||
issue: INTERACTIVE_NO_ACTION,
|
||||
},
|
||||
null,
|
||||
],
|
||||
["Interactive accessible (link with valid href).", "#link-2", null],
|
||||
["Interactive accessible (link with # as href).", "#link-3", null],
|
||||
|
|
|
@ -483,11 +483,7 @@ add_task(async function () {
|
|||
],
|
||||
["<embed> with video data type and aria-label", "#embed-3", null],
|
||||
["<embed> with video data type and aria-labelledby", "#embed-4", null],
|
||||
[
|
||||
"Link with no inner content",
|
||||
"#link-1",
|
||||
{ score: FAIL, issue: INTERACTIVE_NO_NAME },
|
||||
],
|
||||
["Link with no inner content", "#link-1", null],
|
||||
["Link with inner content", "#link-2", null],
|
||||
[
|
||||
"Link with href and no inner content",
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
expected: FAIL
|
||||
|
||||
[el-a-no-href]
|
||||
expected: FAIL
|
||||
expected: PASS
|
||||
|
||||
[el-search]
|
||||
expected: FAIL
|
||||
|
|
Загрузка…
Ссылка в новой задаче