AbstractRange_getShrunkenRangeToVisibleLeaves.html (6197B)
1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Testing SelectionMovementUtils::Get(First|Last)VisiblePointAtLeaf</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 container = document.getElementById("container"); 14 // EditorTestUtils can initialize selection even without editable nodes so 15 // that we can use it. 16 const utils = new EditorTestUtils(container); 17 const greenImageSrc = 18 "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAE0lEQVR4nGNk+M+ADJgYGCjiAwBPkgEJOTC6CgAAAABJRU5ErkJggg=="; 19 for (const data of [ 20 { 21 innerHTML: "{<div><span>abc</span></div>}", 22 expectedRange: function () { 23 return { 24 startContainer: container.querySelector("span").firstChild, 25 startOffset: 0, 26 endContainer: container.querySelector("span").firstChild, 27 endOffset: "abc".length, 28 }; 29 }, 30 }, 31 { 32 innerHTML: "{<div style=user-select:none><span>abc</span></div>}", 33 expectedRange: function () { 34 return { 35 startContainer: container, 36 startOffset: 0, 37 endContainer: container, 38 endOffset: 1, 39 }; 40 }, 41 }, 42 { 43 innerHTML: "{<div><span style=user-select:none>abc</span></div>}", 44 expectedRange: function () { 45 return { 46 startContainer: container.querySelector("div"), 47 startOffset: 0, 48 endContainer: container.querySelector("div"), 49 endOffset: 1, 50 }; 51 }, 52 }, 53 { 54 // Invisible <div>s should be ignored. 55 innerHTML: "{<div style=display:none>ABC</div><div><span>def</span></div><div style=display:none>GHI</div>}", 56 expectedRange: function () { 57 return { 58 startContainer: container.querySelector("span").firstChild, 59 startOffset: 0, 60 endContainer: container.querySelector("span").firstChild, 61 endOffset: "def".length, 62 }; 63 }, 64 }, 65 { 66 // First/last unselectable elements should be ignored. 67 innerHTML: "<div style=user-select:none>[ABC</div><div><span>def</span></div><div style=user-select:none>GHI]</div>", 68 expectedRange: function () { 69 return { 70 startContainer: container.querySelector("span").firstChild, 71 startOffset: 0, 72 endContainer: container.querySelector("span").firstChild, 73 endOffset: "def".length, 74 }; 75 }, 76 }, 77 { 78 innerHTML: "<div style=user-select:none>{<div><span style=user-select:text>abc</span></div>}</div>", 79 expectedRange: function () { 80 return { 81 startContainer: container.querySelector("span").firstChild, 82 startOffset: 0, 83 endContainer: container.querySelector("span").firstChild, 84 endOffset: "abc".length, 85 }; 86 }, 87 }, 88 { 89 innerHTML: "<div style=user-select:none>{<span>ABC</span><span style=user-select:text>def</span><span>GHI</span>}</div>", 90 expectedRange: function () { 91 return { 92 startContainer: container.querySelector("span[style]").firstChild, 93 startOffset: 0, 94 endContainer: container.querySelector("span[style]").firstChild, 95 endOffset: "def".length, 96 }; 97 }, 98 }, 99 { 100 innerHTML: "<div style=user-select:none>{<div><span style=user-select:text><span style=user-select:none>abc</span></span></div>}</div>", 101 expectedRange: function () { 102 return { 103 startContainer: container.querySelector("span"), 104 startOffset: 0, 105 endContainer: container.querySelector("span"), 106 endOffset: 1, 107 }; 108 }, 109 }, 110 { 111 // Don't collapse into the <img> 112 innerHTML: `{<span><img src=${greenImageSrc}></span>}`, 113 expectedRange: function () { 114 return { 115 startContainer: container.querySelector("span"), 116 startOffset: 0, 117 endContainer: container.querySelector("span"), 118 endOffset: 1, 119 }; 120 }, 121 }, 122 { 123 // Don't collapse into the <input> 124 innerHTML: `{<span><input></span>}`, 125 expectedRange: function () { 126 return { 127 startContainer: container.querySelector("span"), 128 startOffset: 0, 129 endContainer: container.querySelector("span"), 130 endOffset: 1, 131 }; 132 }, 133 }, 134 { 135 // Don't collapse into the <button> 136 innerHTML: `{<span><button>ABC</button></span>}`, 137 expectedRange: function () { 138 return { 139 startContainer: container.querySelector("span"), 140 startOffset: 0, 141 endContainer: container.querySelector("span"), 142 endOffset: 1, 143 }; 144 }, 145 }, 146 { 147 // Treat the invisible <br> as invisible. 148 innerHTML: "{<div><span>abc</span><br></div>}", 149 expectedRange: function () { 150 return { 151 startContainer: container.querySelector("span").firstChild, 152 startOffset: 0, 153 endContainer: container.querySelector("div"), 154 endOffset: 2, 155 }; 156 }, 157 }, 158 { 159 // Treat the invisible <br> as invisible. 160 innerHTML: "{<div><span>abc<br></span></div>}", 161 expectedRange: function () { 162 return { 163 startContainer: container.querySelector("span").firstChild, 164 startOffset: 0, 165 endContainer: container.querySelector("span"), 166 endOffset: 2, 167 }; 168 }, 169 }, 170 ]) { 171 test( 172 () => { 173 utils.setupEditingHost(data.innerHTML); 174 container.getBoundingClientRect(); 175 assert_equals( 176 EditorTestUtils.getRangeDescription( 177 SpecialPowers.wrap( 178 getSelection().getRangeAt(0) 179 ).getShrunkenRangeToVisibleLeaves() 180 ), 181 EditorTestUtils.getRangeDescription(data.expectedRange()) 182 ); 183 }, 184 `getShrunkenRangeToVisibleLeaves() when ${ 185 data.innerHTML.replaceAll(greenImageSrc, "...") 186 }` 187 ); 188 } 189 }, {once: true}); 190 </script> 191 </head> 192 <body><div id="container"></div></body> 193 </html>