summaryrefslogtreecommitdiffstats
path: root/accessible/tests/browser/hittest
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/tests/browser/hittest')
-rw-r--r--accessible/tests/browser/hittest/browser.ini18
-rw-r--r--accessible/tests/browser/hittest/browser_test_browser.js68
-rw-r--r--accessible/tests/browser/hittest/browser_test_general.js225
-rw-r--r--accessible/tests/browser/hittest/browser_test_shadowroot.js61
-rw-r--r--accessible/tests/browser/hittest/browser_test_text.js53
-rw-r--r--accessible/tests/browser/hittest/browser_test_zoom.js38
-rw-r--r--accessible/tests/browser/hittest/browser_test_zoom_text.js64
-rw-r--r--accessible/tests/browser/hittest/head.js113
8 files changed, 640 insertions, 0 deletions
diff --git a/accessible/tests/browser/hittest/browser.ini b/accessible/tests/browser/hittest/browser.ini
new file mode 100644
index 0000000000..93c437c7c2
--- /dev/null
+++ b/accessible/tests/browser/hittest/browser.ini
@@ -0,0 +1,18 @@
+[DEFAULT]
+subsuite = a11y
+support-files =
+ head.js
+ !/accessible/tests/browser/shared-head.js
+ !/accessible/tests/browser/*.jsm
+ !/accessible/tests/mochitest/*.js
+ !/accessible/tests/mochitest/letters.gif
+
+[browser_test_browser.js]
+[browser_test_general.js]
+[browser_test_shadowroot.js]
+[browser_test_text.js]
+[browser_test_zoom_text.js]
+[browser_test_zoom.js]
+skip-if =
+ os == 'linux' && bits == 64 # Bug 1778220
+ os == 'win' # Bug 1778220
diff --git a/accessible/tests/browser/hittest/browser_test_browser.js b/accessible/tests/browser/hittest/browser_test_browser.js
new file mode 100644
index 0000000000..477af42fe9
--- /dev/null
+++ b/accessible/tests/browser/hittest/browser_test_browser.js
@@ -0,0 +1,68 @@
+/* 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";
+
+async function runTests(browser, accDoc) {
+ // Hit testing. See bug #726097
+ await invokeContentTask(browser, [], () =>
+ content.document.getElementById("hittest").scrollIntoView(true)
+ );
+
+ const dpr = await getContentDPR(browser);
+ const hititem = findAccessibleChildByID(accDoc, "hititem");
+ const hittest = findAccessibleChildByID(accDoc, "hittest");
+ const outerDocAcc = accDoc.parent;
+ const rootAcc = CommonUtils.getRootAccessible(document);
+
+ const [hitX, hitY, hitWidth, hitHeight] = Layout.getBounds(hititem, dpr);
+ // "hititem" node has the full screen width, so when we divide it by 2, we are
+ // still way outside the inline content.
+ const tgtX = hitX + hitWidth / 2;
+ const tgtY = hitY + hitHeight / 2;
+
+ let hitAcc = rootAcc.getDeepestChildAtPoint(tgtX, tgtY);
+ is(
+ hitAcc,
+ hititem,
+ `Hit match at ${tgtX},${tgtY} (root doc deepest child). Found: ${prettyName(
+ hitAcc
+ )}`
+ );
+
+ const hitAcc2 = accDoc.getDeepestChildAtPoint(tgtX, tgtY);
+ is(
+ hitAcc,
+ hitAcc2,
+ `Hit match at ${tgtX},${tgtY} (doc deepest child). Found: ${prettyName(
+ hitAcc2
+ )}`
+ );
+
+ hitAcc = outerDocAcc.getChildAtPoint(tgtX, tgtY);
+ is(
+ hitAcc,
+ accDoc,
+ `Hit match at ${tgtX},${tgtY} (outer doc child). Found: ${prettyName(
+ hitAcc
+ )}`
+ );
+
+ hitAcc = accDoc.getChildAtPoint(tgtX, tgtY);
+ is(
+ hitAcc,
+ hittest,
+ `Hit match at ${tgtX},${tgtY} (doc child). Found: ${prettyName(hitAcc)}`
+ );
+}
+
+addAccessibleTask(
+ `
+ <div id="hittest">
+ <div id="hititem"><span role="img">img</span>item</div>
+ </div>
+ `,
+ runTests,
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/hittest/browser_test_general.js b/accessible/tests/browser/hittest/browser_test_general.js
new file mode 100644
index 0000000000..c2d5b3906a
--- /dev/null
+++ b/accessible/tests/browser/hittest/browser_test_general.js
@@ -0,0 +1,225 @@
+/* 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";
+
+async function runTests(browser, accDoc) {
+ await waitForImageMap(browser, accDoc);
+ const dpr = await getContentDPR(browser);
+
+ await testChildAtPoint(
+ dpr,
+ 3,
+ 3,
+ findAccessibleChildByID(accDoc, "list"),
+ findAccessibleChildByID(accDoc, "listitem"),
+ findAccessibleChildByID(accDoc, "inner").firstChild
+ );
+ todo(
+ false,
+ "Bug 746974 - children must match on all platforms. On Windows, " +
+ "ChildAtPoint with eDeepestChild is incorrectly ignoring MustPrune " +
+ "for the graphic."
+ );
+
+ const txt = findAccessibleChildByID(accDoc, "txt");
+ await testChildAtPoint(dpr, 1, 1, txt, txt, txt);
+
+ info(
+ "::MustPrune case, point is outside of textbox accessible but is in document."
+ );
+ await testChildAtPoint(dpr, -1, -1, txt, null, null);
+
+ info("::MustPrune case, point is outside of root accessible.");
+ await testChildAtPoint(dpr, -10000, -10000, txt, null, null);
+
+ info("Not specific case, point is inside of btn accessible.");
+ const btn = findAccessibleChildByID(accDoc, "btn");
+ await testChildAtPoint(dpr, 1, 1, btn, btn, btn);
+
+ info("Not specific case, point is outside of btn accessible.");
+ await testChildAtPoint(dpr, -1, -1, btn, null, null);
+
+ info(
+ "Out of flow accessible testing, do not return out of flow accessible " +
+ "because it's not a child of the accessible even though visually it is."
+ );
+ await invokeContentTask(browser, [], () => {
+ const { CommonUtils } = ChromeUtils.importESModule(
+ "chrome://mochitests/content/browser/accessible/tests/browser/Common.sys.mjs"
+ );
+ const doc = content.document;
+ const rectArea = CommonUtils.getNode("area", doc).getBoundingClientRect();
+ const outOfFlow = CommonUtils.getNode("outofflow", doc);
+ outOfFlow.style.left = rectArea.left + "px";
+ outOfFlow.style.top = rectArea.top + "px";
+ });
+
+ const area = findAccessibleChildByID(accDoc, "area");
+ await testChildAtPoint(dpr, 1, 1, area, area, area);
+
+ info("Test image maps. Their children are not in the layout tree.");
+ const imgmap = findAccessibleChildByID(accDoc, "imgmap");
+ const theLetterA = imgmap.firstChild;
+ await hitTest(browser, imgmap, theLetterA, theLetterA);
+ await hitTest(
+ browser,
+ findAccessibleChildByID(accDoc, "container"),
+ imgmap,
+ theLetterA
+ );
+
+ info("hit testing for element contained by zero-width element");
+ const container2Input = findAccessibleChildByID(accDoc, "container2_input");
+ await hitTest(
+ browser,
+ findAccessibleChildByID(accDoc, "container2"),
+ container2Input,
+ container2Input
+ );
+
+ info("hittesting table, row, cells -- rows are not in the layout tree");
+ const table = findAccessibleChildByID(accDoc, "table");
+ const row = findAccessibleChildByID(accDoc, "row");
+ const cell1 = findAccessibleChildByID(accDoc, "cell1");
+
+ await hitTest(browser, table, row, cell1);
+
+ info("Testing that an inaccessible child doesn't break hit testing");
+ const containerWithInaccessibleChild = findAccessibleChildByID(
+ accDoc,
+ "containerWithInaccessibleChild"
+ );
+ const containerWithInaccessibleChildP2 = findAccessibleChildByID(
+ accDoc,
+ "containerWithInaccessibleChild_p2"
+ );
+ await hitTest(
+ browser,
+ containerWithInaccessibleChild,
+ containerWithInaccessibleChildP2,
+ containerWithInaccessibleChildP2.firstChild
+ );
+}
+
+addAccessibleTask(
+ `
+ <div role="list" id="list">
+ <div role="listitem" id="listitem"><span title="foo" id="inner">inner</span>item</div>
+ </div>
+
+ <span role="button">button1</span><span role="button" id="btn">button2</span>
+
+ <span role="textbox">textbox1</span><span role="textbox" id="txt">textbox2</span>
+
+ <div id="outofflow" style="width: 10px; height: 10px; position: absolute; left: 0px; top: 0px; background-color: yellow;">
+ </div>
+ <div id="area" style="width: 100px; height: 100px; background-color: blue;"></div>
+
+ <map name="atoz_map">
+ <area id="thelettera" href="http://www.bbc.co.uk/radio4/atoz/index.shtml#a"
+ coords="0,0,15,15" alt="thelettera" shape="rect"/>
+ </map>
+
+ <div id="container">
+ <img id="imgmap" width="447" height="15" usemap="#atoz_map" src="http://example.com/a11y/accessible/tests/mochitest/letters.gif"/>
+ </div>
+
+ <div id="container2" style="width: 0px">
+ <input id="container2_input">
+ </div>
+
+ <table id="table" border>
+ <tr id="row">
+ <td id="cell1">hello</td>
+ <td id="cell2">world</td>
+ </tr>
+ </table>
+
+ <div id="containerWithInaccessibleChild">
+ <p>hi</p>
+ <p aria-hidden="true">hi</p>
+ <p id="containerWithInaccessibleChild_p2">bye</p>
+ </div>
+ `,
+ runTests,
+ {
+ iframe: true,
+ remoteIframe: true,
+ // Ensure that all hittest elements are in view.
+ iframeAttrs: { style: "width: 600px; height: 600px; padding: 10px;" },
+ }
+);
+
+addAccessibleTask(
+ `
+ <div id="container">
+ <h1 id="a">A</h1><h1 id="b">B</h1>
+ </div>
+ `,
+ async function(browser, accDoc) {
+ const a = findAccessibleChildByID(accDoc, "a");
+ const b = findAccessibleChildByID(accDoc, "b");
+ const dpr = await getContentDPR(browser);
+ // eslint-disable-next-line no-unused-vars
+ const [x, y, w, h] = Layout.getBounds(a, dpr);
+ // The point passed below will be made relative to `b`, but
+ // we'd like to test a point within `a`. Pass `a`s negative
+ // width for an x offset. Pass zero as a y offset,
+ // assuming the headings are on the same line.
+ await testChildAtPoint(dpr, -w, 0, b, null, null);
+ },
+ {
+ iframe: true,
+ remoteIframe: true,
+ // Ensure that all hittest elements are in view.
+ iframeAttrs: { style: "width: 600px; height: 600px; padding: 10px;" },
+ }
+);
+
+addAccessibleTask(
+ `
+ <style>
+ div {
+ width: 50px;
+ height: 50px;
+ position: relative;
+ }
+
+ div > div {
+ width: 30px;
+ height: 30px;
+ position: absolute;
+ opacity: 0.9;
+ }
+ </style>
+ <div id="a" style="background-color: orange;">
+ <div id="aa" style="background-color: purple;"></div>
+ </div>
+ <div id="b" style="background-color: yellowgreen;">
+ <div id="bb" style="top: -30px; background-color: turquoise"></div>
+ </div>`,
+ async function(browser, accDoc) {
+ const a = findAccessibleChildByID(accDoc, "a");
+ const aa = findAccessibleChildByID(accDoc, "aa");
+ const dpr = await getContentDPR(browser);
+ const [, , w, h] = Layout.getBounds(a, dpr);
+ // test upper left of `a`
+ await testChildAtPoint(dpr, 1, 1, a, aa, aa);
+ // test upper right of `a`
+ await testChildAtPoint(dpr, w - 1, 1, a, a, a);
+ // test just outside upper left of `a`
+ await testChildAtPoint(dpr, 1, -1, a, null, null);
+ // test halfway down/left of `a`
+ await testChildAtPoint(dpr, 1, Math.round(h / 2), a, a, a);
+ },
+ {
+ chrome: true,
+ topLevel: true,
+ iframe: false,
+ remoteIframe: false,
+ // Ensure that all hittest elements are in view.
+ iframeAttrs: { style: "width: 600px; height: 600px; padding: 10px;" },
+ }
+);
diff --git a/accessible/tests/browser/hittest/browser_test_shadowroot.js b/accessible/tests/browser/hittest/browser_test_shadowroot.js
new file mode 100644
index 0000000000..94a5ce071a
--- /dev/null
+++ b/accessible/tests/browser/hittest/browser_test_shadowroot.js
@@ -0,0 +1,61 @@
+/* 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";
+
+async function runTests(browser, accDoc) {
+ const dpr = await getContentDPR(browser);
+ let componentAcc = findAccessibleChildByID(accDoc, "component1");
+ await testChildAtPoint(
+ dpr,
+ 1,
+ 1,
+ componentAcc,
+ componentAcc.firstChild,
+ componentAcc.firstChild
+ );
+
+ componentAcc = findAccessibleChildByID(accDoc, "component2");
+ await testChildAtPoint(
+ dpr,
+ 1,
+ 1,
+ componentAcc,
+ componentAcc.firstChild,
+ componentAcc.firstChild
+ );
+}
+
+addAccessibleTask(
+ `
+ <div role="group" class="components" id="component1" style="display: inline-block;">
+ <!--
+ <div role="button" id="component-child"
+ style="width: 100px; height: 100px; background-color: pink;">
+ </div>
+ -->
+ </div>
+ <div role="group" class="components" id="component2" style="display: inline-block;">
+ <!--
+ <button>Hello world</button>
+ -->
+ </div>
+ <script>
+ // This routine adds the comment children of each 'component' to its
+ // shadow root.
+ var components = document.querySelectorAll(".components");
+ for (var i = 0; i < components.length; i++) {
+ var component = components[i];
+ var shadow = component.attachShadow({mode: "open"});
+ for (var child = component.firstChild; child; child = child.nextSibling) {
+ if (child.nodeType === 8)
+ // eslint-disable-next-line no-unsanitized/property
+ shadow.innerHTML = child.data;
+ }
+ }
+ </script>
+ `,
+ runTests,
+ { iframe: true, remoteIframe: true }
+);
diff --git a/accessible/tests/browser/hittest/browser_test_text.js b/accessible/tests/browser/hittest/browser_test_text.js
new file mode 100644
index 0000000000..1bd314e438
--- /dev/null
+++ b/accessible/tests/browser/hittest/browser_test_text.js
@@ -0,0 +1,53 @@
+/* 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";
+
+addAccessibleTask(
+ `
+a
+<div id="noChars" style="width: 5px; height: 5px;"><p></p></div>
+<p id="twoText"><span>a</span><span>b</span></p>
+<div id="iframeAtEnd" style="width: 20px; height: 20px;">
+ a
+ <iframe width="1" height="1"></iframe>
+</div>
+ `,
+ async function(browser, docAcc) {
+ const dpr = await getContentDPR(browser);
+ // Test getOffsetAtPoint on a container containing no characters. The inner
+ // container does not include the requested point, but the outer one does.
+ const noChars = findAccessibleChildByID(docAcc, "noChars", [
+ Ci.nsIAccessibleText,
+ ]);
+ let [x, y] = Layout.getBounds(noChars, dpr);
+ await testOffsetAtPoint(noChars, x, y, COORDTYPE_SCREEN_RELATIVE, -1);
+
+ // Test that the correct offset is returned for a point in a second text
+ // leaf.
+ const twoText = findAccessibleChildByID(docAcc, "twoText", [
+ Ci.nsIAccessibleText,
+ ]);
+ const text2 = twoText.getChildAt(1);
+ [x, y] = Layout.getBounds(text2, dpr);
+ await testOffsetAtPoint(twoText, x, y, COORDTYPE_SCREEN_RELATIVE, 1);
+
+ // Test offsetAtPoint when there is an iframe at the end of the container.
+ const iframeAtEnd = findAccessibleChildByID(docAcc, "iframeAtEnd", [
+ Ci.nsIAccessibleText,
+ ]);
+ let width;
+ let height;
+ [x, y, width, height] = Layout.getBounds(iframeAtEnd, dpr);
+ x += width - 1;
+ y += height - 1;
+ await testOffsetAtPoint(iframeAtEnd, x, y, COORDTYPE_SCREEN_RELATIVE, -1);
+ },
+ {
+ topLevel: true,
+ iframe: true,
+ remoteIframe: true,
+ chrome: true,
+ }
+);
diff --git a/accessible/tests/browser/hittest/browser_test_zoom.js b/accessible/tests/browser/hittest/browser_test_zoom.js
new file mode 100644
index 0000000000..84383df483
--- /dev/null
+++ b/accessible/tests/browser/hittest/browser_test_zoom.js
@@ -0,0 +1,38 @@
+/* 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";
+
+async function runTests(browser, accDoc) {
+ if (Services.appinfo.OS !== "Darwin") {
+ const p1 = findAccessibleChildByID(accDoc, "p1");
+ const p2 = findAccessibleChildByID(accDoc, "p2");
+ await hitTest(browser, accDoc, p1, p1.firstChild);
+ await hitTest(browser, accDoc, p2, p2.firstChild);
+
+ await invokeContentTask(browser, [], () => {
+ const { Layout } = ChromeUtils.importESModule(
+ "chrome://mochitests/content/browser/accessible/tests/browser/Layout.sys.mjs"
+ );
+
+ Layout.zoomDocument(content.document, 2.0);
+ content.document.body.offsetTop; // getBounds doesn't flush layout on its own.
+ });
+
+ await hitTest(browser, accDoc, p1, p1.firstChild);
+ await hitTest(browser, accDoc, p2, p2.firstChild);
+ } else {
+ todo(
+ false,
+ "Bug 746974 - deepest child must be correct on all platforms, disabling on Mac!"
+ );
+ }
+}
+
+addAccessibleTask(`<p id="p1">para 1</p><p id="p2">para 2</p>`, runTests, {
+ iframe: true,
+ remoteIframe: true,
+ // Ensure that all hittest elements are in view.
+ iframeAttrs: { style: "left: 100px; top: 100px;" },
+});
diff --git a/accessible/tests/browser/hittest/browser_test_zoom_text.js b/accessible/tests/browser/hittest/browser_test_zoom_text.js
new file mode 100644
index 0000000000..9e429c16b3
--- /dev/null
+++ b/accessible/tests/browser/hittest/browser_test_zoom_text.js
@@ -0,0 +1,64 @@
+/* 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";
+
+async function runTests(browser, accDoc) {
+ const expectedLength = await invokeContentTask(browser, [], () => {
+ const { CommonUtils } = ChromeUtils.importESModule(
+ "chrome://mochitests/content/browser/accessible/tests/browser/Common.sys.mjs"
+ );
+ const hyperText = CommonUtils.getNode("paragraph", content.document);
+ return Math.floor(hyperText.textContent.length / 2);
+ });
+ const hyperText = findAccessibleChildByID(accDoc, "paragraph", [
+ Ci.nsIAccessibleText,
+ ]);
+ const textNode = hyperText.firstChild;
+
+ let [x, y, width, height] = Layout.getBounds(
+ textNode,
+ await getContentDPR(browser)
+ );
+
+ await testOffsetAtPoint(
+ hyperText,
+ x + width / 2,
+ y + height / 2,
+ COORDTYPE_SCREEN_RELATIVE,
+ expectedLength
+ );
+
+ await invokeContentTask(browser, [], () => {
+ const { Layout } = ChromeUtils.importESModule(
+ "chrome://mochitests/content/browser/accessible/tests/browser/Layout.sys.mjs"
+ );
+
+ Layout.zoomDocument(content.document, 2.0);
+ content.document.body.offsetTop; // getBounds doesn't flush layout on its own.
+ });
+
+ [x, y, width, height] = Layout.getBounds(
+ textNode,
+ await getContentDPR(browser)
+ );
+
+ await testOffsetAtPoint(
+ hyperText,
+ x + width / 2,
+ y + height / 2,
+ COORDTYPE_SCREEN_RELATIVE,
+ expectedLength
+ );
+}
+
+addAccessibleTask(
+ `<p id="paragraph" style="font-family: monospace;">hello world hello world</p>`,
+ runTests,
+ {
+ iframe: true,
+ remoteIframe: true,
+ iframeAttrs: { style: "width: 600px; height: 600px;" },
+ }
+);
diff --git a/accessible/tests/browser/hittest/head.js b/accessible/tests/browser/hittest/head.js
new file mode 100644
index 0000000000..867f8cde35
--- /dev/null
+++ b/accessible/tests/browser/hittest/head.js
@@ -0,0 +1,113 @@
+/* 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";
+
+// Load the shared-head file first.
+/* import-globals-from ../shared-head.js */
+
+/* exported CommonUtils, testChildAtPoint, Layout, hitTest, testOffsetAtPoint */
+
+Services.scriptloader.loadSubScript(
+ "chrome://mochitests/content/browser/accessible/tests/browser/shared-head.js",
+ this
+);
+
+// Loading and common.js from accessible/tests/mochitest/ for all tests, as
+// well as promisified-events.js.
+loadScripts(
+ { name: "common.js", dir: MOCHITESTS_DIR },
+ { name: "promisified-events.js", dir: MOCHITESTS_DIR }
+);
+
+const { CommonUtils } = ChromeUtils.importESModule(
+ "chrome://mochitests/content/browser/accessible/tests/browser/Common.sys.mjs"
+);
+
+const { Layout } = ChromeUtils.importESModule(
+ "chrome://mochitests/content/browser/accessible/tests/browser/Layout.sys.mjs"
+);
+
+function getChildAtPoint(container, x, y, findDeepestChild) {
+ try {
+ return findDeepestChild
+ ? container.getDeepestChildAtPoint(x, y)
+ : container.getChildAtPoint(x, y);
+ } catch (e) {
+ // Failed to get child at point.
+ }
+ info("could not get child at point");
+ return null;
+}
+
+async function testChildAtPoint(dpr, x, y, container, child, grandChild) {
+ const [containerX, containerY] = Layout.getBounds(container, dpr);
+ x += containerX;
+ y += containerY;
+ let actual = null;
+ await untilCacheIs(
+ () => {
+ actual = getChildAtPoint(container, x, y, false);
+ return actual;
+ },
+ child,
+ `Wrong direct child accessible at the point (${x}, ${y}) of ${CommonUtils.prettyName(
+ container
+ )}, sought ${CommonUtils.prettyName(
+ child
+ )} and got ${CommonUtils.prettyName(actual)}`
+ );
+ actual = null;
+ await untilCacheIs(
+ () => {
+ actual = getChildAtPoint(container, x, y, true);
+ return actual;
+ },
+ grandChild,
+ `Wrong deepest child accessible at the point (${x}, ${y}) of ${CommonUtils.prettyName(
+ container
+ )}, sought ${CommonUtils.prettyName(
+ grandChild
+ )} and got ${CommonUtils.prettyName(actual)}`
+ );
+}
+
+/**
+ * Test if getChildAtPoint returns the given child and grand child accessibles
+ * at coordinates of child accessible (direct and deep hit test).
+ */
+async function hitTest(browser, container, child, grandChild) {
+ const [childX, childY] = await getContentBoundsForDOMElm(
+ browser,
+ getAccessibleDOMNodeID(child)
+ );
+ const x = childX + 1;
+ const y = childY + 1;
+
+ await untilCacheIs(
+ () => getChildAtPoint(container, x, y, false),
+ child,
+ `Wrong direct child accessible at the point (${x}, ${y}) of ${CommonUtils.prettyName(
+ container
+ )}, sought ${CommonUtils.prettyName(child)}`
+ );
+ await untilCacheIs(
+ () => getChildAtPoint(container, x, y, true),
+ grandChild,
+ `Wrong deepest child accessible at the point (${x}, ${y}) of ${CommonUtils.prettyName(
+ container
+ )}, sought ${CommonUtils.prettyName(grandChild)}`
+ );
+}
+
+/**
+ * Test if getOffsetAtPoint returns the given text offset at given coordinates.
+ */
+async function testOffsetAtPoint(hyperText, x, y, coordType, expectedOffset) {
+ await untilCacheIs(
+ () => hyperText.getOffsetAtPoint(x, y, coordType),
+ expectedOffset,
+ `Wrong offset at given point (${x}, ${y}) for ${prettyName(hyperText)}`
+ );
+}