/* 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"; function selectedTextEventPromises(stateChangeType) { return [ waitForMacEventWithInfo("AXSelectedTextChanged", (elem, info) => { return ( info.AXTextStateChangeType == stateChangeType && elem.getAttributeValue("AXDOMIdentifier") == "body" ); }), waitForMacEventWithInfo("AXSelectedTextChanged", (elem, info) => { return ( info.AXTextStateChangeType == stateChangeType && elem.getAttributeValue("AXDOMIdentifier") == "input" ); }), ]; } async function testInput(browser, accDoc) { let input = getNativeInterface(accDoc, "input"); is(input.getAttributeValue("AXDescription"), "Name", "Correct input label"); is(input.getAttributeValue("AXTitle"), "", "Correct input title"); is(input.getAttributeValue("AXValue"), "Elmer Fudd", "Correct input value"); is( input.getAttributeValue("AXNumberOfCharacters"), 10, "Correct length of value" ); ok(input.attributeNames.includes("AXSelectedText"), "Has AXSelectedText"); ok( input.attributeNames.includes("AXSelectedTextRange"), "Has AXSelectedTextRange" ); let evt = Promise.all([ waitForMacEvent("AXFocusedUIElementChanged", "input"), ...selectedTextEventPromises(AXTextStateChangeTypeSelectionMove), ]); await SpecialPowers.spawn(browser, [], () => { content.document.getElementById("input").focus(); }); await evt; evt = Promise.all( selectedTextEventPromises(AXTextStateChangeTypeSelectionExtend) ); await SpecialPowers.spawn(browser, [], () => { let elm = content.document.getElementById("input"); if (elm.setSelectionRange) { elm.setSelectionRange(6, 9); } else { let r = new content.Range(); let textNode = elm.firstElementChild.firstChild; r.setStart(textNode, 6); r.setEnd(textNode, 9); let s = content.getSelection(); s.removeAllRanges(); s.addRange(r); } }); await evt; is( input.getAttributeValue("AXSelectedText"), "Fud", "Correct text is selected" ); Assert.deepEqual( input.getAttributeValue("AXSelectedTextRange"), [6, 3], "correct range selected" ); ok( input.isAttributeSettable("AXSelectedTextRange"), "AXSelectedTextRange is settable" ); evt = Promise.all( selectedTextEventPromises(AXTextStateChangeTypeSelectionExtend) ); input.setAttributeValue("AXSelectedTextRange", NSRange(1, 7)); await evt; Assert.deepEqual( input.getAttributeValue("AXSelectedTextRange"), [1, 7], "correct range selected" ); is( input.getAttributeValue("AXSelectedText"), "lmer Fu", "Correct text is selected" ); let domSelection = await SpecialPowers.spawn(browser, [], () => { let elm = content.document.querySelector("input#input"); if (elm) { return elm.value.substring(elm.selectionStart, elm.selectionEnd); } return content.getSelection().toString(); }); is(domSelection, "lmer Fu", "correct DOM selection"); is( input.getParameterizedAttributeValue("AXStringForRange", NSRange(3, 5)), "er Fu", "AXStringForRange works" ); } /** * Input selection test */ addAccessibleTask( ``, testInput ); /** * contenteditable selection test */ addAccessibleTask( `

Elmer Fudd

`, testInput ); /** * test contenteditable with selection that extends past editable part */ addAccessibleTask( `Elmer Fudd is the name`, async (browser, accDoc) => { let evt = Promise.all([ waitForMacEvent("AXFocusedUIElementChanged", "input"), waitForMacEvent("AXSelectedTextChanged", "body"), waitForMacEvent("AXSelectedTextChanged", "input"), ]); await SpecialPowers.spawn(browser, [], () => { content.document.getElementById("input").focus(); }); await evt; evt = waitForEvent(EVENT_TEXT_CARET_MOVED); await SpecialPowers.spawn(browser, [], () => { let input = content.document.getElementById("input"); let notinput = content.document.getElementById("notinput"); let r = new content.Range(); r.setStart(input.firstChild, 4); r.setEnd(notinput.firstChild, 6); let s = content.getSelection(); s.removeAllRanges(); s.addRange(r); }); await evt; let input = getNativeInterface(accDoc, "input"); is( input.getAttributeValue("AXSelectedText"), "r Fudd", "Correct text is selected in #input" ); is( stringForRange( input, input.getAttributeValue("AXSelectedTextMarkerRange") ), "r Fudd is the", "Correct text is selected in document" ); } ); /** * test nested content editables and their ancestor getters. */ addAccessibleTask( `

Bob Loblaw's

Law Blog
`, (browser, accDoc) => { let link = getNativeInterface(accDoc, "link"); let innerLink = getNativeInterface(accDoc, "inner_link"); let idmatches = (elem, id) => { is(elem.getAttributeValue("AXDOMIdentifier"), id, "Matches ID"); }; idmatches(link.getAttributeValue("AXEditableAncestor"), "outer"); idmatches(link.getAttributeValue("AXFocusableAncestor"), "outer"); idmatches(link.getAttributeValue("AXHighestEditableAncestor"), "outer"); idmatches(innerLink.getAttributeValue("AXEditableAncestor"), "inner"); idmatches(innerLink.getAttributeValue("AXFocusableAncestor"), "inner"); idmatches( innerLink.getAttributeValue("AXHighestEditableAncestor"), "outer" ); } );