| <!DOCTYPE html> |
| <script src="../resources/testharness.js"></script> |
| <script src="../resources/testharnessreport.js"></script> |
| |
| <div id="main" role="main"> |
| |
| <div id="contenteditable-textbox" role="textbox" contenteditable="true"> |
| <div id="contenteditable-line1">Line 1</div> |
| <textarea id="contenteditable-line2" rows="1" cols="40">Line 2</textarea> |
| </div> |
| |
| <div id="contenteditable-div" contenteditable> |
| <p id="paragraph1">Line 1<br> |
| Line 2</p> |
| <p id="paragraph2">Line 3</p> |
| </div> |
| |
| <div id="contenteditable-div-2" contenteditable role="textbox" |
| style="max-width: 5px; overflow-wrap: normal;"> |
| Line 1<br> |
| Line 2 |
| </div> |
| |
| </div> |
| |
| <script> |
| test(function() |
| { |
| let mainAccessible = accessibilityController.accessibleElementById("main"); |
| |
| assert_equals(mainAccessible.selectionAnchorObject, null); |
| assert_equals(mainAccessible.selectionAnchorOffset, -1); |
| assert_equals(mainAccessible.selectionFocusObject, null); |
| assert_equals(mainAccessible.selectionFocusOffset, -1); |
| }, "Initially there should be no selection under the main object."); |
| |
| test(function() |
| { |
| let rootAccessible = accessibilityController.rootElement; |
| |
| assert_equals(rootAccessible.selectionAnchorObject, null); |
| assert_equals(rootAccessible.selectionAnchorOffset, -1); |
| assert_equals(rootAccessible.selectionFocusObject, null); |
| assert_equals(rootAccessible.selectionFocusOffset, -1); |
| }, "Initially there should be no selection on the root object."); |
| |
| test(function() |
| { |
| let textbox = document.getElementById("contenteditable-textbox"); |
| textbox.focus(); |
| let textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); |
| |
| assert_equals(textboxAccessible.selectionAnchorObject, textboxAccessible); |
| assert_equals(textboxAccessible.selectionAnchorOffset, 0); |
| assert_equals(textboxAccessible.selectionFocusObject, textboxAccessible); |
| assert_equals(textboxAccessible.selectionFocusOffset, 0); |
| }, "Moving the focus to an ARIA textbox should place the caret at its beginning."); |
| |
| test(function() |
| { |
| let selection = window.getSelection(); |
| let selectionRange = document.createRange(); |
| let textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); |
| let mainAccessible = accessibilityController.accessibleElementById("main"); |
| let rootAccessible = accessibilityController.rootElement; |
| let line1 = document.getElementById("contenteditable-line1"); |
| let line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1"); |
| let line1TextAccessible = line1Accessible.childAtIndex(0); |
| |
| selectionRange.setStart(line1.firstChild, 1); |
| selectionRange.setEnd(line1.firstChild, 1); |
| selection.removeAllRanges(); |
| selection.addRange(selectionRange); |
| |
| assert_equals(textboxAccessible.selectionAnchorObject, line1TextAccessible); |
| assert_equals(textboxAccessible.selectionAnchorOffset, 1); |
| assert_equals(textboxAccessible.selectionFocusObject, line1TextAccessible); |
| assert_equals(textboxAccessible.selectionFocusOffset, 1); |
| |
| assert_equals(mainAccessible.selectionAnchorObject, line1TextAccessible); |
| assert_equals(mainAccessible.selectionAnchorOffset, 1); |
| assert_equals(mainAccessible.selectionFocusObject, line1TextAccessible); |
| assert_equals(mainAccessible.selectionFocusOffset, 1); |
| |
| assert_equals(rootAccessible.selectionAnchorObject, line1TextAccessible); |
| assert_equals(rootAccessible.selectionAnchorOffset, 1); |
| assert_equals(rootAccessible.selectionFocusObject, line1TextAccessible); |
| assert_equals(rootAccessible.selectionFocusOffset, 1); |
| }, "Setting a new caret position in the ARIA textbox should be reflected in the accessibility APIs."); |
| |
| test(function() |
| { |
| let selection = window.getSelection(); |
| let textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); |
| let mainAccessible = accessibilityController.accessibleElementById("main"); |
| let rootAccessible = accessibilityController.rootElement; |
| |
| selection.removeAllRanges(); |
| |
| assert_equals(textboxAccessible.selectionAnchorObject, null); |
| assert_equals(textboxAccessible.selectionAnchorOffset, -1); |
| assert_equals(textboxAccessible.selectionFocusObject, null); |
| assert_equals(textboxAccessible.selectionFocusOffset, -1); |
| |
| assert_equals(mainAccessible.selectionAnchorObject, null); |
| assert_equals(mainAccessible.selectionAnchorOffset, -1); |
| assert_equals(mainAccessible.selectionFocusObject, null); |
| assert_equals(mainAccessible.selectionFocusOffset, -1); |
| |
| assert_equals(rootAccessible.selectionAnchorObject, null); |
| assert_equals(rootAccessible.selectionAnchorOffset, -1); |
| assert_equals(rootAccessible.selectionFocusObject, null); |
| assert_equals(rootAccessible.selectionFocusOffset, -1); |
| }, "Removing the selection should remove the caret completely."); |
| |
| test(function() |
| { |
| let selection = window.getSelection(); |
| let textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); |
| let mainAccessible = accessibilityController.accessibleElementById("main"); |
| let rootAccessible = accessibilityController.rootElement; |
| let line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1"); |
| let line1TextAccessible = line1Accessible.childAtIndex(0); |
| |
| line1TextAccessible.setSelectedTextRange(2, 0); |
| |
| assert_equals(textboxAccessible.selectionAnchorObject, line1TextAccessible); |
| assert_equals(textboxAccessible.selectionAnchorOffset, 2); |
| assert_equals(textboxAccessible.selectionFocusObject, line1TextAccessible); |
| assert_equals(textboxAccessible.selectionFocusOffset, 2); |
| |
| assert_equals(mainAccessible.selectionAnchorObject, line1TextAccessible); |
| assert_equals(mainAccessible.selectionAnchorOffset, 2); |
| assert_equals(mainAccessible.selectionFocusObject, line1TextAccessible); |
| assert_equals(mainAccessible.selectionFocusOffset, 2); |
| |
| assert_equals(rootAccessible.selectionAnchorObject, line1TextAccessible); |
| assert_equals(rootAccessible.selectionAnchorOffset, 2); |
| assert_equals(rootAccessible.selectionFocusObject, line1TextAccessible); |
| assert_equals(rootAccessible.selectionFocusOffset, 2); |
| }, "Positioning the caret using the accessibility API instead of the DOM should work."); |
| |
| test(function() |
| { |
| let line2Accessible = accessibilityController.accessibleElementById("contenteditable-line2"); |
| let textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); |
| let mainAccessible = accessibilityController.accessibleElementById("main"); |
| let line2 = document.getElementById("contenteditable-line2"); |
| line2.focus(); |
| |
| assert_equals(line2Accessible.selectionAnchorObject, line2Accessible); |
| assert_equals(line2Accessible.selectionAnchorOffset, 0); |
| assert_equals(line2Accessible.selectionFocusObject, line2Accessible); |
| assert_equals(line2Accessible.selectionFocusOffset, 0); |
| |
| assert_equals(textboxAccessible.selectionAnchorObject, line2Accessible); |
| assert_equals(textboxAccessible.selectionAnchorOffset, 0); |
| assert_equals(textboxAccessible.selectionFocusObject, line2Accessible); |
| assert_equals(textboxAccessible.selectionFocusOffset, 0); |
| |
| assert_equals(mainAccessible.selectionAnchorObject, line2Accessible); |
| assert_equals(mainAccessible.selectionAnchorOffset, 0); |
| assert_equals(mainAccessible.selectionFocusObject, line2Accessible); |
| assert_equals(mainAccessible.selectionFocusOffset, 0); |
| }, "Moving the focus into a textarea should remove the caret from the ARIA textbox."); |
| |
| test(function() |
| { |
| document.getElementById("contenteditable-line2").focus(); |
| let rootAccessible = accessibilityController.rootElement; |
| let line2Accessible = accessibilityController.focusedElement; |
| |
| assert_equals(rootAccessible.selectionAnchorObject, line2Accessible); |
| assert_equals(rootAccessible.selectionAnchorOffset, 0); |
| assert_equals(rootAccessible.selectionFocusObject, line2Accessible); |
| assert_equals(rootAccessible.selectionFocusOffset, 0); |
| |
| assert_equals(line2Accessible.selectionAnchorObject, line2Accessible); |
| assert_equals(line2Accessible.selectionAnchorOffset, 0); |
| assert_equals(line2Accessible.selectionFocusObject, line2Accessible); |
| assert_equals(line2Accessible.selectionFocusOffset, 0); |
| }, "Standard text fields start with the caret at the beginning of their contents."); |
| |
| test(function() |
| { |
| let line2 = document.getElementById("contenteditable-line2"); |
| line2.focus(); |
| let line2Accessible = accessibilityController.focusedElement; |
| |
| line2.setSelectionRange(3, 3); |
| |
| assert_equals(line2Accessible.selectionAnchorObject, line2Accessible); |
| assert_equals(line2Accessible.selectionAnchorOffset, 3); |
| assert_equals(line2Accessible.selectionFocusObject, line2Accessible); |
| assert_equals(line2Accessible.selectionFocusOffset, 3); |
| }, "Setting a new caret position in the textarea should be exposed in the accessibility APIs."); |
| |
| test(function() |
| { |
| let textboxAccessible = accessibilityController.accessibleElementById("contenteditable-textbox"); |
| let mainAccessible = accessibilityController.accessibleElementById("main"); |
| let rootAccessible = accessibilityController.rootElement; |
| document.getElementById("contenteditable-line2").focus(); |
| let line2Accessible = accessibilityController.focusedElement; |
| |
| assert_equals(textboxAccessible.selectionAnchorObject, line2Accessible); |
| assert_equals(textboxAccessible.selectionAnchorOffset, 3); |
| assert_equals(textboxAccessible.selectionFocusObject, line2Accessible); |
| assert_equals(textboxAccessible.selectionFocusOffset, 3); |
| |
| assert_equals(mainAccessible.selectionAnchorObject, line2Accessible); |
| assert_equals(mainAccessible.selectionAnchorOffset, 3); |
| assert_equals(mainAccessible.selectionFocusObject, line2Accessible); |
| assert_equals(mainAccessible.selectionFocusOffset, 3); |
| |
| assert_equals(rootAccessible.selectionAnchorObject, line2Accessible); |
| assert_equals(rootAccessible.selectionAnchorOffset, 3); |
| assert_equals(rootAccessible.selectionFocusObject, line2Accessible); |
| assert_equals(rootAccessible.selectionFocusOffset, 3); |
| }, "Offsets in text fields should be reported from the beginning of the field and not from the top of the container."); |
| |
| test(function() |
| { |
| var line1Accessible = accessibilityController.accessibleElementById("contenteditable-line1"); |
| var line2Accessible = accessibilityController.accessibleElementById("contenteditable-line2"); |
| |
| assert_equals(line1Accessible.selectionAnchorObject, line2Accessible); |
| assert_equals(line1Accessible.selectionAnchorOffset, 3); |
| assert_equals(line1Accessible.selectionFocusObject, line2Accessible); |
| assert_equals(line1Accessible.selectionFocusOffset, 3); |
| assert_equals(line2Accessible.selectionAnchorObject, line2Accessible); |
| assert_equals(line2Accessible.selectionAnchorOffset, 3); |
| assert_equals(line2Accessible.selectionFocusObject, line2Accessible); |
| assert_equals(line2Accessible.selectionFocusOffset, 3); |
| }, "The caret position should be retrievable from any object."); |
| |
| test(function() |
| { |
| const selection = window.getSelection(); |
| const selectionRange = document.createRange(); |
| const mainAccessible = accessibilityController.accessibleElementById("main"); |
| const rootAccessible = accessibilityController.rootElement; |
| |
| const contenteditable = document.getElementById("contenteditable-div"); |
| contenteditable.focus(); |
| // The offset from the newline character between the two lines of the |
| // first paragraph to the first character of its second line. |
| // (Needed for skipping wide space.) |
| const line2StartOffset = 13; |
| |
| const line1 = document.getElementById("paragraph1").firstChild; |
| const line2 = document.getElementById("paragraph1").lastChild; |
| const line3 = document.getElementById("paragraph2").firstChild; |
| const contenteditableLines = [ line1, line2, line3 ]; |
| |
| const contenteditableAccessible = accessibilityController.accessibleElementById("contenteditable-div"); |
| const paragraph1Accessible = accessibilityController.accessibleElementById("paragraph1"); |
| const paragraph2Accessible = accessibilityController.accessibleElementById("paragraph2"); |
| const line1Accessible = paragraph1Accessible.childAtIndex(0); |
| const line2Accessible = paragraph1Accessible.childAtIndex(2); |
| const line3Accessible = paragraph2Accessible.childAtIndex(0); |
| const expectations = [ |
| line1Accessible, line2Accessible, line3Accessible |
| ]; |
| |
| for (let lineNumber = 0; lineNumber < 3; ++lineNumber) { |
| for (let characterOffset = 0; characterOffset < 7; ++characterOffset) { |
| // Any widespace in the DOM should be stripped out in the |
| // accessibility tree. |
| let selectionOffset = characterOffset; |
| if (lineNumber == 1) |
| selectionOffset += line2StartOffset; |
| |
| selectionRange.setStart(contenteditableLines[lineNumber], selectionOffset); |
| selectionRange.setEnd(contenteditableLines[lineNumber], selectionOffset); |
| selection.removeAllRanges(); |
| selection.addRange(selectionRange); |
| |
| assert_equals(contenteditableAccessible.selectionAnchorObject, expectations[lineNumber]); |
| assert_equals(contenteditableAccessible.selectionAnchorOffset, characterOffset); |
| assert_equals(contenteditableAccessible.selectionFocusObject, expectations[lineNumber]); |
| assert_equals(contenteditableAccessible.selectionFocusOffset, characterOffset); |
| |
| assert_equals(mainAccessible.selectionAnchorObject, expectations[lineNumber]); |
| assert_equals(mainAccessible.selectionAnchorOffset, characterOffset); |
| assert_equals(mainAccessible.selectionFocusObject, expectations[lineNumber]); |
| assert_equals(mainAccessible.selectionFocusOffset, characterOffset); |
| |
| assert_equals(rootAccessible.selectionAnchorObject, expectations[lineNumber]); |
| assert_equals(rootAccessible.selectionAnchorOffset, characterOffset); |
| assert_equals(rootAccessible.selectionFocusObject, expectations[lineNumber]); |
| assert_equals(rootAccessible.selectionFocusOffset, characterOffset); |
| } |
| } |
| |
| }, "Test moving the caret across two paragraphs by re-creating the selection."); |
| |
| test(function() |
| { |
| const selection = window.getSelection(); |
| const selectionRange = document.createRange(); |
| const mainAccessible = accessibilityController.accessibleElementById("main"); |
| const rootAccessible = accessibilityController.rootElement; |
| |
| const contenteditable = document.getElementById("contenteditable-div"); |
| contenteditable.focus(); |
| |
| const line1 = document.getElementById("paragraph1").firstChild; |
| selectionRange.setStart(line1, 0); |
| selectionRange.setEnd(line1, 0); |
| selection.removeAllRanges(); |
| selection.addRange(selectionRange); |
| |
| const contenteditableAccessible = accessibilityController.accessibleElementById("contenteditable-div"); |
| const paragraph1Accessible = accessibilityController.accessibleElementById("paragraph1"); |
| const paragraph2Accessible = accessibilityController.accessibleElementById("paragraph2"); |
| const line1Accessible = paragraph1Accessible.childAtIndex(0); |
| const line2Accessible = paragraph1Accessible.childAtIndex(2); |
| const line3Accessible = paragraph2Accessible.childAtIndex(0); |
| const expectations = [ |
| line1Accessible, line2Accessible, line3Accessible |
| ]; |
| |
| for (let lineNumber = 0; lineNumber < 3; ++lineNumber) { |
| for (let characterOffset = 0; characterOffset < 7; ++characterOffset) { |
| assert_equals(contenteditableAccessible.selectionAnchorObject, expectations[lineNumber]); |
| assert_equals(contenteditableAccessible.selectionAnchorOffset, characterOffset); |
| assert_equals(contenteditableAccessible.selectionFocusObject, expectations[lineNumber]); |
| assert_equals(contenteditableAccessible.selectionFocusOffset, characterOffset); |
| |
| assert_equals(mainAccessible.selectionAnchorObject, expectations[lineNumber]); |
| assert_equals(mainAccessible.selectionAnchorOffset, characterOffset); |
| assert_equals(mainAccessible.selectionFocusObject, expectations[lineNumber]); |
| assert_equals(mainAccessible.selectionFocusOffset, characterOffset); |
| |
| assert_equals(rootAccessible.selectionAnchorObject, expectations[lineNumber]); |
| assert_equals(rootAccessible.selectionAnchorOffset, characterOffset); |
| assert_equals(rootAccessible.selectionFocusObject, expectations[lineNumber]); |
| assert_equals(rootAccessible.selectionFocusOffset, characterOffset); |
| |
| selection.modify('move', 'forward', 'character'); |
| } |
| } |
| |
| }, "Test moving the caret across two paragraphs by modifying the existing selection."); |
| |
| test(function() |
| { |
| const selection = window.getSelection(); |
| const selectionRange = document.createRange(); |
| const mainAccessible = accessibilityController.accessibleElementById("main"); |
| const rootAccessible = accessibilityController.rootElement; |
| |
| const contenteditable = document.getElementById('contenteditable-div-2'); |
| contenteditable.focus(); |
| selectionRange.setStart(contenteditable, 0); |
| selectionRange.setEnd(contenteditable, 0); |
| selection.removeAllRanges(); |
| selection.addRange(selectionRange); |
| |
| const contenteditableAccessible = accessibilityController.accessibleElementById('contenteditable-div-2'); |
| const line1Accessible = contenteditableAccessible.childAtIndex(0); |
| const line2Accessible = contenteditableAccessible.childAtIndex(2); |
| const expectations = [ line1Accessible, line2Accessible ]; |
| |
| for (let lineNumber = 0; lineNumber < 2; ++lineNumber) { |
| for (let characterOffset = 0; characterOffset < 7; ++characterOffset) { |
| assert_equals(contenteditableAccessible.selectionAnchorObject, expectations[lineNumber]); |
| assert_equals(contenteditableAccessible.selectionAnchorOffset, characterOffset); |
| assert_equals(contenteditableAccessible.selectionFocusObject, expectations[lineNumber]); |
| assert_equals(contenteditableAccessible.selectionFocusOffset, characterOffset); |
| |
| assert_equals(mainAccessible.selectionAnchorObject, expectations[lineNumber]); |
| assert_equals(mainAccessible.selectionAnchorOffset, characterOffset); |
| assert_equals(mainAccessible.selectionFocusObject, expectations[lineNumber]); |
| assert_equals(mainAccessible.selectionFocusOffset, characterOffset); |
| |
| assert_equals(rootAccessible.selectionAnchorObject, expectations[lineNumber]); |
| assert_equals(rootAccessible.selectionAnchorOffset, characterOffset); |
| assert_equals(rootAccessible.selectionFocusObject, expectations[lineNumber]); |
| assert_equals(rootAccessible.selectionFocusOffset, characterOffset); |
| |
| selection.modify('move', 'forward', 'character'); |
| } |
| } |
| |
| }, "Test moving the caret across two lines that wrap by modifying the existing selection."); |
| </script> |