input-events-get-target-ranges-joining-dl-element-and-another-list.tentative.html (11489B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <meta name="timeout" content="long"> 4 <meta name="variant" content="?Backspace"> 5 <meta name="variant" content="?Delete"> 6 <title>InputEvent.getTargetRanges() at joining dl element and ol or ul element</title> 7 <div contenteditable></div> 8 <script src="input-events-get-target-ranges.js"></script> 9 <script src="/resources/testharness.js"></script> 10 <script src="/resources/testharnessreport.js"></script> 11 <script src="/resources/testdriver.js"></script> 12 <script src="/resources/testdriver-vendor.js"></script> 13 <script src="/resources/testdriver-actions.js"></script> 14 <script> 15 "use strict"; 16 17 const action = location.search.substring(1); 18 function run() { 19 switch (action) { 20 case "Backspace": 21 return sendBackspaceKey(); 22 case "Delete": 23 return sendDeleteKey(); 24 default: 25 throw "Unhandled variant"; 26 } 27 } 28 29 /** 30 * @param innerHTML Initial `innerHTML` value of the editor. 31 * @param data 32 * expectedInnerHTML 33 * Expected `innerHTML` of the editor after calling 34 * `run()`. This can be array of string if there are 35 * some acceptable differences like whether there is 36 * an invisible `<br>` element at end of list item. 37 * expectedTargetRanges 38 * `null` or `unspecified` if `beforeinput` event shouldn't 39 * be fired. 40 * Otherwise, function returning an array of objects 41 * which have `startContainer`, `startOffset`, 42 * `endContainer`, `endOffset`. This will be called 43 * before calling `run()` and compared with 44 * `getTargetRanges()` after that. 45 * expectInputEvent: 46 * `true` if it should cause an `input` event. 47 */ 48 function addPromiseTest(innerHTML, data) { 49 promise_test(async (t) => { 50 initializeTest(innerHTML); 51 let expectedTargetRanges = 52 typeof data.expectedTargetRanges === "function" 53 ? data.expectedTargetRanges() 54 : null; 55 await run(); 56 checkEditorContentResultAsSubTest(data.expectedInnerHTML, t.name); 57 if (expectedTargetRanges !== null) { 58 checkGetTargetRangesOfBeforeinputOnDeleteSomething(expectedTargetRanges); 59 if (data.expectInputEvent) { 60 checkGetTargetRangesOfInputOnDeleteSomething(); 61 } else { 62 checkGetTargetRangesOfInputOnDoNothing(); 63 } 64 } else { 65 checkBeforeinputAndInputEventsOnNOOP(); 66 } 67 }, `${action} at "${innerHTML}"`); 68 } 69 70 // TODO: This file does not have tests for the cases joining dl elements and 71 // parent or child ul/ol elements. They should be added, but perhaps, 72 // they are edge cases. 73 74 // Joining dl with ul/ol list element 75 for (let otherList of ["ul", "ol"]) { 76 for (let firstItem of ["dt", "dd"]) { 77 addPromiseTest( 78 action === "Backspace" 79 ? `<${otherList}><li>list-item1</li></${otherList}><dl><${firstItem}>[]list-item2</${firstItem}></dl>` 80 : `<${otherList}><li>list-item1[]</li></${otherList}><dl><${firstItem}>list-item2</${firstItem}></dl>`, 81 { 82 expectedInnerHTML: `<${otherList}><li>list-item1list-item2</li></${otherList}>`, 83 expectedTargetRanges: () => { 84 return [ 85 { 86 startContainer: gEditor.querySelector("li").firstChild, 87 startOffset: gEditor.querySelector("li").firstChild.length, 88 endContainer: gEditor.querySelector(firstItem).firstChild, 89 endOffset: 0, 90 }, 91 ]; 92 }, 93 expectInputEvent: true, 94 } 95 ); 96 97 for (let secondItem of ["dt", "dd"]) { 98 addPromiseTest( 99 action === "Backspace" 100 ? `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}}>list-item2</${secondItem}></dl><${otherList}><li>[]list-item3</li></${otherList}>` 101 : `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>list-item2[]</${secondItem}></dl><${otherList}><li>list-item3</li></${otherList}>`, 102 { 103 expectedInnerHTML: `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>list-item2list-item3</${secondItem}></dl>`, 104 expectedTargetRanges: () => { 105 return [ 106 { 107 startContainer: gEditor.querySelector(`${firstItem} + ${secondItem}`).firstChild, 108 startOffset: gEditor.querySelector(`${firstItem} + ${secondItem}`).firstChild.length, 109 endContainer: gEditor.querySelector("li").firstChild, 110 endOffset: 0, 111 }, 112 ]; 113 }, 114 expectInputEvent: true, 115 } 116 ); 117 118 addPromiseTest( 119 `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>[list-item2</${secondItem}></dl><${otherList}><li>}list-item3</li></${otherList}>`, 120 { 121 expectedInnerHTML: 122 secondItem === "dt" 123 ? [ 124 `<dl><${firstItem}>list-item1</${firstItem}></dl><${otherList}><li>list-item3</li></${otherList}>`, 125 `<dl><${firstItem}>list-item1</${firstItem}></dl><${otherList}><li>list-item3<br></li></${otherList}>`, 126 ] 127 : [ 128 `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>`, 129 `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>list-item3<br></${secondItem}></dl>`, 130 ], 131 expectedTargetRanges: () => { 132 return [ 133 { 134 startContainer: gEditor.querySelector(`${firstItem} + ${secondItem}`).firstChild, 135 startOffset: 0, 136 endContainer: gEditor.querySelector("li"), 137 endOffset: 0, 138 }, 139 ]; 140 }, 141 expectInputEvent: true, 142 } 143 ); 144 145 addPromiseTest( 146 `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}>[list-item2</${secondItem}></dl><${otherList}><li>list-item3]</li></${otherList}>`, 147 { 148 expectedInnerHTML: `<dl><${firstItem}>list-item1</${firstItem}><${secondItem}><br></${secondItem}></dl>`, 149 expectedTargetRanges: () => { 150 return [ 151 { 152 startContainer: gEditor.querySelector(secondItem).firstChild, 153 startOffset: 0, 154 endContainer: gEditor.querySelector("li").firstChild, 155 endOffset: gEditor.querySelector("li").firstChild.length, 156 }, 157 ]; 158 }, 159 expectInputEvent: true, 160 } 161 ); 162 163 addPromiseTest( 164 `<dl><${firstItem}>[list-item1</${firstItem}><${secondItem}>list-item2</${secondItem}></dl><${otherList}><li>list-item3]</li></${otherList}>`, 165 { 166 expectedInnerHTML: `<dl><${firstItem}><br></${firstItem}></dl>`, 167 expectedTargetRanges: () => { 168 return [ 169 { 170 startContainer: gEditor.querySelector(firstItem).firstChild, 171 startOffset: 0, 172 endContainer: gEditor.querySelector("li").firstChild, 173 endOffset: gEditor.querySelector("li").firstChild.length, 174 }, 175 ]; 176 }, 177 expectInputEvent: true, 178 } 179 ); 180 181 addPromiseTest( 182 action === "Backspace" 183 ? `<${otherList}><li>list-item1</li></${otherList}><dl><${firstItem}>[]list-item2</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>` 184 : `<${otherList}><li>list-item1[]</li></${otherList}><dl><${firstItem}>list-item2</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>`, 185 { 186 expectedInnerHTML: `<${otherList}><li>list-item1list-item2</li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`, 187 expectedTargetRanges: () => { 188 return [ 189 { 190 startContainer: gEditor.querySelector("li").firstChild, 191 startOffset: gEditor.querySelector("li").firstChild.length, 192 endContainer: gEditor.querySelector(firstItem).firstChild, 193 endOffset: 0, 194 }, 195 ]; 196 }, 197 expectInputEvent: true, 198 } 199 ); 200 201 addPromiseTest( 202 `<${otherList}><li>[list-item1</li></${otherList}><dl><${firstItem}>}list-item2</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>`, 203 { 204 expectedInnerHTML: [ 205 `<${otherList}><li>list-item2</li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`, 206 `<${otherList}><li>list-item2<br></li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`, 207 ], 208 expectedTargetRanges: () => { 209 return [ 210 { 211 startContainer: gEditor.querySelector("li").firstChild, 212 startOffset: 0, 213 endContainer: gEditor.querySelector(firstItem), 214 endOffset: 0, 215 }, 216 ]; 217 }, 218 expectInputEvent: true, 219 } 220 ); 221 222 addPromiseTest( 223 `<${otherList}><li>[list-item1</li></${otherList}><dl><${firstItem}>list-item2]</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>`, 224 { 225 expectedInnerHTML: `<${otherList}><li><br></li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`, 226 expectedTargetRanges: () => { 227 return [ 228 { 229 startContainer: gEditor.querySelector("li").firstChild, 230 startOffset: 0, 231 endContainer: gEditor.querySelector(firstItem).firstChild, 232 endOffset: gEditor.querySelector(firstItem).firstChild.length, 233 }, 234 ]; 235 }, 236 expectInputEvent: true, 237 } 238 ); 239 240 addPromiseTest( 241 `<${otherList}><li>list-item1[</li></${otherList}><dl><${firstItem}>}list-item2</${firstItem}><${secondItem}>list-item3</${secondItem}></dl>`, 242 { 243 expectedInnerHTML: [ 244 `<${otherList}><li>list-item1list-item2</li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`, 245 `<${otherList}><li>list-item1list-item2<br></li></${otherList}><dl><${secondItem}>list-item3</${secondItem}></dl>`, 246 ], 247 expectedTargetRanges: () => { 248 return [ 249 { 250 startContainer: gEditor.querySelector("li").firstChild, 251 startOffset: gEditor.querySelector("li").firstChild.length, 252 endContainer: gEditor.querySelector(firstItem), 253 endOffset: 0, 254 }, 255 ]; 256 }, 257 expectInputEvent: true, 258 } 259 ); 260 261 addPromiseTest( 262 `<${otherList}><li>list-item1[</li></${otherList}><dl><${firstItem}>list-item2</${firstItem}><${secondItem}>}list-item3</${secondItem}></dl>`, 263 { 264 expectedInnerHTML: [ 265 `<${otherList}><li>list-item1list-item3</li></${otherList}>`, 266 `<${otherList}><li>list-item1list-item3<br></li></${otherList}>`, 267 ], 268 expectedTargetRanges: () => { 269 return [ 270 { 271 startContainer: gEditor.querySelector("li").firstChild, 272 startOffset: gEditor.querySelector("li").firstChild.length, 273 endContainer: gEditor.querySelector(secondItem), 274 endOffset: 0, 275 }, 276 ]; 277 }, 278 expectInputEvent: true, 279 } 280 ); 281 } 282 } 283 } 284 285 </script>