test_bug1315065.html (6387B)
1 <!DOCTYPE HTML> 2 <html> 3 <!-- 4 https://bugzilla.mozilla.org/show_bug.cgi?id=1315065 5 --> 6 <head> 7 <meta charset="utf-8"> 8 <title>Test for Bug 1315065</title> 9 <script src="/tests/SimpleTest/SimpleTest.js"></script> 10 <script src="/tests/SimpleTest/EventUtils.js"></script> 11 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> 12 </head> 13 <body> 14 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1315065">Mozilla Bug 1315065</a> 15 <div contenteditable><p>abc<br></p></div> 16 <script type="application/javascript"> 17 /** Test for Bug 1315065 */ 18 SimpleTest.waitForExplicitFinish(); 19 SimpleTest.waitForFocus(() => { 20 const editor = document.getElementsByTagName("div")[0]; 21 function initForBackspace(aSelectionCollapsedTo /* = 0 ~ 3 */) { 22 editor.innerHTML = "<p id='p'>abc<br></p>"; 23 const p = document.getElementById("p"); 24 // FYI: We cannot inserting empty text nodes as expected with 25 // Node.appendChild() nor Node.insertBefore(). Therefore, let's use 26 // Range.insertNode() like actual web apps. 27 const selection = window.getSelection(); 28 selection.collapse(p, 1); 29 const range = selection.getRangeAt(0); 30 const emptyTextNode3 = document.createTextNode(""); 31 range.insertNode(emptyTextNode3); 32 const emptyTextNode2 = document.createTextNode(""); 33 range.insertNode(emptyTextNode2); 34 const emptyTextNode1 = document.createTextNode(""); 35 range.insertNode(emptyTextNode1); 36 is(p.childNodes.length, 5, "Failed to initialize the editor"); 37 is(p.childNodes.item(1), emptyTextNode1, "1st text node should be emptyTextNode1"); 38 is(p.childNodes.item(2), emptyTextNode2, "2nd text node should be emptyTextNode2"); 39 is(p.childNodes.item(3), emptyTextNode3, "3rd text node should be emptyTextNode3"); 40 switch (aSelectionCollapsedTo) { 41 case 0: 42 selection.collapse(p.firstChild, 3); // next to 'c' 43 break; 44 case 1: 45 selection.collapse(emptyTextNode1, 0); 46 break; 47 case 2: 48 selection.collapse(emptyTextNode2, 0); 49 break; 50 case 3: 51 selection.collapse(emptyTextNode3, 0); 52 break; 53 default: 54 ok(false, "aSelectionCollapsedTo is illegal value"); 55 } 56 } 57 58 for (let i = 0; i < 4; i++) { 59 const kDescription = i == 0 ? "Backspace from immediately after the last character" : 60 "Backspace from " + i + "th empty text node"; 61 editor.focus(); 62 initForBackspace(i); 63 synthesizeKey("KEY_Backspace"); 64 const p = document.getElementById("p"); 65 ok(p, kDescription + ": <p> element shouldn't be removed by Backspace key press"); 66 is(p.tagName.toLowerCase(), "p", kDescription + ": <p> element shouldn't be removed by Backspace key press"); 67 // When Backspace key is pressed even in empty text nodes, Gecko should not remove empty text nodes for now 68 // because we should keep our traditional behavior (same as Edge) for backward compatibility as far as possible. 69 // In this case, Chromium removes all empty text nodes, but Edge doesn't remove any empty text nodes. 70 // XXX It's fine to delete empty text nodes too if it's reasonable for handling deletion. 71 is(p.childNodes.length, 4, kDescription + ": <p> should have 4 children after pressing Backspace key"); 72 is(p.childNodes.item(0).textContent, "ab", kDescription + ": 'c' should be removed by pressing Backspace key"); 73 is(p.childNodes.item(1).textContent, "", kDescription + ": 1st empty text node should not be removed by pressing Backspace key"); 74 is(p.childNodes.item(2).textContent, "", kDescription + ": 2nd empty text node should not be removed by pressing Backspace key"); 75 is(p.childNodes.item(3).textContent, "", kDescription + ": 3rd empty text node should not be removed by pressing Backspace key"); 76 editor.blur(); 77 } 78 79 function initForDelete(aSelectionCollapsedTo /* = 0 ~ 3 */) { 80 editor.innerHTML = "<p id='p'>abc<br></p>"; 81 const p = document.getElementById("p"); 82 // FYI: We cannot inserting empty text nodes as expected with 83 // Node.appendChild() nor Node.insertBefore(). Therefore, let's use 84 // Range.insertNode() like actual web apps. 85 const selection = window.getSelection(); 86 selection.collapse(p, 0); 87 const range = selection.getRangeAt(0); 88 const emptyTextNode1 = document.createTextNode(""); 89 range.insertNode(emptyTextNode1); 90 const emptyTextNode2 = document.createTextNode(""); 91 range.insertNode(emptyTextNode2); 92 const emptyTextNode3 = document.createTextNode(""); 93 range.insertNode(emptyTextNode3); 94 is(p.childNodes.length, 5, "Failed to initialize the editor"); 95 is(p.childNodes.item(0), emptyTextNode3, "1st text node should be emptyTextNode3"); 96 is(p.childNodes.item(1), emptyTextNode2, "2nd text node should be emptyTextNode2"); 97 is(p.childNodes.item(2), emptyTextNode1, "3rd text node should be emptyTextNode1"); 98 switch (aSelectionCollapsedTo) { 99 case 0: 100 selection.collapse(p.childNodes.item(3), 0); // next to 'a' 101 break; 102 case 1: 103 selection.collapse(emptyTextNode1, 0); 104 break; 105 case 2: 106 selection.collapse(emptyTextNode2, 0); 107 break; 108 case 3: 109 selection.collapse(emptyTextNode3, 0); 110 break; 111 default: 112 ok(false, "aSelectionCollapsedTo is illegal value"); 113 } 114 } 115 116 for (let i = 0; i < 4; i++) { 117 const kDescription = i == 0 ? "Delete from immediately before the first character" : 118 "Delete from " + i + "th empty text node"; 119 editor.focus(); 120 initForDelete(i); 121 synthesizeKey("KEY_Delete"); 122 const p = document.getElementById("p"); 123 ok(p, kDescription + ": <p> element shouldn't be removed by Delete key press"); 124 is(p.tagName.toLowerCase(), "p", kDescription + ": <p> element shouldn't be removed by Delete key press"); 125 // If Delete key is pressed in an empty text node, it's fine to delete all 126 // empty text nodes, but the non-empty text node should be modified. 127 is( 128 p.childNodes.length, 129 2, 130 `${kDescription}: <p> should have at least one text node after pressing Delete key` 131 ); 132 is( 133 p.textContent, 134 "bc", 135 `${kDescription}: empty text nodes and 'a' should be removed by pressing Delete key` 136 ); 137 editor.blur(); 138 } 139 SimpleTest.finish(); 140 }); 141 </script> 142 </body> 143 </html>