summaryrefslogtreecommitdiffstats
path: root/accessible/tests/browser/mac/browser_link.js
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/tests/browser/mac/browser_link.js')
-rw-r--r--accessible/tests/browser/mac/browser_link.js231
1 files changed, 231 insertions, 0 deletions
diff --git a/accessible/tests/browser/mac/browser_link.js b/accessible/tests/browser/mac/browser_link.js
new file mode 100644
index 0000000000..7407a50b42
--- /dev/null
+++ b/accessible/tests/browser/mac/browser_link.js
@@ -0,0 +1,231 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+/* import-globals-from ../../mochitest/role.js */
+/* import-globals-from ../../mochitest/states.js */
+loadScripts(
+ { name: "role.js", dir: MOCHITESTS_DIR },
+ { name: "states.js", dir: MOCHITESTS_DIR }
+);
+
+ChromeUtils.defineESModuleGetters(this, {
+ PlacesTestUtils: "resource://testing-common/PlacesTestUtils.sys.mjs",
+});
+
+/**
+ * Test visited link properties.
+ */
+addAccessibleTask(
+ `
+ <a id="link" href="http://www.example.com/">I am a non-visited link</a><br>
+ `,
+ async (browser, accDoc) => {
+ let link = getNativeInterface(accDoc, "link");
+ let stateChanged = waitForEvent(EVENT_STATE_CHANGE, "link");
+
+ is(link.getAttributeValue("AXVisited"), 0, "Link has not been visited");
+
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ await PlacesTestUtils.addVisits(["http://www.example.com/"]);
+
+ await stateChanged;
+ is(link.getAttributeValue("AXVisited"), 1, "Link has been visited");
+
+ // Ensure history is cleared before running
+ await PlacesUtils.history.clear();
+ }
+);
+
+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
+ */
+addAccessibleTask(
+ `
+ <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>
+ `,
+ async (browser, accDoc) => {
+ let link1 = getNativeInterface(accDoc, "link1");
+ is(
+ link1.getAttributeValue("AXRole"),
+ "AXLink",
+ "a[href] gets correct link role"
+ );
+ ok(
+ link1.attributeNames.includes("AXVisited"),
+ "Link has visited attribute"
+ );
+ ok(link1.attributeNames.includes("AXURL"), "Link has URL attribute");
+
+ let link2 = getNativeInterface(accDoc, "link2");
+ is(
+ link2.getAttributeValue("AXRole"),
+ "AXLink",
+ "a[onclick] gets correct link role"
+ );
+ ok(
+ link2.attributeNames.includes("AXVisited"),
+ "Link has visited attribute"
+ );
+ ok(link2.attributeNames.includes("AXURL"), "Link has URL attribute");
+
+ let link3 = getNativeInterface(accDoc, "link3");
+ is(
+ link3.getAttributeValue("AXRole"),
+ "AXGroup",
+ "bare <a> gets correct group role"
+ );
+
+ let stateChanged = waitForLinkedChange("link1", false);
+ await SpecialPowers.spawn(browser, [], () => {
+ content.document.getElementById("link1").removeAttribute("href");
+ });
+ await stateChanged;
+ is(
+ link1.getAttributeValue("AXRole"),
+ "AXGroup",
+ "<a> stripped from href gets group role"
+ );
+
+ stateChanged = waitForLinkedChange("link2", false);
+ await SpecialPowers.spawn(browser, [], () => {
+ content.document.getElementById("link2").removeAttribute("onclick");
+ });
+ await stateChanged;
+ is(
+ link2.getAttributeValue("AXRole"),
+ "AXGroup",
+ "<a> stripped from onclick gets group role"
+ );
+
+ stateChanged = waitForLinkedChange("link3", true);
+ await SpecialPowers.spawn(browser, [], () => {
+ content.document
+ .getElementById("link3")
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ .setAttribute("href", "http://example.com");
+ });
+ await stateChanged;
+ is(
+ link3.getAttributeValue("AXRole"),
+ "AXLink",
+ "href added to bare a gets link role"
+ );
+
+ ok(
+ link3.attributeNames.includes("AXVisited"),
+ "Link has visited attribute"
+ );
+ ok(link3.attributeNames.includes("AXURL"), "Link has URL attribute");
+ }
+);
+
+/**
+ * Test anchors and linked ui elements attr
+ */
+addAccessibleTask(
+ `
+ <a id="link0" href="http://example.com">I am a link</a>
+ <a id="link1" href="#">I am a link with an empty anchor</a>
+ <a id="link2" href="#hello">I am a link with no corresponding element</a>
+ <a id="link3" href="#world">I am a link with a corresponding element</a>
+ <a id="link4" href="#empty">I jump to an empty element</a>
+ <a id="link5" href="#namedElem">I jump to a named element</a>
+ <a id="link6" href="#emptyNamed">I jump to an empty named element</a>
+ <h1 id="world">I am that element</h1>
+ <h2 id="empty"></h2>
+ <a name="namedElem">I have a name</a>
+ <a name="emptyNamed"></a>
+ <h3>I have no name and no ID</h3>
+ <h4></h4>
+ `,
+ async (browser, accDoc) => {
+ let link0 = getNativeInterface(accDoc, "link0");
+ let link1 = getNativeInterface(accDoc, "link1");
+ let link2 = getNativeInterface(accDoc, "link2");
+ let link3 = getNativeInterface(accDoc, "link3");
+ let link4 = getNativeInterface(accDoc, "link4");
+ let link5 = getNativeInterface(accDoc, "link5");
+ let link6 = getNativeInterface(accDoc, "link6");
+
+ is(
+ link0.getAttributeValue("AXLinkedUIElements").length,
+ 0,
+ "Link 0 has no linked UI elements"
+ );
+ is(
+ link1.getAttributeValue("AXLinkedUIElements").length,
+ 0,
+ "Link 1 has no linked UI elements"
+ );
+ is(
+ link2.getAttributeValue("AXLinkedUIElements").length,
+ 0,
+ "Link 2 has no linked UI elements"
+ );
+ is(
+ link3.getAttributeValue("AXLinkedUIElements").length,
+ 1,
+ "Link 3 has one linked UI element"
+ );
+ is(
+ link3
+ .getAttributeValue("AXLinkedUIElements")[0]
+ .getAttributeValue("AXTitle"),
+ "I am that element",
+ "Link 3 is linked to the heading"
+ );
+ is(
+ link4.getAttributeValue("AXLinkedUIElements").length,
+ 1,
+ "Link 4 has one linked UI element"
+ );
+ is(
+ link4
+ .getAttributeValue("AXLinkedUIElements")[0]
+ .getAttributeValue("AXTitle"),
+ "",
+ "Link 4 is linked to the heading"
+ );
+ is(
+ link5.getAttributeValue("AXLinkedUIElements").length,
+ 1,
+ "Link 5 has one linked UI element"
+ );
+ is(
+ link5
+ .getAttributeValue("AXLinkedUIElements")[0]
+ .getAttributeValue("AXTitle"),
+ "I have a name",
+ "Link 5 is linked to a named element"
+ );
+ is(
+ link6.getAttributeValue("AXLinkedUIElements").length,
+ 1,
+ "Link 6 has one linked UI element"
+ );
+ is(
+ link6
+ .getAttributeValue("AXLinkedUIElements")[0]
+ .getAttributeValue("AXTitle"),
+ "",
+ "Link 6 is linked to an empty named element"
+ );
+ }
+);