4 <title>Test for nsITableEditor.insertTableColumn()
</title>
5 <script src=
"/tests/SimpleTest/SimpleTest.js"></script>
6 <link rel=
"stylesheet" href=
"/tests/SimpleTest/test.css">
11 <div id=
"content" contenteditable
>out of table
<table><tr><td>default content
</td></tr></table></div>
15 <script class=
"testbody" type=
"application/javascript">
18 SimpleTest.waitForExplicitFinish();
19 SimpleTest.waitForFocus(() =
> {
20 let editor = document.getElementById(
"content");
21 let selection = document.getSelection();
22 let selectionRanges = [];
24 function checkInputEvent(aEvent, aDescription) {
25 ok(aEvent instanceof InputEvent,
26 `
"${aEvent.type}" event should be dispatched with InputEvent interface ${aDescription}`);
27 is(aEvent.cancelable, false,
28 `
"${aEvent.type}" event should be never cancelable ${aDescription}`);
29 is(aEvent.bubbles, true,
30 `
"${aEvent.type}" event should always bubble ${aDescription}`);
31 is(aEvent.inputType,
"",
32 `inputType of
"${aEvent.type}" event should be empty string ${aDescription}`);
34 `data of
"${aEvent.type}" event should be null ${aDescription}`);
35 is(aEvent.dataTransfer, null,
36 `dataTransfer of
"${aEvent.type}" event should be null ${aDescription}`);
37 let targetRanges = aEvent.getTargetRanges();
38 if (aEvent.type ===
"beforeinput") {
39 is(targetRanges.length, selectionRanges.length,
40 `getTargetRanges() of
"beforeinput" event should return selection ranges ${aDescription}`);
41 if (targetRanges.length === selectionRanges.length) {
42 for (let i =
0; i < selectionRanges.length; i++) {
43 is(targetRanges[i].startContainer, selectionRanges[i].startContainer,
44 `startContainer of getTargetRanges()[${i}] of
"beforeinput" event does not match ${aDescription}`);
45 is(targetRanges[i].startOffset, selectionRanges[i].startOffset,
46 `startOffset of getTargetRanges()[${i}] of
"beforeinput" event does not match ${aDescription}`);
47 is(targetRanges[i].endContainer, selectionRanges[i].endContainer,
48 `endContainer of getTargetRanges()[${i}] of
"beforeinput" event does not match ${aDescription}`);
49 is(targetRanges[i].endOffset, selectionRanges[i].endOffset,
50 `endOffset of getTargetRanges()[${i}] of
"beforeinput" event does not match ${aDescription}`);
54 is(targetRanges.length,
0,
55 `getTargetRanges() of
"${aEvent.type}" event should return empty array ${aDescription}`);
59 let beforeInputEvents = [];
61 function onBeforeInput(aEvent) {
62 beforeInputEvents.push(aEvent);
64 for (let i =
0; i < selection.rangeCount; i++) {
65 let range = selection.getRangeAt(i);
66 selectionRanges.push({startContainer: range.startContainer, startOffset: range.startOffset,
67 endContainer: range.endContainer, endOffset: range.endOffset});
70 function onInput(aEvent) {
71 inputEvents.push(aEvent);
73 editor.addEventListener(
"beforeinput", onBeforeInput);
74 editor.addEventListener(
"input", onInput);
76 beforeInputEvents = [];
78 selection.collapse(editor.firstChild,
0);
79 getTableEditor().insertTableColumn(
1, false);
80 is(editor.innerHTML,
"out of table<table><tbody><tr><td>default content</td></tr></tbody></table>",
81 "nsITableEditor.insertTableColumn(1, false) should do nothing if selection is not in <table>");
82 is(beforeInputEvents.length,
1,
83 'beforeinput
" event should be fired when a call of nsITableEditor.insertTableColumn(1, false) even though it will do nothing');
84 checkInputEvent(beforeInputEvents[0], "when selection is collapsed outside table element (nsITableEditor.insertTableColumn(
1, false))
");
85 is(inputEvents.length, 0,
86 'No "input
" event should be fired when a call of nsITableEditor.insertTableColumn(1, false) does nothing');
88 beforeInputEvents = [];
90 getTableEditor().insertTableColumn(1, true);
91 is(editor.innerHTML, "out of table
<table><tbody><tr><td>default content
</td></tr></tbody></table>",
92 "nsITableEditor.insertTableColumn(
1, true) should do nothing if selection is not in
<table>");
93 is(beforeInputEvents.length, 1,
94 '"beforeinput
" event should be fired when a call of nsITableEditor.insertTableColumn(1, true) even though it will do nothing');
95 checkInputEvent(beforeInputEvents[0], "when selection is collapsed outside table element (nsITableEditor.insertTableColumn(
1, true))
");
96 is(inputEvents.length, 0,
97 'No "input
" event should be fired when a call of nsITableEditor.insertTableColumn(1, true) does nothing');
99 selection.removeAllRanges();
101 beforeInputEvents = [];
103 getTableEditor().insertTableColumn(1, false);
104 ok(false, "getTableEditor().insertTableColumn(
1, false) without selection ranges should throw exception
");
106 ok(true, "getTableEditor().insertTableColumn(
1, false) without selection ranges should throw exception
");
107 is(beforeInputEvents.length, 0,
108 'No "beforeinput
" event should be fired when nsITableEditor.insertTableColumn(1, false) causes exception due to no selection range');
109 is(inputEvents.length, 0,
110 'No "input
" event should be fired when nsITableEditor.insertTableColumn(1, false) causes exception due to no selection range');
113 beforeInputEvents = [];
115 getTableEditor().insertTableColumn(1, true);
116 ok(false, "getTableEditor().insertTableColumn(
1, true) without selection ranges should throw exception
");
118 ok(true, "getTableEditor().insertTableColumn(
1, true) without selection ranges should throw exception
");
119 is(beforeInputEvents.length, 0,
120 'No "beforeinput
" event should be fired when nsITableEditor.insertTableColumn(1, true) causes exception due to no selection range');
121 is(inputEvents.length, 0,
122 'No "input
" event should be fired when nsITableEditor.insertTableColumn(1, true) causes exception due to no selection range');
125 (function testInsertBeforeFirstColumn() {
126 selection.removeAllRanges();
129 '<tr><td id="select
">cell1-1</td><td>cell1-2</td><td>cell1-3</td></tr>' +
130 "<tr><td>cell2-
1</td><td>cell2-
2</td><td>cell2-
3</td></tr>" +
133 beforeInputEvents = [];
135 selection.setBaseAndExtent(
136 document.getElementById("select
").firstChild,
138 document.getElementById("select
").firstChild,
141 getTableEditor().insertTableColumn(1, false);
145 '<tr><td valign="top
"><br></td><td id="select
">cell1-1</td><td>cell1-2</td><td>cell1-3</td></tr>' +
146 '<tr><td valign="top
"><br></td><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>' +
148 "testInsertBeforeFirstColumn: nsITableEditor.insertTableColumn(
1, false) should insert a column before the first column
"
151 beforeInputEvents.length,
153 'testInsertBeforeFirstColumn: Only one "beforeinput
" event should be fired'
156 beforeInputEvents[0],
157 "when selection is collapsed in the first column (testInsertBeforeFirstColumn)
"
162 'testInsertBeforeFirstColumn: Only one "input
" event should be fired'
166 "when selection is collapsed in the first column (testInsertBeforeFirstColumn)
"
170 (function testInsertAfterLastColumn() {
171 selection.removeAllRanges();
174 '<tr><td>cell1-1</td><td>cell1-2</td><td id="select
">cell1-3</td></tr>' +
175 "<tr><td>cell2-
1</td><td>cell2-
2</td><td>cell2-
3</td></tr>" +
178 beforeInputEvents = [];
180 selection.setBaseAndExtent(
181 document.getElementById("select
").firstChild,
183 document.getElementById("select
").firstChild,
186 getTableEditor().insertTableColumn(1, true);
190 '<tr><td>cell1-1</td><td>cell1-2</td><td id="select
">cell1-3</td><td valign="top
"><br></td></tr>' +
191 '<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td><td valign="top
"><br></td></tr>' +
193 "testInsertAfterLastColumn: nsITableEditor.insertTableColumn(
1, true) should insert a column after the last column
"
196 beforeInputEvents.length,
198 'testInsertAfterLastColumn: Only one "beforeinput
" event should be fired'
201 beforeInputEvents[0],
202 "when selection is collapsed in the last column (testInsertAfterLastColumn)
"
207 'testInsertAfterLastColumn: One "input
" event should be fired'
211 "when selection is collapsed in the last column (testInsertAfterLastColumn)
"
215 selection.removeAllRanges();
216 editor.innerHTML = "<table>" +
217 '<tr><td>cell1-1</td><td id="select
">cell1-2</td><td>cell1-3</td></tr>' +
218 "<tr><td>cell2-
1</td><td>cell2-
2</td><td>cell2-
3</td></tr>" +
221 beforeInputEvents = [];
223 selection.setBaseAndExtent(document.getElementById("select
").firstChild, 0,
224 document.getElementById("select
").firstChild, 0);
225 getTableEditor().insertTableColumn(1, false);
226 is(editor.innerHTML, "<table><tbody>" +
227 '<tr><td>cell1-1</td><td valign="top
"><br></td><td id="select
">cell1-2</td><td>cell1-3</td></tr>' +
228 '<tr><td>cell2-1</td><td valign="top
"><br></td><td>cell2-2</td><td>cell2-3</td></tr>' +
230 "nsITableEditor.insertTableColumn(
1, false) should insert a column to left of the second column
");
231 is(beforeInputEvents.length, 1,
232 'Only one "beforeinput
" event should be fired when selection is collapsed in a cell in second column (before)');
233 checkInputEvent(beforeInputEvents[0], "when selection is collapsed in a cell in second column (before)
");
234 is(inputEvents.length, 1,
235 'Only one "input
" event should be fired when selection is collapsed in a cell in second column (before)');
236 checkInputEvent(inputEvents[0], "when selection is collapsed in a cell in second column (before)
");
238 selection.removeAllRanges();
239 editor.innerHTML = "<table>" +
240 '<tr><td>cell1-1</td><td id="select
">cell1-2</td><td>cell1-3</td></tr>' +
241 "<tr><td>cell2-
1</td><td>cell2-
2</td><td>cell2-
3</td></tr>" +
244 beforeInputEvents = [];
246 selection.setBaseAndExtent(document.getElementById("select
").firstChild, 0,
247 document.getElementById("select
").firstChild, 0);
248 getTableEditor().insertTableColumn(1, true);
249 is(editor.innerHTML, "<table><tbody>" +
250 '<tr><td>cell1-1</td><td id="select
">cell1-2</td><td valign="top
"><br></td><td>cell1-3</td></tr>' +
251 '<tr><td>cell2-1</td><td>cell2-2</td><td valign="top
"><br></td><td>cell2-3</td></tr>' +
253 "nsITableEditor.insertTableColumn(
1, false) should insert a column to right of the second column
");
254 is(beforeInputEvents.length, 1,
255 'Only one "beforeinput
" event should be fired when selection is collapsed in a cell in second column (after)');
256 checkInputEvent(beforeInputEvents[0], "when selection is collapsed in a cell in second column (after)
");
257 is(inputEvents.length, 1,
258 'Only one "input
" event should be fired when selection is collapsed in a cell in second column (after)');
259 checkInputEvent(inputEvents[0], "when selection is collapsed in a cell in second column (after)
");
261 selection.removeAllRanges();
262 editor.innerHTML = "<table>" +
263 '<tr><td>cell1-1</td><td id="select
">cell1-2</td><td>cell1-3</td></tr>' +
264 '<tr><td colspan="2">cell2-1</td><td>cell2-3</td></tr>' +
267 beforeInputEvents = [];
269 selection.setBaseAndExtent(document.getElementById("select
").firstChild, 0,
270 document.getElementById("select
").firstChild, 0);
271 getTableEditor().insertTableColumn(1, false);
272 is(editor.innerHTML, "<table><tbody>" +
273 '<tr><td>cell1-1</td><td valign="top
"><br></td><td id="select
">cell1-2</td><td>cell1-3</td></tr>' +
274 '<tr><td colspan="3">cell2-1</td><td>cell2-3</td></tr>' +
276 "nsITableEditor.insertTableColumn(
1, false) should insert a column to left of the second column and colspan in the first column should be increased
");
277 is(beforeInputEvents.length, 1,
278 'Only one "beforeinput
" event should be fired when selection is collapsed in a cell in second column whose next row cell is col-spanned (before)');
279 checkInputEvent(beforeInputEvents[0], "when selection is collapsed in a cell in second column whose next row cell is col-spanned (before)
");
280 is(inputEvents.length, 1,
281 'Only one "input
" event should be fired when selection is collapsed in a cell in second column whose next row cell is col-spanned (before)');
282 checkInputEvent(inputEvents[0], "when selection is collapsed in a cell in second column whose next row cell is col-spanned (before)
");
284 selection.removeAllRanges();
285 editor.innerHTML = "<table>" +
286 '<tr><td>cell1-1</td><td id="select
">cell1-2</td><td>cell1-3</td></tr>' +
287 '<tr><td colspan="3">cell2-1</td></tr>' +
290 beforeInputEvents = [];
292 selection.setBaseAndExtent(document.getElementById("select
").firstChild, 0,
293 document.getElementById("select
").firstChild, 0);
294 getTableEditor().insertTableColumn(1, true);
295 is(editor.innerHTML, "<table><tbody>" +
296 '<tr><td>cell1-1</td><td id="select
">cell1-2</td><td valign="top
"><br></td><td>cell1-3</td></tr>' +
297 '<tr><td colspan="4">cell2-1</td></tr>' +
299 "nsITableEditor.insertTableColumn(
1, true) should insert a column to right of the second column and colspan in the first column should be increased
");
300 is(beforeInputEvents.length, 1,
301 'Only one "beforeinput
" event should be fired when selection is collapsed in a cell in second column whose next row cell is col-spanned (after)');
302 checkInputEvent(beforeInputEvents[0], "when selection is collapsed in a cell in second column whose next row cell is col-spanned (after)
");
303 is(inputEvents.length, 1,
304 'Only one "input
" event should be fired when selection is collapsed in a cell in second column whose next row cell is col-spanned (after)');
305 checkInputEvent(inputEvents[0], "when selection is collapsed in a cell in second column whose next row cell is col-spanned (after)
");
307 selection.removeAllRanges();
308 editor.innerHTML = "<table>" +
309 "<tr><td>cell1-
1</td><td>cell1-
2</td><td>cell1-
3</td></tr>" +
310 '<tr><td id="select
" colspan="2">cell2-1</td><td>cell2-3</td></tr>' +
313 beforeInputEvents = [];
315 selection.setBaseAndExtent(document.getElementById("select
").firstChild, 0,
316 document.getElementById("select
").firstChild, 1);
317 getTableEditor().insertTableColumn(2, false);
318 is(editor.innerHTML, "<table><tbody>" +
319 '<tr><td valign="top
"><br></td><td valign="top
"><br></td><td>cell1-1</td><td>cell1-2</td><td>cell1-3</td></tr>' +
320 '<tr><td valign="top
"><br></td><td valign="top
"><br></td><td id="select
" colspan="2">cell2-1</td><td>cell2-3</td></tr>' +
322 "nsITableEditor.insertTableColumn(
2, false) should insert
2 columns to left of the first column
");
323 is(beforeInputEvents.length, 1,
324 'Only one "beforeinput
" event should be fired when selection is collapsed in a cell which is col-spanning (before)');
325 checkInputEvent(beforeInputEvents[0], "when selection is collapsed in a cell which is col-spanning (before)
");
326 is(inputEvents.length, 1,
327 'Only one "input
" event should be fired when selection is collapsed in a cell which is col-spanning (before)');
328 checkInputEvent(inputEvents[0], "when selection is collapsed in a cell which is col-spanning (before)
");
330 selection.removeAllRanges();
331 editor.innerHTML = "<table>" +
332 "<tr><td>cell1-
1</td><td>cell1-
2</td><td>cell1-
3</td></tr>" +
333 '<tr><td id="select
" colspan="2">cell2-1</td><td>cell2-3</td></tr>' +
336 beforeInputEvents = [];
338 selection.setBaseAndExtent(document.getElementById("select
").firstChild, 0,
339 document.getElementById("select
").firstChild, 1);
340 getTableEditor().insertTableColumn(2, true);
341 is(editor.innerHTML, "<table><tbody>" +
342 '<tr><td>cell1-1</td><td>cell1-2</td><td valign="top
"><br></td><td valign="top
"><br></td><td>cell1-3</td></tr>' +
343 '<tr><td id="select
" colspan="2">cell2-1</td><td valign="top
"><br></td><td valign="top
"><br></td><td>cell2-3</td></tr>' +
345 "nsITableEditor.insertTableColumn(
2, false) should insert
2 columns to right of the second column (i.e., right of the right-most column of the column-spanning cell
");
346 is(beforeInputEvents.length, 1,
347 'Only one "beforeinput
" event should be fired when selection is collapsed in a cell which is col-spanning (after)');
348 checkInputEvent(beforeInputEvents[0], "when selection is collapsed in a cell which is col-spanning (after)
");
349 is(inputEvents.length, 1,
350 'Only one "input
" event should be fired when selection is collapsed in a cell which is col-spanning (after)');
351 checkInputEvent(inputEvents[0], "when selection is collapsed in a cell which is col-spanning (after)
");
353 (function testInsertBeforeFirstColumnFollowingTextNode() {
354 selection.removeAllRanges();
357 '<tr> <td id="select
">cell1-1</td><td>cell1-2</td><td>cell1-3</td> </tr>' +
358 "<tr> <td>cell2-
1</td><td>cell2-
2</td><td>cell2-
3</td> </tr>" +
361 beforeInputEvents = [];
363 selection.setBaseAndExtent(
364 document.getElementById("select
").firstChild,
366 document.getElementById("select
").firstChild,
369 getTableEditor().insertTableColumn(1, false);
373 '<tr> <td valign="top
"><br></td><td id="select
">cell1-1</td><td>cell1-2</td><td>cell1-3</td> </tr>' +
374 '<tr> <td valign="top
"><br></td><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td> </tr>' +
376 "testInsertBeforeFirstColumnFollowingTextNode: nsITableEditor.insertTableColumn(
1, false) should insert a column before the first column
"
379 beforeInputEvents.length,
381 'testInsertBeforeFirstColumnFollowingTextNode: Only one "beforeinput
" event should be fired'
384 beforeInputEvents[0],
385 "when selection is collapsed in the first column (testInsertBeforeFirstColumnFollowingTextNode)
"
390 'testInsertBeforeFirstColumnFollowingTextNode: Only one "input
" event should be fired'
394 "when selection is collapsed in the first column (testInsertBeforeFirstColumnFollowingTextNode)
"
398 (function testInsertAfterLastColumnFollowedByTextNode() {
399 selection.removeAllRanges();
402 '<tr> <td>cell1-1</td><td>cell1-2</td><td id="select
">cell1-3</td> </tr>' +
403 "<tr> <td>cell2-
1</td><td>cell2-
2</td><td>cell2-
3</td> </tr>" +
406 beforeInputEvents = [];
408 selection.setBaseAndExtent(
409 document.getElementById("select
").firstChild,
411 document.getElementById("select
").firstChild,
414 getTableEditor().insertTableColumn(1, true);
418 '<tr> <td>cell1-1</td><td>cell1-2</td><td id="select
">cell1-3</td><td valign="top
"><br></td> </tr>' +
419 '<tr> <td>cell2-1</td><td>cell2-2</td><td>cell2-3</td><td valign="top
"><br></td> </tr>' +
421 "testInsertAfterLastColumnFollowedByTextNode: nsITableEditor.insertTableColumn(
1, true) should insert a column after the last column
"
424 beforeInputEvents.length,
426 'testInsertAfterLastColumnFollowedByTextNode: Only one "beforeinput
" event should be fired'
429 beforeInputEvents[0],
430 "when selection is collapsed in the last column (testInsertAfterLastColumnFollowedByTextNode)
"
435 'testInsertAfterLastColumnFollowedByTextNode: One "input
" event should be fired'
439 "when selection is collapsed in the last column (testInsertAfterLastColumnFollowedByTextNode)
"
443 (function testInsertBeforeColumnFollowingTextNode() {
444 selection.removeAllRanges();
447 '<tr><td>cell1-1</td> <td id="select
">cell1-2</td> <td>cell1-3</td></tr>' +
448 "<tr><td>cell2-
1</td> <td>cell2-
2</td> <td>cell2-
3</td></tr>" +
451 beforeInputEvents = [];
453 selection.setBaseAndExtent(
454 document.getElementById("select
").firstChild,
456 document.getElementById("select
").firstChild,
459 getTableEditor().insertTableColumn(1, false);
463 '<tr><td>cell1-1</td> <td valign="top
"><br></td><td id="select
">cell1-2</td> <td>cell1-3</td></tr>' +
464 '<tr><td>cell2-1</td> <td valign="top
"><br></td><td>cell2-2</td> <td>cell2-3</td></tr>' +
466 "testInsertBeforeColumnFollowingTextNode: nsITableEditor.insertTableColumn(
1, false) should insert a column before the first column
"
469 beforeInputEvents.length,
471 'testInsertBeforeColumnFollowingTextNode: Only one "beforeinput
" event should be fired'
474 beforeInputEvents[0],
475 "when selection is collapsed in the column following a text node (testInsertBeforeColumnFollowingTextNode)
"
480 'testInsertBeforeColumnFollowingTextNode: Only one "input
" event should be fired'
484 "when selection is collapsed in the column following a text node (testInsertBeforeColumnFollowingTextNode)
"
488 (function testInsertAfterColumnFollowedByTextNode() {
489 selection.removeAllRanges();
492 '<tr><td>cell1-1</td> <td id="select
">cell1-2</td> <td>cell1-3</td></tr>' +
493 "<tr><td>cell2-
1</td> <td>cell2-
2</td> <td>cell2-
3</td></tr>" +
496 beforeInputEvents = [];
498 selection.setBaseAndExtent(
499 document.getElementById("select
").firstChild,
501 document.getElementById("select
").firstChild,
504 getTableEditor().insertTableColumn(1, true);
508 '<tr><td>cell1-1</td> <td id="select
">cell1-2</td><td valign="top
"><br></td> <td>cell1-3</td></tr>' +
509 '<tr><td>cell2-1</td> <td>cell2-2</td><td valign="top
"><br></td> <td>cell2-3</td></tr>' +
511 "testInsertAfterColumnFollowedByTextNode: nsITableEditor.insertTableColumn(
1, true) should insert a column before the first column
"
514 beforeInputEvents.length,
516 'testInsertAfterColumnFollowedByTextNode: Only one "beforeinput
" event should be fired'
519 beforeInputEvents[0],
520 "when selection is collapsed in the column followed by a text node (testInsertAfterColumnFollowedByTextNode)
"
525 'testInsertAfterColumnFollowedByTextNode: Only one "input
" event should be fired'
529 "when selection is collapsed in the column followed by a text node (testInsertAfterColumnFollowedByTextNode)
"
533 editor.removeEventListener("beforeinput
", onBeforeInput);
534 editor.removeEventListener("input
", onInput);
539 function getTableEditor() {
540 var editingSession = SpecialPowers.wrap(window).docShell.editingSession;
541 return editingSession.getEditorForWindow(window).QueryInterface(SpecialPowers.Ci.nsITableEditor);