dom/imptests/editing/conformancetest/test_event.html

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:f9baceba1bb5
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 beforeInputAction: function() {
101 getSelection().removeAllRanges();
102 var range = document.createRange();
103 range.setStart(div.querySelector("div + div").firstChild, 0);
104 range.setEnd(div.querySelector("div + div").firstChild, 3);
105 getSelection().addRange(range);
106 },
107 command: "bold",
108 value: "",
109 },
110 ];
111
112 var commandTests = {
113 backColor: ["green"],
114 createLink: ["http://www.w3.org/community/editing/"],
115 fontName: ["serif", "Helvetica"],
116 fontSize: ["6", "15px"],
117 foreColor: ["green"],
118 hiliteColor: ["green"],
119 italic: [],
120 removeFormat: [],
121 strikeThrough: [],
122 subscript: [],
123 superscript: [],
124 underline: [],
125 unlink: [],
126 delete: [],
127 formatBlock: ["p"],
128 forwardDelete: [],
129 indent: [],
130 insertHorizontalRule: ["id"],
131 insertHTML: ["<b>hi</b>"],
132 insertImage: ["http://example.com/some-image"],
133 insertLineBreak: [],
134 insertOrderedList: [],
135 insertParagraph: [],
136 insertText: ["abc"],
137 insertUnorderedList: [],
138 justifyCenter: [],
139 justifyFull: [],
140 justifyLeft: [],
141 justifyRight: [],
142 outdent: [],
143 redo: [],
144 selectAll: [],
145 styleWithCSS: [],
146 undo: [],
147 useCSS: [],
148 };
149
150 Object.keys(commandTests).forEach(function(command) {
151 commandTests[command] = ["", "quasit"].concat(commandTests[command]);
152 commandTests[command].forEach(function(value) {
153 tests.push({
154 name: "Command " + command + ", value " + format_value(value),
155 html: "<div contenteditable>foo<b>bar</b>baz</div>",
156 initRange: function(range) {
157 range.setStart(div.querySelector("b").firstChild, 0);
158 range.setEnd(div.querySelector("b"), 1);
159 },
160 target: function() {
161 return ["redo", "selectAll", "styleWithCSS", "undo", "useCSS"]
162 .indexOf(command) == -1 ? div.firstChild : null;
163 },
164 command: command,
165 value: value,
166 });
167 });
168 });
169
170 tests.forEach(function(obj) {
171 [true, false].forEach(function(cancel) {
172 // Kill all event handlers first
173 var newDiv = div.cloneNode(false);
174 div.parentNode.insertBefore(newDiv, div);
175 div.parentNode.removeChild(div);
176 div = newDiv;
177
178 div.innerHTML = obj.html;
179
180 var originalContents = div.cloneNode(true);
181
182 getSelection().removeAllRanges();
183 var range = document.createRange();
184 obj.initRange(range);
185 getSelection().addRange(range);
186
187 var target = obj.target();
188 var finalTarget = "finalTarget" in obj ? obj.finalTarget() : target;
189 var command = obj.command;
190 var value = obj.value;
191
192 var beforeInputEvents = [];
193 var inputEvents = [];
194 div.addEventListener("beforeinput", function(e) {
195 var copied = copyEvent(e);
196 copied.inputEventsLength = inputEvents.length;
197 beforeInputEvents.push(copied);
198 if (cancel) {
199 e.preventDefault();
200 }
201 if ("beforeInputAction" in obj) {
202 obj.beforeInputAction();
203 }
204 });
205 div.addEventListener("input", function(e) { inputEvents.push(copyEvent(e)) });
206
207 // Uncomment this code instead of the execCommand() to make all the
208 // tests pass, as a sanity check
209 //var e = new Event("beforeinput", {bubbles: true, cancelable: true});
210 //e.command = command;
211 //e.value = value;
212 //var ret = target ? target.dispatchEvent(e) : false;
213 //if (ret) {
214 // var e = new Event("input", {bubbles: true});
215 // e.command = command;
216 // e.value = value;
217 // finalTarget.dispatchEvent(e);
218 //}
219
220 var exception = null;
221 try {
222 document.execCommand(command, false, value);
223 } catch(e) {
224 exception = e;
225 }
226
227 test(function() {
228 assert_equals(exception, null, "Unexpected exception");
229 }, obj.name + ": execCommand() must not throw, "
230 + (cancel ? "canceled" : "uncanceled"));
231
232 test(function() {
233 assert_equals(beforeInputEvents.length, target ? 1 : 0,
234 "number of beforeinput events fired");
235 if (beforeInputEvents.length == 0) {
236 assert_equals(inputEvents.length, 0, "number of input events fired");
237 return;
238 }
239 var e = beforeInputEvents[0];
240 assert_equals(e.inputEventsLength, 0, "number of input events fired");
241 assert_equals(e.type, "beforeinput", "event.type");
242 assert_equals(e.target, target, "event.target");
243 assert_equals(e.currentTarget, div, "event.currentTarget");
244 assert_equals(e.eventPhase, Event.BUBBLING_PHASE, "event.eventPhase");
245 assert_equals(e.bubbles, true, "event.bubbles");
246 assert_equals(e.cancelable, true, "event.cancelable");
247 assert_equals(e.defaultPrevented, false, "event.defaultPrevented");
248 assert_equals(e.command, command, "e.command");
249 assert_equals(e.value, value, "e.value");
250 assert_own_property(window, "EditingBeforeInputEvent",
251 "window.EditingBeforeInputEvent must exist");
252 assert_equals(Object.getPrototypeOf(e.original),
253 EditingBeforeInputEvent.prototype,
254 "event prototype");
255 assert_true(originalContents.isEqualNode(div),
256 "div contents not yet changed");
257 assert_equals(e.isTrusted, true, "event.isTrusted");
258 }, obj.name + ": beforeinput event, " + (cancel ? "canceled" : "uncanceled"));
259
260 test(function() {
261 assert_equals(inputEvents.length, target && !cancel ? 1 : 0,
262 "number of input events fired");
263 if (!target || cancel) {
264 assert_true(originalContents.isEqualNode(div),
265 "div contents must not be changed");
266 return;
267 }
268 var e = inputEvents[0];
269 assert_equals(e.type, "input", "event.type");
270 assert_equals(e.target, finalTarget, "event.target");
271 assert_equals(e.currentTarget, div, "event.currentTarget");
272 assert_equals(e.eventPhase, Event.BUBBLING_PHASE, "event.eventPhase");
273 assert_equals(e.bubbles, true, "event.bubbles");
274 assert_equals(e.cancelable, false, "event.cancelable");
275 assert_equals(e.defaultPrevented, false, "event.defaultPrevented");
276 assert_equals(e.command, command, "e.command");
277 assert_equals(e.value, value, "e.value");
278 assert_own_property(window, "EditingInputEvent",
279 "window.EditingInputEvent must exist");
280 assert_equals(Object.getPrototypeOf(e.original),
281 EditingInputEvent.prototype,
282 "event prototype");
283 assert_equals(e.isTrusted, true, "event.isTrusted");
284 }, obj.name + ": input event, " + (cancel ? "canceled" : "uncanceled"));
285 });
286 });
287
288 // Thanks, Gecko.
289 document.body.bgColor = "";
290 </script>

mercurial