/* 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); 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."); await waitForImageMap(browser, accDoc); const imgmap = findAccessibleChildByID(accDoc, "imgmap"); ok(imgmap, "Image map exists"); 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 ); info("Testing wrapped text"); const wrappedTextLinkFirstP = findAccessibleChildByID( accDoc, "wrappedTextLinkFirstP" ); const wrappedTextLinkFirstA = findAccessibleChildByID( accDoc, "wrappedTextLinkFirstA" ); await hitTest( browser, wrappedTextLinkFirstP, wrappedTextLinkFirstA, wrappedTextLinkFirstA.firstChild ); const wrappedTextLeafFirstP = findAccessibleChildByID( accDoc, "wrappedTextLeafFirstP" ); const wrappedTextLeafFirstMark = findAccessibleChildByID( accDoc, "wrappedTextLeafFirstMark" ); await hitTest( browser, wrappedTextLeafFirstP, wrappedTextLeafFirstMark, wrappedTextLeafFirstMark.firstChild ); info("Testing image"); const imageP = findAccessibleChildByID(accDoc, "imageP"); const image = findAccessibleChildByID(accDoc, "image"); await hitTest(browser, imageP, image, image); info("Testing image map with 0-sized area"); const mapWith0AreaP = findAccessibleChildByID(accDoc, "mapWith0AreaP"); const mapWith0Area = findAccessibleChildByID(accDoc, "mapWith0Area"); await hitTest(browser, mapWith0AreaP, mapWith0Area, mapWith0Area); } addAccessibleTask( `
inneritem
button1button2 textbox1textbox2
thelettera
hello world

hi

bye

ab cd

ab cd

`, runTests, { iframe: true, remoteIframe: true, // Ensure that all hittest elements are in view. iframeAttrs: { style: "width: 600px; height: 600px; padding: 10px;" }, } ); addAccessibleTask( `

A

B

`, 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( `
`, 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;" }, } ); /** * Verify that hit testing returns the proper accessible when one acc content * is partially hidden due to overflow:hidden; */ addAccessibleTask( `
abcde
fghij
`, async function (browser, docAcc) { const container = findAccessibleChildByID(docAcc, "container"); const aNode = findAccessibleChildByID(docAcc, "aNode"); const fNode = findAccessibleChildByID(docAcc, "fNode"); const dpr = await getContentDPR(browser); const [, , containerWidth] = Layout.getBounds(container, dpr); const [, , aNodeWidth] = Layout.getBounds(aNode, dpr); await testChildAtPoint( dpr, containerWidth - 1, 1, container, aNode, aNode.firstChild ); await testChildAtPoint( dpr, containerWidth - aNodeWidth - 1, 1, container, fNode, fNode.firstChild ); }, { chrome: true, iframe: true, remoteIframe: true } ); /** * Verify that hit testing is appropriately fuzzy when working with generics. * If we match on a generic which contains additional generics and a single text * leaf, we should return the text leaf as the deepest match instead of the * generic itself. */ addAccessibleTask( ` I am some invisible text `, async function (browser, docAcc) { const link = findAccessibleChildByID(docAcc, "link"); const generic = findAccessibleChildByID(docAcc, "generic"); const invisible = findAccessibleChildByID(docAcc, "invisible"); const dpr = await getContentDPR(browser); await testChildAtPoint( dpr, 1, 1, link, generic, // Direct Child invisible.firstChild // Deepest Child ); await testOffsetAtPoint( findAccessibleChildByID(docAcc, "invisible", [Ci.nsIAccessibleText]), 1, 1, COORDTYPE_PARENT_RELATIVE, 0 ); }, { chrome: false, iframe: true, remoteIframe: true } ); /** * Verify that hit testing is appropriately fuzzy when working with generics with siblings. * We should return the deepest text leaf as the deepest match instead of the generic itself. */ addAccessibleTask( `
hello world
Mozilla

I am some other text
`, async function (browser, docAcc) { const generic = findAccessibleChildByID(docAcc, "generic"); const invisible = findAccessibleChildByID(docAcc, "invisible"); const dpr = await getContentDPR(browser); await testChildAtPoint( dpr, 1, 1, generic, invisible, // Direct Child invisible.firstChild // Deepest Child ); }, { chrome: false, iframe: true, remoteIframe: true } ); /** * Verify that hit testing correctly ignores * elements with pointer-events: none; */ addAccessibleTask( `
`, async function (browser, docAcc) { const container = findAccessibleChildByID(docAcc, "container"); const obscured = findAccessibleChildByID(docAcc, "obscured"); const clickable = findAccessibleChildByID(docAcc, "clickable"); const dpr = await getContentDPR(browser); let [targetX, targetY, targetW, targetH] = Layout.getBounds(obscured, dpr); const [x, y] = Layout.getBounds(docAcc, dpr); await testChildAtPoint( dpr, targetX - x + targetW / 2, targetY - y + targetH / 2, docAcc, container, // Direct Child obscured // Deepest Child ); [targetX, targetY, targetW, targetH] = Layout.getBounds(clickable, dpr); await testChildAtPoint( dpr, targetX - x + targetW / 2, targetY - y + targetH / 2, docAcc, clickable, // Direct Child clickable // Deepest Child ); }, { chrome: false, iframe: true, remoteIframe: true } );