event.html (7171B)
1 <!doctype html> 2 <title>Editing event tests</title> 3 <style>body { font-family: serif }</style> 4 <script src=/resources/testharness.js></script> 5 <script src=/resources/testharnessreport.js></script> 6 <div id=test></div> 7 <div id=log></div> 8 <script> 9 "use strict"; 10 11 var div = document.querySelector("#test"); 12 add_completion_callback(function() { div.parentNode.removeChild(div) }); 13 14 function copyEvent(e) { 15 var ret = {}; 16 ret.original = e; 17 ["type", "target", "currentTarget", "eventPhase", "bubbles", "cancelable", 18 "defaultPrevented", "isTrusted", "command", "value"].forEach(function(k) { 19 ret[k] = e[k]; 20 }); 21 return ret; 22 } 23 24 var tests = [ 25 { 26 name: "Simple editable div", 27 html: "<div contenteditable>foo<b>bar</b>baz</div>", 28 initRange: function(range) { 29 range.setStart(div.querySelector("b").firstChild, 0); 30 range.setEnd(div.querySelector("b"), 1); 31 }, 32 target: function() { return div.firstChild }, 33 command: "bold", 34 value: "", 35 }, 36 { 37 name: "Editable b", 38 html: "foo<b contenteditable>bar</b>baz", 39 initRange: function(range) { 40 range.setStart(div.querySelector("b").firstChild, 0); 41 range.setEnd(div.querySelector("b"), 1); 42 }, 43 target: function() { return div.querySelector("b") }, 44 command: "bold", 45 value: "", 46 }, 47 { 48 name: "No editable content", 49 html: "foo<b>bar</b>baz", 50 initRange: function(range) { 51 range.setStart(div.querySelector("b").firstChild, 0); 52 range.setEnd(div.querySelector("b"), 1); 53 }, 54 target: function() { return null }, 55 command: "bold", 56 value: "", 57 }, 58 { 59 name: "Partially-selected editable content", 60 html: "foo<b contenteditable>bar</b>baz", 61 initRange: function(range) { 62 range.setStart(div.querySelector("b").firstChild, 0); 63 range.setEnd(div, 3); 64 }, 65 target: function() { return null }, 66 command: "bold", 67 value: "", 68 }, 69 { 70 name: "Selection spans two editing hosts", 71 html: "<div contenteditable>foo</div><div contenteditable>bar</div>", 72 initRange: function(range) { 73 range.setStart(div.querySelector("div").firstChild, 2); 74 range.setEnd(div.querySelector("div + div").firstChild, 1); 75 }, 76 target: function() { return null }, 77 command: "bold", 78 value: "", 79 }, 80 { 81 name: "Selection includes two editing hosts", 82 html: "foo<div contenteditable>bar</div>baz<div contenteditable>quz</div>qoz", 83 initRange: function(range) { 84 range.setStart(div.firstChild, 2); 85 range.setEnd(div.lastChild, 1); 86 }, 87 target: function() { return null }, 88 command: "bold", 89 value: "", 90 }, 91 { 92 name: "Changing selection from handler", 93 html: "<div contenteditable>foo</div><div contenteditable>bar</div>", 94 initRange: function(range) { 95 range.setStart(div.querySelector("div").firstChild, 0); 96 range.setEnd(div.querySelector("div").firstChild, 3); 97 }, 98 target: function() { return div.firstChild }, 99 finalTarget: function() { return div.lastChild }, 100 command: "bold", 101 value: "", 102 }, 103 ]; 104 105 var commandTests = { 106 backColor: ["green"], 107 createLink: ["http://www.w3.org/community/editing/"], 108 fontName: ["serif", "Helvetica"], 109 fontSize: ["6", "15px"], 110 foreColor: ["green"], 111 hiliteColor: ["green"], 112 italic: [], 113 removeFormat: [], 114 strikeThrough: [], 115 subscript: [], 116 superscript: [], 117 underline: [], 118 unlink: [], 119 delete: [], 120 formatBlock: ["p"], 121 forwardDelete: [], 122 indent: [], 123 insertHorizontalRule: ["id"], 124 insertHTML: ["<b>hi</b>"], 125 insertImage: ["../images/green.png"], 126 insertLineBreak: [], 127 insertOrderedList: [], 128 insertParagraph: [], 129 insertText: ["abc"], 130 insertUnorderedList: [], 131 justifyCenter: [], 132 justifyFull: [], 133 justifyLeft: [], 134 justifyRight: [], 135 outdent: [], 136 redo: [], 137 selectAll: [], 138 styleWithCSS: [], 139 undo: [], 140 useCSS: [], 141 }; 142 143 Object.keys(commandTests).forEach(function(command) { 144 commandTests[command] = ["", "quasit"].concat(commandTests[command]); 145 commandTests[command].forEach(function(value) { 146 tests.push({ 147 name: "Command " + command + ", value " + format_value(value), 148 html: "<div contenteditable>foo<b>bar</b>baz</div>", 149 initRange: function(range) { 150 range.setStart(div.querySelector("b").firstChild, 0); 151 range.setEnd(div.querySelector("b"), 1); 152 }, 153 target: function() { 154 return ["redo", "selectAll", "styleWithCSS", "undo", "useCSS"] 155 .indexOf(command) == -1 ? div.firstChild : null; 156 }, 157 command: command, 158 value: value, 159 }); 160 }); 161 }); 162 163 tests.forEach(function(obj) { 164 // Kill all event handlers first 165 var newDiv = div.cloneNode(false); 166 div.parentNode.insertBefore(newDiv, div); 167 div.parentNode.removeChild(div); 168 div = newDiv; 169 170 div.innerHTML = obj.html; 171 172 var originalContents = div.cloneNode(true); 173 174 getSelection().removeAllRanges(); 175 var range = document.createRange(); 176 obj.initRange(range); 177 getSelection().addRange(range); 178 179 var target = obj.target(); 180 var finalTarget = "finalTarget" in obj ? obj.finalTarget() : target; 181 var command = obj.command; 182 var value = obj.value; 183 184 var inputEvents = []; 185 div.addEventListener("input", function(e) { inputEvents.push(copyEvent(e)) }); 186 187 var exception = null; 188 try { 189 document.execCommand(command, false, value); 190 } catch(e) { 191 exception = e; 192 } 193 194 test(function() { 195 assert_equals(exception, null, "Unexpected exception"); 196 }, obj.name + ": execCommand() must not throw"); 197 198 test(function() { 199 assert_equals(inputEvents.length, target ? 1 : 0, 200 "number of input events fired"); 201 if (!target) { 202 assert_true(originalContents.isEqualNode(div), 203 "div contents must not be changed"); 204 return; 205 } 206 var e = inputEvents[0]; 207 assert_equals(e.type, "input", "event.type"); 208 assert_equals(e.target, finalTarget, "event.target"); 209 assert_equals(e.currentTarget, div, "event.currentTarget"); 210 assert_equals(e.eventPhase, Event.BUBBLING_PHASE, "event.eventPhase"); 211 assert_equals(e.bubbles, true, "event.bubbles"); 212 assert_equals(e.cancelable, false, "event.cancelable"); 213 assert_equals(e.defaultPrevented, false, "event.defaultPrevented"); 214 assert_own_property(window, "InputEvent", 215 "window.InputEvent must exist"); 216 assert_equals(Object.getPrototypeOf(e.original), InputEvent.prototype, 217 "event prototype"); 218 assert_equals(e.isTrusted, true, "event.isTrusted"); 219 }, obj.name + ": input event"); 220 }); 221 222 // Thanks, Gecko. 223 document.body.bgColor = ""; 224 </script>