summaryrefslogtreecommitdiffstats
path: root/accessible/tests/browser/e10s/browser_caching_relations_002.js
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/tests/browser/e10s/browser_caching_relations_002.js')
-rw-r--r--accessible/tests/browser/e10s/browser_caching_relations_002.js366
1 files changed, 366 insertions, 0 deletions
diff --git a/accessible/tests/browser/e10s/browser_caching_relations_002.js b/accessible/tests/browser/e10s/browser_caching_relations_002.js
new file mode 100644
index 0000000000..072656eb5e
--- /dev/null
+++ b/accessible/tests/browser/e10s/browser_caching_relations_002.js
@@ -0,0 +1,366 @@
+/* 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";
+requestLongerTimeout(2);
+
+/**
+ * Test MEMBER_OF relation caching on HTML radio buttons
+ */
+addAccessibleTask(
+ `
+ <input type="radio" id="r1">I have no name<br>
+ <input type="radio" id="r2">I also have no name<br>
+ <input type="radio" id="r3" name="n">I have a name<br>
+ <input type="radio" id="r4" name="a">I have a different name<br>
+ <fieldset role="radiogroup">
+ <input type="radio" id="r5" name="n">I have an already used name
+ and am in a different part of the tree
+ <input type="radio" id="r6" name="r">I have a different name but am
+ in the same group
+ </fieldset>`,
+ async function (browser, accDoc) {
+ const r1 = findAccessibleChildByID(accDoc, "r1");
+ const r2 = findAccessibleChildByID(accDoc, "r2");
+ const r3 = findAccessibleChildByID(accDoc, "r3");
+ const r4 = findAccessibleChildByID(accDoc, "r4");
+ const r5 = findAccessibleChildByID(accDoc, "r5");
+ const r6 = findAccessibleChildByID(accDoc, "r6");
+
+ await testCachedRelation(r1, RELATION_MEMBER_OF, null);
+ await testCachedRelation(r2, RELATION_MEMBER_OF, null);
+ await testCachedRelation(r3, RELATION_MEMBER_OF, [r3, r5]);
+ await testCachedRelation(r4, RELATION_MEMBER_OF, r4);
+ await testCachedRelation(r5, RELATION_MEMBER_OF, [r3, r5]);
+ await testCachedRelation(r6, RELATION_MEMBER_OF, r6);
+
+ await invokeContentTask(browser, [], () => {
+ content.document.getElementById("r5").name = "a";
+ });
+
+ await testCachedRelation(r3, RELATION_MEMBER_OF, r3);
+ await testCachedRelation(r4, RELATION_MEMBER_OF, [r5, r4]);
+ await testCachedRelation(r5, RELATION_MEMBER_OF, [r5, r4]);
+ },
+ { chrome: true, iframe: true, remoteIframe: true }
+);
+
+/*
+ * Test MEMBER_OF relation caching on aria radio buttons
+ */
+addAccessibleTask(
+ `
+ <div role="radio" id="r1">I have no radio group</div><br>
+ <fieldset role="radiogroup" id="fs">
+ <div role="radio" id="r2">hello</div><br>
+ <div role="radio" id="r3">world</div><br>
+ </fieldset>`,
+ async function (browser, accDoc) {
+ const r1 = findAccessibleChildByID(accDoc, "r1");
+ const r2 = findAccessibleChildByID(accDoc, "r2");
+ let r3 = findAccessibleChildByID(accDoc, "r3");
+
+ await testCachedRelation(r1, RELATION_MEMBER_OF, null);
+ await testCachedRelation(r2, RELATION_MEMBER_OF, [r2, r3]);
+ await testCachedRelation(r3, RELATION_MEMBER_OF, [r2, r3]);
+ const r = waitForEvent(EVENT_INNER_REORDER, "fs");
+ await invokeContentTask(browser, [], () => {
+ let innerRadio = content.document.getElementById("r3");
+ content.document.body.appendChild(innerRadio);
+ });
+ await r;
+
+ r3 = findAccessibleChildByID(accDoc, "r3");
+ await testCachedRelation(r1, RELATION_MEMBER_OF, null);
+ await testCachedRelation(r2, RELATION_MEMBER_OF, r2);
+ await testCachedRelation(r3, RELATION_MEMBER_OF, null);
+ },
+ {
+ chrome: true,
+ iframe: true,
+ remoteIframe: true,
+ }
+);
+
+/*
+ * Test mutation of LABEL relations via accessible shutdown.
+ */
+addAccessibleTask(
+ `
+ <div id="d"></div>
+ <label id="l">
+ <select id="s">
+ `,
+ async function (browser, accDoc) {
+ const label = findAccessibleChildByID(accDoc, "l");
+ const select = findAccessibleChildByID(accDoc, "s");
+ const div = findAccessibleChildByID(accDoc, "d");
+
+ await testCachedRelation(label, RELATION_LABEL_FOR, select);
+ await testCachedRelation(select, RELATION_LABELLED_BY, label);
+ await testCachedRelation(div, RELATION_LABELLED_BY, null);
+
+ const r = waitForEvent(EVENT_REORDER, "l");
+ await invokeContentTask(browser, [], () => {
+ content.document.getElementById("s").remove();
+ });
+ await r;
+ await invokeContentTask(browser, [], () => {
+ const l = content.document.getElementById("l");
+ l.htmlFor = "d";
+ });
+ await testCachedRelation(label, RELATION_LABEL_FOR, div);
+ await testCachedRelation(div, RELATION_LABELLED_BY, label);
+ },
+ {
+ chrome: false,
+ iframe: true,
+ remoteIframe: true,
+ topLevel: true,
+ }
+);
+
+/*
+ * Test mutation of LABEL relations via DOM ID reuse.
+ */
+addAccessibleTask(
+ `
+ <div id="label">before</div><input id="input" aria-labelledby="label">
+ `,
+ async function (browser, accDoc) {
+ let label = findAccessibleChildByID(accDoc, "label");
+ const input = findAccessibleChildByID(accDoc, "input");
+
+ await testCachedRelation(label, RELATION_LABEL_FOR, input);
+ await testCachedRelation(input, RELATION_LABELLED_BY, label);
+
+ const r = waitForEvent(EVENT_REORDER, accDoc);
+ await invokeContentTask(browser, [], () => {
+ content.document.getElementById("label").remove();
+ let l = content.document.createElement("div");
+ l.id = "label";
+ l.textContent = "after";
+ content.document.body.insertBefore(
+ l,
+ content.document.getElementById("input")
+ );
+ });
+ await r;
+ label = findAccessibleChildByID(accDoc, "label");
+ await testCachedRelation(label, RELATION_LABEL_FOR, input);
+ await testCachedRelation(input, RELATION_LABELLED_BY, label);
+ },
+ {
+ chrome: true,
+ iframe: true,
+ remoteIframe: true,
+ }
+);
+
+/*
+ * Test LINKS_TO relation caching an anchor with multiple hashes
+ */
+addAccessibleTask(
+ `
+ <a id="link" href="#foo#bar">Origin</a><br>
+ <a id="anchor" name="foo#bar">Destination`,
+ async function (browser, accDoc) {
+ const link = findAccessibleChildByID(accDoc, "link");
+ const anchor = findAccessibleChildByID(accDoc, "anchor");
+
+ await testCachedRelation(link, RELATION_LINKS_TO, anchor);
+ },
+ {
+ chrome: true,
+ // IA2 doesn't have a LINKS_TO relation and Windows non-cached
+ // RemoteAccessible uses IA2, so we can't run these tests in this case.
+ topLevel: true,
+ iframe: true,
+ remoteIframe: true,
+ }
+);
+
+/*
+ * Test mutation of LABEL relations via accessible shutdown.
+ */
+addAccessibleTask(
+ `
+ <div id="d"></div>
+ <label id="l">
+ <select id="s">
+ `,
+ async function (browser, accDoc) {
+ const label = findAccessibleChildByID(accDoc, "l");
+ const select = findAccessibleChildByID(accDoc, "s");
+ const div = findAccessibleChildByID(accDoc, "d");
+
+ await testCachedRelation(label, RELATION_LABEL_FOR, select);
+ await testCachedRelation(select, RELATION_LABELLED_BY, label);
+ await testCachedRelation(div, RELATION_LABELLED_BY, null);
+ await untilCacheOk(() => {
+ try {
+ // We should get an acc ID back from this, but we don't have a way of
+ // verifying its correctness -- it should be the ID of the select.
+ return label.cache.getStringProperty("for");
+ } catch (e) {
+ ok(false, "Exception thrown while trying to read from the cache");
+ return false;
+ }
+ }, "Label for relation exists");
+
+ const r = waitForEvent(EVENT_REORDER, "l");
+ await invokeContentTask(browser, [], () => {
+ content.document.getElementById("s").remove();
+ });
+ await r;
+ await untilCacheOk(() => {
+ try {
+ label.cache.getStringProperty("for");
+ } catch (e) {
+ // This property should no longer exist in the cache, so we should
+ // get an exception if we try to fetch it.
+ return true;
+ }
+ return false;
+ }, "Label for relation exists");
+
+ await invokeContentTask(browser, [], () => {
+ const l = content.document.getElementById("l");
+ l.htmlFor = "d";
+ });
+ await testCachedRelation(label, RELATION_LABEL_FOR, div);
+ await testCachedRelation(div, RELATION_LABELLED_BY, label);
+ },
+ {
+ /**
+ * This functionality is broken in our LocalAcccessible implementation,
+ * so we avoid running this test in chrome or when the cache is off.
+ */
+ chrome: false,
+ iframe: true,
+ remoteIframe: true,
+ topLevel: true,
+ }
+);
+
+/**
+ * Test label relations on HTML figure/figcaption.
+ */
+addAccessibleTask(
+ `
+<figure id="figure1">
+ before
+ <figcaption id="caption1">caption1</figcaption>
+ after
+</figure>
+<figure id="figure2" aria-labelledby="label">
+ <figcaption id="caption2">caption2</figure>
+</figure>
+<div id="label">label</div>
+ `,
+ async function (browser, docAcc) {
+ const figure1 = findAccessibleChildByID(docAcc, "figure1");
+ let caption1 = findAccessibleChildByID(docAcc, "caption1");
+ await testCachedRelation(figure1, RELATION_LABELLED_BY, caption1);
+ await testCachedRelation(caption1, RELATION_LABEL_FOR, figure1);
+
+ info("Hiding caption1");
+ let mutated = waitForEvent(EVENT_HIDE, caption1);
+ await invokeContentTask(browser, [], () => {
+ content.document.getElementById("caption1").hidden = true;
+ });
+ await mutated;
+ await testCachedRelation(figure1, RELATION_LABELLED_BY, null);
+
+ info("Showing caption1");
+ mutated = waitForEvent(EVENT_SHOW, "caption1");
+ await invokeContentTask(browser, [], () => {
+ content.document.getElementById("caption1").hidden = false;
+ });
+ caption1 = (await mutated).accessible;
+ await testCachedRelation(figure1, RELATION_LABELLED_BY, caption1);
+ await testCachedRelation(caption1, RELATION_LABEL_FOR, figure1);
+
+ const figure2 = findAccessibleChildByID(docAcc, "figure2");
+ const caption2 = findAccessibleChildByID(docAcc, "caption2");
+ const label = findAccessibleChildByID(docAcc, "label");
+ await testCachedRelation(figure2, RELATION_LABELLED_BY, [label, caption2]);
+ await testCachedRelation(caption2, RELATION_LABEL_FOR, figure2);
+ await testCachedRelation(label, RELATION_LABEL_FOR, figure2);
+ },
+ { chrome: true, topLevel: true }
+);
+
+/**
+ * Test details relations on popovers and their invokers.
+ */
+addAccessibleTask(
+ `
+<button id="hide" popovertarget="popover" popovertargetaction="hide">hide</button>
+<button id="toggle1" popovertarget="popover">toggle1</button>
+<button id="toggle2">toggle2</button>
+<button id="toggleSibling">toggleSibling</button>
+<div id="popover" popover>popover</div>
+<div id="details">details</div>
+ `,
+ async function testPopover(browser, docAcc) {
+ // The popover is hidden, so nothing should be referring to it.
+ const hide = findAccessibleChildByID(docAcc, "hide");
+ await testCachedRelation(hide, RELATION_DETAILS, []);
+ const toggle1 = findAccessibleChildByID(docAcc, "toggle1");
+ await testCachedRelation(toggle1, RELATION_DETAILS, []);
+ const toggle2 = findAccessibleChildByID(docAcc, "toggle2");
+ await testCachedRelation(toggle2, RELATION_DETAILS, []);
+ const toggleSibling = findAccessibleChildByID(docAcc, "toggleSibling");
+ await testCachedRelation(toggleSibling, RELATION_DETAILS, []);
+
+ info("Showing popover");
+ let shown = waitForEvent(EVENT_SHOW, "popover");
+ toggle1.doAction(0);
+ const popover = (await shown).accessible;
+ await testCachedRelation(toggle1, RELATION_DETAILS, popover);
+ // toggle2 shouldn't have a details relation because it doesn't have a
+ // popovertarget.
+ await testCachedRelation(toggle2, RELATION_DETAILS, []);
+ // hide shouldn't have a details relation because its action is hide.
+ await testCachedRelation(hide, RELATION_DETAILS, []);
+ // toggleSibling shouldn't have a details relation because it is a sibling
+ // of the popover.
+ await testCachedRelation(toggleSibling, RELATION_DETAILS, []);
+ await testCachedRelation(popover, RELATION_DETAILS_FOR, toggle1);
+
+ info("Setting toggle2 popovertargetaction");
+ await invokeSetAttribute(browser, "toggle2", "popovertarget", "popover");
+ await testCachedRelation(toggle2, RELATION_DETAILS, popover);
+ await testCachedRelation(popover, RELATION_DETAILS_FOR, [toggle1, toggle2]);
+
+ info("Removing toggle2 popovertarget");
+ await invokeSetAttribute(browser, "toggle2", "popovertarget", null);
+ await testCachedRelation(toggle2, RELATION_DETAILS, []);
+ await testCachedRelation(popover, RELATION_DETAILS_FOR, toggle1);
+
+ info("Setting aria-details on toggle1");
+ await invokeSetAttribute(browser, "toggle1", "aria-details", "details");
+ const details = findAccessibleChildByID(docAcc, "details");
+ // aria-details overrides popover.
+ await testCachedRelation(toggle1, RELATION_DETAILS, details);
+ await testCachedRelation(popover, RELATION_DETAILS_FOR, []);
+
+ info("Removing aria-details from toggle1");
+ await invokeSetAttribute(browser, "toggle1", "aria-details", null);
+ await testCachedRelation(toggle1, RELATION_DETAILS, popover);
+ await testCachedRelation(popover, RELATION_DETAILS_FOR, toggle1);
+
+ info("Hiding popover");
+ let hidden = waitForEvent(EVENT_HIDE, popover);
+ toggle1.doAction(0);
+ // The relations between toggle1 and popover are removed when popover shuts
+ // down. However, this doesn't cause a cache update notification. Therefore,
+ // to avoid timing out in testCachedRelation, we must wait for a hide event
+ // first.
+ await hidden;
+ await testCachedRelation(toggle1, RELATION_DETAILS, []);
+ },
+ { chrome: false, topLevel: true }
+);