dom/imptests/editing/conformancetest/test_event.html

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial