modify-around-non-editable-span.html (5795B)
1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Selection.modify() shouldn't move caret into non-editable nodes</title> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="../../editing/include/editor-test-utils.js"></script> 9 <script> 10 "use strict"; 11 12 addEventListener("load", () => { 13 const editingHost = document.querySelector("div[contenteditable]"); 14 editingHost.focus(); 15 const precedingWhiteSpaces = editingHost.firstChild; 16 const middleText = editingHost.querySelector("span").nextSibling; 17 const trailingWhiteSpaces = editingHost.lastChild; 18 for (const callSelectAllChildren of [false, true]) { 19 for (const direction of ["forward", "right"]) { 20 test(() => { 21 if (callSelectAllChildren) { 22 getSelection().selectAllChildren(editingHost); 23 } 24 getSelection().collapse(precedingWhiteSpaces, precedingWhiteSpaces.length); 25 getSelection().modify("move", direction, "character"); 26 assert_in_array( 27 EditorTestUtils.getRangeDescription(getSelection().getRangeAt(0)), 28 [ 29 // start of editable region at middle of the line 30 EditorTestUtils.getRangeDescription( 31 { startContainer: editingHost, startOffset: 2, endContainer: editingHost, endOffset: 2 }), 32 EditorTestUtils.getRangeDescription( 33 { startContainer: middleText, startOffset: 0, endContainer: middleText, endOffset: 0 }), 34 ] 35 ); 36 }, `getSelection().modify("move", "${direction}", "character") ${ 37 callSelectAllChildren ? "after getSelection().selectAllChildren(editingHost) " : "" 38 }when " []<span contenteditable=false>"`); 39 test(() => { 40 if (callSelectAllChildren) { 41 getSelection().selectAllChildren(editingHost); 42 } 43 getSelection().collapse(middleText, middleText.length); 44 getSelection().modify("move", direction, "character"); 45 assert_in_array( 46 EditorTestUtils.getRangeDescription(getSelection().getRangeAt(0)), 47 [ 48 // At start of trailing invisible white spaces 49 EditorTestUtils.getRangeDescription( 50 { startContainer: editingHost, startOffset: 4, endContainer: editingHost, endOffset: 4 }), 51 EditorTestUtils.getRangeDescription( 52 { startContainer: trailingWhiteSpaces, startOffset: 0, endContainer: trailingWhiteSpaces, endOffset: 0 }), 53 // or at end of trailing invisible white spaces 54 EditorTestUtils.getRangeDescription( 55 { startContainer: editingHost, startOffset: 5, endContainer: editingHost, endOffset: 5 }), 56 EditorTestUtils.getRangeDescription( 57 { startContainer: trailingWhiteSpaces, startOffset: trailingWhiteSpaces.length, endContainer: trailingWhiteSpaces, endOffset: trailingWhiteSpaces.length }), 58 ] 59 ); 60 }, `getSelection().modify("move", "${direction}", "character") ${ 61 callSelectAllChildren ? "after getSelection().selectAllChildren(editingHost) " : "" 62 }when "editable[]<span contenteditable=false>"`); 63 } 64 for (const direction of ["backward", "left"]) { 65 test(() => { 66 if (callSelectAllChildren) { 67 getSelection().selectAllChildren(editingHost); 68 } 69 getSelection().collapse(middleText, 0); 70 getSelection().modify("move", direction, "character"); 71 assert_in_array( 72 EditorTestUtils.getRangeDescription(getSelection().getRangeAt(0)), 73 [ 74 // At end of preceding invisible white spaces 75 EditorTestUtils.getRangeDescription( 76 { startContainer: editingHost, startOffset: 1, endContainer: editingHost, endOffset: 1 }), 77 EditorTestUtils.getRangeDescription( 78 { startContainer: precedingWhiteSpaces, startOffset: 1, endContainer: precedingWhiteSpaces, endOffset: 1 }), 79 // or start of preceding invisible whites spaces 80 EditorTestUtils.getRangeDescription( 81 { startContainer: editingHost, startOffset: 0, endContainer: editingHost, endOffset: 0 }), 82 EditorTestUtils.getRangeDescription( 83 { startContainer: precedingWhiteSpaces, startOffset: 0, endContainer: precedingWhiteSpaces, endOffset: 0 }), 84 ] 85 ); 86 }, `getSelection().modify("move", "${direction}", "character") ${ 87 callSelectAllChildren ? "after getSelection().selectAllChildren(editingHost) " : "" 88 }when " <span contenteditable=false>...</span>[]editable"`); 89 test(() => { 90 if (callSelectAllChildren) { 91 getSelection().selectAllChildren(editingHost); 92 } 93 getSelection().collapse(trailingWhiteSpaces, 0); 94 getSelection().modify("move", direction, "character"); 95 assert_in_array( 96 EditorTestUtils.getRangeDescription(getSelection().getRangeAt(0)), 97 [ 98 // end of editable region at middle of the line 99 EditorTestUtils.getRangeDescription( 100 { startContainer: editingHost, startOffset: 3, endContainer: editingHost, endOffset: 3 }), 101 EditorTestUtils.getRangeDescription( 102 { startContainer: middleText, startOffset: middleText.length, endContainer: middleText, endOffset: middleText.length }), 103 ] 104 ); 105 }, `getSelection().modify("move", "${direction}", "character") ${ 106 callSelectAllChildren ? "after getSelection().selectAllChildren(editingHost) " : "" 107 }when "editable<span contenteditable=false>...</span>[] "`); 108 } 109 } 110 }, {once: true}); 111 </script> 112 </head> 113 <body> 114 <div contenteditable> <span contenteditable="false">non-editable</span>editable<span contenteditable="false">non-editable</span> </div> 115 </body> 116 </html>