tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_nsITableEditor_deleteTableCell.html (39112B)


      1 <!DOCTYPE>
      2 <html>
      3 <head>
      4  <title>Test for nsITableEditor.deleteTableCell()</title>
      5  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      6  <link rel="stylesheet" href="/tests/SimpleTest/test.css">
      7 </head>
      8 <body>
      9 <div id="display">
     10 </div>
     11 <div id="content" contenteditable>out of table<table><tr><td>default content</td></tr></table></div>
     12 <pre id="test">
     13 </pre>
     14 
     15 <script class="testbody" type="application/javascript">
     16 "use strict";
     17 
     18 SimpleTest.waitForExplicitFinish();
     19 SimpleTest.waitForFocus(() => {
     20  let editor = document.getElementById("content");
     21  let selection = document.getSelection();
     22  let selectionRanges = [];
     23 
     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, aEvent.type === "beforeinput",
     28       `"${aEvent.type}" event should be ${aEvent.type === "beforeinput" ? "be" : "never cancelable"} ${aDescription}`);
     29    is(aEvent.bubbles, true,
     30       `"${aEvent.type}" event should always bubble ${aDescription}`);
     31    is(aEvent.inputType, "deleteContent",
     32       `inputType of "${aEvent.type}" event should be "deleteContent" ${aDescription}`);
     33    is(aEvent.data, null,
     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}`);
     51        }
     52      }
     53    } else {
     54      is(targetRanges.length, 0,
     55         `getTargetRanges() of "${aEvent.type}" event should return empty array ${aDescription}`);
     56    }
     57  }
     58 
     59  let beforeInputEvents = [];
     60  let inputEvents = [];
     61  function onBeforeInput(aEvent) {
     62    beforeInputEvents.push(aEvent);
     63    selectionRanges = [];
     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});
     68    }
     69  }
     70  function onInput(aEvent) {
     71    inputEvents.push(aEvent);
     72  }
     73  editor.addEventListener("beforeinput", onBeforeInput);
     74  editor.addEventListener("input", onInput);
     75 
     76  beforeInputEvents = [];
     77  inputEvents = [];
     78  selection.collapse(editor.firstChild, 0);
     79  getTableEditor().deleteTableCell(1);
     80  is(editor.innerHTML, "out of table<table><tbody><tr><td>default content</td></tr></tbody></table>",
     81     "nsITableEditor.deleteTableCell(1) should do nothing if selection is not in <table>");
     82  // If there were specific inputType value for this API, we should dispatch cancelable "beforeinput", though.
     83  is(beforeInputEvents.length, 1,
     84     '"beforeinput" event should be fired when a call of nsITableEditor.deleteTableCell(1) even though it will do nothing');
     85  checkInputEvent(beforeInputEvents[0], "when selection is collapsed outside table element");
     86  is(inputEvents.length, 0,
     87     'No "input" event should be fired when a call of nsITableEditor.deleteTableCell(1) does nothing');
     88 
     89  selection.removeAllRanges();
     90  try {
     91    beforeInputEvents = [];
     92    inputEvents = [];
     93    getTableEditor().deleteTableCell(1);
     94    ok(false, "getTableEditor().deleteTableCell(1) without selection ranges should throw exception");
     95  } catch (e) {
     96    ok(true, "getTableEditor().deleteTableCell(1) without selection ranges should throw exception");
     97    is(beforeInputEvents.length, 0,
     98       'No "beforeinput" event should be fired when nsITableEditor.deleteTableCell(1) causes exception due to no selection range');
     99    is(inputEvents.length, 0,
    100       'No "input" event should be fired when nsITableEditor.deleteTableCell(1) causes exception due to no selection range');
    101  }
    102 
    103  selection.removeAllRanges();
    104  editor.innerHTML = "<table>" +
    105                       '<tr><td id="select">cell1-1</td><td>cell1-2</td><td>cell1-3</td></tr>' +
    106                       "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    107                     "</table>";
    108  beforeInputEvents = [];
    109  inputEvents = [];
    110  let range = document.createRange();
    111  range.selectNode(document.getElementById("select"));
    112  selection.addRange(range);
    113  getTableEditor().deleteTableCell(1);
    114  is(editor.innerHTML, "<table><tbody>" +
    115                         "<tr><td>cell1-2</td><td>cell1-3</td></tr>" +
    116                         "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    117                       "</tbody></table>",
    118     "nsITableEditor.deleteTableCellContents(1) should remove only selected cell when only one cell is selected #1-1");
    119  is(beforeInputEvents.length, 1,
    120     'Only one "beforeinput" event should be fired when only one cell is selected #1-1');
    121  checkInputEvent(beforeInputEvents[0], "when only one cell is selected #1-1");
    122  is(inputEvents.length, 1,
    123     'Only one "input" event should be fired when only one cell is selected #1-1');
    124  checkInputEvent(inputEvents[0], "when only one cell is selected #1-1");
    125 
    126  selection.removeAllRanges();
    127  editor.innerHTML = "<table>" +
    128                       '<tr><td>cell1-1</td><td id="select">cell1-2</td><td>cell1-3</td></tr>' +
    129                       "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    130                     "</table>";
    131  beforeInputEvents = [];
    132  inputEvents = [];
    133  range = document.createRange();
    134  range.selectNode(document.getElementById("select"));
    135  selection.addRange(range);
    136  getTableEditor().deleteTableCell(1);
    137  is(editor.innerHTML, "<table><tbody>" +
    138                         "<tr><td>cell1-1</td><td>cell1-3</td></tr>" +
    139                         "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    140                       "</tbody></table>",
    141     "nsITableEditor.deleteTableCellContents(1) should remove only selected cell when only one cell is selected #1-2");
    142  is(beforeInputEvents.length, 1,
    143     'Only one "beforeinput" event should be fired when only one cell is selected #1-2');
    144  checkInputEvent(beforeInputEvents[0], "when only one cell is selected #1-2");
    145  is(inputEvents.length, 1,
    146     'Only one "input" event should be fired when only one cell is selected #1-2');
    147  checkInputEvent(inputEvents[0], "when only one cell is selected #1-2");
    148 
    149  selection.removeAllRanges();
    150  editor.innerHTML = "<table>" +
    151                       '<tr><td>cell1-1</td><td>cell1-2</td><td id="select">cell1-3</td></tr>' +
    152                       "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    153                     "</table>";
    154  beforeInputEvents = [];
    155  inputEvents = [];
    156  range = document.createRange();
    157  range.selectNode(document.getElementById("select"));
    158  selection.addRange(range);
    159  getTableEditor().deleteTableCell(1);
    160  is(editor.innerHTML, "<table><tbody>" +
    161                         "<tr><td>cell1-1</td><td>cell1-2</td></tr>" +
    162                         "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    163                       "</tbody></table>",
    164     "nsITableEditor.deleteTableCellContents(1) should remove only selected cell when only one cell is selected #1-3");
    165  is(beforeInputEvents.length, 1,
    166     'Only one "beforeinput" event should be fired when only one cell is selected #1-3');
    167  checkInputEvent(beforeInputEvents[0], "when only one cell is selected #1-3");
    168  is(inputEvents.length, 1,
    169     'Only one "input" event should be fired when only one cell is selected #1-3');
    170  checkInputEvent(inputEvents[0], "when only one cell is selected #1-3");
    171 
    172  // When only one cell element is selected, the argument should be used.
    173  selection.removeAllRanges();
    174  editor.innerHTML = "<table>" +
    175                       '<tr><td id="select">cell1-1</td><td>cell1-2</td><td>cell1-3</td></tr>' +
    176                       "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    177                     "</table>";
    178  beforeInputEvents = [];
    179  inputEvents = [];
    180  range = document.createRange();
    181  range.selectNode(document.getElementById("select"));
    182  selection.addRange(range);
    183  getTableEditor().deleteTableCell(2);
    184  is(editor.innerHTML, "<table><tbody>" +
    185                         "<tr><td>cell1-3</td></tr>" +
    186                         "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    187                       "</tbody></table>",
    188     "nsITableEditor.deleteTableCellContents(2) should remove selected cell element and next cell element in same row #1-4");
    189  is(beforeInputEvents.length, 1,
    190     'Only one "beforeinput" event should be fired when only one cell is selected #1-4');
    191  checkInputEvent(beforeInputEvents[0], "when only one cell is selected #1-4");
    192  is(inputEvents.length, 1,
    193     'Only one "input" event should be fired when only one cell is selected #1-4');
    194  checkInputEvent(inputEvents[0], "when only one cell is selected #1-4");
    195 
    196  // When the argument is larger than remaining cell elements from selected
    197  // cell element, the behavior is really buggy.
    198  selection.removeAllRanges();
    199  editor.innerHTML = "<table>" +
    200                       '<tr><td>cell1-1</td><td>cell1-2</td><td id="select">cell1-3</td></tr>' +
    201                       "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    202                     "</table>";
    203  beforeInputEvents = [];
    204  inputEvents = [];
    205  range = document.createRange();
    206  range.selectNode(document.getElementById("select"));
    207  selection.addRange(range);
    208  getTableEditor().deleteTableCell(2);
    209  is(editor.innerHTML, "<table><tbody>" +
    210                         "<tr><td>cell1-1</td></tr>" +
    211                         "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    212                       "</tbody></table>",
    213     "nsITableEditor.deleteTableCellContents(2) should remove selected cell element and its previous cell element when it reaches the last cell element in the row");
    214  is(beforeInputEvents.length, 1,
    215     'Only one "beforeinput" event should be fired when the argument is larger than remaining cell elements from selected cell element');
    216  checkInputEvent(beforeInputEvents[0], "when the argument is larger than remaining cell elements from selected cell element");
    217  is(inputEvents.length, 1,
    218     'Only one "input" event should be fired when the argument is larger than remaining cell elements from selected cell element');
    219  checkInputEvent(inputEvents[0], "when the argument is larger than remaining cell elements from selected cell element");
    220 
    221  // XXX If the former case is expected, first row should be removed in this
    222  //     case, but it removes only selected cell and its previous cell.
    223  selection.removeAllRanges();
    224  editor.innerHTML = "<table>" +
    225                       '<tr><td>cell1-1</td><td>cell1-2</td><td id="select">cell1-3</td></tr>' +
    226                       "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    227                     "</table>";
    228  beforeInputEvents = [];
    229  inputEvents = [];
    230  range = document.createRange();
    231  range.selectNode(document.getElementById("select"));
    232  selection.addRange(range);
    233  getTableEditor().deleteTableCell(4);
    234  todo_is(editor.innerHTML, "<table><tbody>" +
    235                               "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    236                            "</tbody></table>",
    237          "nsITableEditor.deleteTableCellContents(4) should remove the first row when a cell in it is selected and the argument is larger than number of cells in the row");
    238  is(beforeInputEvents.length, 1,
    239     'Only one "beforeinput" event should be fired when the argument is larger than number of cells in the row');
    240  checkInputEvent(beforeInputEvents[0], "when the argument is larger than number of cells in the row");
    241  is(inputEvents.length, 1,
    242     'Only one "input" event should be fired when the argument is larger than number of cells in the row');
    243  checkInputEvent(inputEvents[0], "when the argument is larger than number of cells in the row");
    244 
    245  // If 2 or more cells are selected, the argument should be ignored.
    246  selection.removeAllRanges();
    247  editor.innerHTML = "<table>" +
    248                       '<tr><td id="select1">cell1-1</td><td>cell1-2</td><td>cell1-3</td></tr>' +
    249                       '<tr><td>cell2-1</td><td id="select2">cell2-2</td><td>cell2-3</td></tr>' +
    250                     "</table>";
    251  beforeInputEvents = [];
    252  inputEvents = [];
    253  range = document.createRange();
    254  range.selectNode(document.getElementById("select1"));
    255  selection.addRange(range);
    256  range = document.createRange();
    257  range.selectNode(document.getElementById("select2"));
    258  selection.addRange(range);
    259  getTableEditor().deleteTableCell(1);
    260  is(editor.innerHTML, "<table><tbody>" +
    261                         "<tr><td>cell1-2</td><td>cell1-3</td></tr>" +
    262                         "<tr><td>cell2-1</td><td>cell2-3</td></tr>" +
    263                       "</tbody></table>",
    264     "nsITableEditor.deleteTableCellContents(1) should remove selected cell elements even if the argument is smaller than number of selected cells");
    265  is(beforeInputEvents.length, 1,
    266     'Only one "beforeinput" event should be fired even if the argument is smaller than number of selected cells');
    267  checkInputEvent(beforeInputEvents[0], "even if the argument is smaller than number of selected cells");
    268  is(inputEvents.length, 1,
    269     'Only one "input" event should be fired even if the argument is smaller than number of selected cells');
    270  checkInputEvent(inputEvents[0], "even if the argument is smaller than number of selected cells");
    271 
    272  // If all cells in a row are selected, the <tr> element should also be removed.
    273  selection.removeAllRanges();
    274  editor.innerHTML = "<table>" +
    275                       '<tr><td id="select1">cell1-1</td><td id="select2">cell1-2</td><td id="select3">cell1-3</td></tr>' +
    276                       "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    277                     "</table>";
    278  beforeInputEvents = [];
    279  inputEvents = [];
    280  range = document.createRange();
    281  range.selectNode(document.getElementById("select1"));
    282  selection.addRange(range);
    283  range = document.createRange();
    284  range.selectNode(document.getElementById("select2"));
    285  selection.addRange(range);
    286  range = document.createRange();
    287  range.selectNode(document.getElementById("select3"));
    288  selection.addRange(range);
    289  getTableEditor().deleteTableCell(1);
    290  is(editor.innerHTML, "<table><tbody>" +
    291                         "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    292                       "</tbody></table>",
    293     "nsITableEditor.deleteTableCellContents(1) should remove also <tr> element when all cell elements in a row is selected");
    294  is(beforeInputEvents.length, 1,
    295     'Only one "beforeinput" event should be fired when all cell elements in a row is selected');
    296  checkInputEvent(beforeInputEvents[0], "when all cell elements in a row is selected");
    297  is(inputEvents.length, 1,
    298     'Only one "input" event should be fired when all cell elements in a row is selected');
    299  checkInputEvent(inputEvents[0], "when all cell elements in a row is selected");
    300 
    301  selection.removeAllRanges();
    302  editor.innerHTML = "<table>" +
    303                       '<tr><td id="select">cell1-1</td></tr>' +
    304                       "<tr><td>cell2-1</td></tr>" +
    305                     "</table>";
    306  beforeInputEvents = [];
    307  inputEvents = [];
    308  range = document.createRange();
    309  range.selectNode(document.getElementById("select"));
    310  selection.addRange(range);
    311  getTableEditor().deleteTableCell(1);
    312  is(editor.innerHTML, "<table><tbody>" +
    313                         "<tr><td>cell2-1</td></tr>" +
    314                       "</tbody></table>",
    315     "nsITableEditor.deleteTableCellContents(1) should remove also <tr> element when a cell element which is only child of a row is selected");
    316  is(beforeInputEvents.length, 1,
    317     'Only one "beforeinput" event should be fired when a cell element which is only child of a row is selected');
    318  checkInputEvent(beforeInputEvents[0], "when a cell element which is only child of a row is selected");
    319  is(inputEvents.length, 1,
    320     'Only one "input" event should be fired when a cell element which is only child of a row is selected');
    321  checkInputEvent(inputEvents[0], "when a cell element which is only child of a row is selected");
    322 
    323  // If all cells are removed, the <table> element should be removed.
    324  selection.removeAllRanges();
    325  editor.innerHTML = "<table>" +
    326                       '<tr><td id="select1">cell1-1</td><td id="select2">cell1-2</td></tr>' +
    327                       '<tr><td id="select3">cell2-1</td><td id="select4">cell2-2</td></tr>' +
    328                     "</table>";
    329  beforeInputEvents = [];
    330  inputEvents = [];
    331  range = document.createRange();
    332  range.selectNode(document.getElementById("select1"));
    333  selection.addRange(range);
    334  range = document.createRange();
    335  range.selectNode(document.getElementById("select2"));
    336  selection.addRange(range);
    337  range = document.createRange();
    338  range.selectNode(document.getElementById("select3"));
    339  selection.addRange(range);
    340  range = document.createRange();
    341  range.selectNode(document.getElementById("select4"));
    342  selection.addRange(range);
    343  getTableEditor().deleteTableCell(1);
    344  is(editor.innerHTML, "",
    345     "nsITableEditor.deleteTableCellContents(1) should remove also <table> element when all cell elements are selected");
    346  is(beforeInputEvents.length, 1,
    347     'Only one "beforeinput" event should be fired when all cell elements are selected');
    348  checkInputEvent(beforeInputEvents[0], "when all cell elements are selected");
    349  is(inputEvents.length, 1,
    350     'Only one "input" event should be fired when all cell elements are selected');
    351  checkInputEvent(inputEvents[0], "when all cell elements are selected");
    352 
    353  selection.removeAllRanges();
    354  editor.innerHTML = "<table>" +
    355                       '<tr><td id="select">cell1-1</td></tr>' +
    356                     "</table>";
    357  beforeInputEvents = [];
    358  inputEvents = [];
    359  range = document.createRange();
    360  range.selectNode(document.getElementById("select"));
    361  selection.addRange(range);
    362  getTableEditor().deleteTableCell(1);
    363  is(editor.innerHTML, "",
    364     "nsITableEditor.deleteTableCellContents(1) should remove also <table> element when a cell element which is only child of <table> is selected");
    365  is(beforeInputEvents.length, 1,
    366     'Only one "beforeinput" event should be fired when a cell element which is only child of <table> is selected');
    367  checkInputEvent(beforeInputEvents[0], "when a cell element which is only child of <table> is selected");
    368  is(inputEvents.length, 1,
    369     'Only one "input" event should be fired when a cell element which is only child of <table> is selected');
    370  checkInputEvent(inputEvents[0], "when a cell element which is only child of <table> is selected");
    371 
    372  // rowspan
    373  selection.removeAllRanges();
    374  editor.innerHTML = "<table>" +
    375                       '<tr><td id="select" rowspan="2">cell1-1</td><td>cell1-2</td></tr>' +
    376                       "<tr><td>cell2-2</td></tr>" +
    377                       "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    378                     "</table>";
    379  beforeInputEvents = [];
    380  inputEvents = [];
    381  range = document.createRange();
    382  range.selectNode(document.getElementById("select"));
    383  selection.addRange(range);
    384  getTableEditor().deleteTableCell(1);
    385  is(editor.innerHTML, "<table><tbody>" +
    386                         "<tr><td>cell1-2</td></tr>" +
    387                         "<tr><td>cell2-2</td></tr>" +
    388                         "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    389                       "</tbody></table>",
    390     "nsITableEditor.deleteTableCellContents(1) should just remove the cell spanning rows");
    391  is(beforeInputEvents.length, 1,
    392     'Only one "beforeinput" event should be fired when removing the cell spanning rows');
    393  checkInputEvent(beforeInputEvents[0], "when removing the cell spanning rows");
    394  is(inputEvents.length, 1,
    395     'Only one "input" event should be fired when removing the cell spanning rows');
    396  checkInputEvent(inputEvents[0], "when removing the cell spanning rows");
    397 
    398  // XXX cell3-1 is also removed even though it's not selected.
    399  selection.removeAllRanges();
    400  editor.innerHTML = "<table>" +
    401                       '<tr><td id="select1" rowspan="2">cell1-1</td><td>cell1-2</td></tr>' +
    402                       "<tr><td>cell2-2</td></tr>" +
    403                       '<tr><td>cell3-1</td><td id="select2">cell3-2</td></tr>' +
    404                     "</table>";
    405  beforeInputEvents = [];
    406  inputEvents = [];
    407  range = document.createRange();
    408  range.selectNode(document.getElementById("select1"));
    409  selection.addRange(range);
    410  range = document.createRange();
    411  range.selectNode(document.getElementById("select2"));
    412  selection.addRange(range);
    413  getTableEditor().deleteTableCell(1);
    414  todo_is(editor.innerHTML, "<table><tbody>" +
    415                              "<tr><td>cell1-2</td></tr>" +
    416                              "<tr><td>cell2-2</td></tr>" +
    417                              "<tr><td>cell3-1</td></tr>" +
    418                            "</tbody></table>",
    419          "nsITableEditor.deleteTableCellContents(1) should just remove the cell spanning rows (when 2 cell elements are selected)");
    420  is(beforeInputEvents.length, 1,
    421     'Only one "beforeinput" event should be fired when removing the cell spanning rows (when 2 cell elements are selected)');
    422  checkInputEvent(beforeInputEvents[0], "when removing the cell spanning rows (when 2 cell elements are selected)");
    423  is(inputEvents.length, 1,
    424     'Only one "input" event should be fired when removing the cell spanning rows (when 2 cell elements are selected)');
    425  checkInputEvent(inputEvents[0], "when removing the cell spanning rows (when 2 cell elements are selected)");
    426 
    427  selection.removeAllRanges();
    428  editor.innerHTML = "<table>" +
    429                       '<tr><td rowspan="2">cell1-1</td><td>cell1-2</td></tr>' +
    430                       '<tr><td id="select">cell2-2</td></tr>' +
    431                       "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    432                     "</table>";
    433  beforeInputEvents = [];
    434  inputEvents = [];
    435  range = document.createRange();
    436  range.selectNode(document.getElementById("select"));
    437  selection.addRange(range);
    438  getTableEditor().deleteTableCell(1);
    439  is(editor.innerHTML, "<table><tbody>" +
    440                         '<tr><td rowspan="1">cell1-1</td><td>cell1-2</td></tr>' +
    441                         "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    442                       "</tbody></table>",
    443     "nsITableEditor.deleteTableCellContents(1) should adjust rowspan when spanned <tr>'s last child cell element is removed");
    444  is(beforeInputEvents.length, 1,
    445     'Only one "beforeinput" event should be fired when spanned <tr>\'s last child cell element is removed');
    446  checkInputEvent(beforeInputEvents[0], "when spanned <tr>'s last child cell element is removed");
    447  is(inputEvents.length, 1,
    448     'Only one "input" event should be fired when spanned <tr>\'s last child cell element is removed');
    449  checkInputEvent(inputEvents[0], "when spanned <tr>'s last child cell element is removed");
    450 
    451  // XXX broken case, the second row isn't removed.
    452  selection.removeAllRanges();
    453  editor.innerHTML = "<table>" +
    454                       '<tr><td rowspan="2">cell1-1</td><td>cell1-2</td></tr>' +
    455                       '<tr><td id="select1">cell2-2</td></tr>' +
    456                       '<tr><td>cell3-1</td><td id="select2">cell3-2</td></tr>' +
    457                     "</table>";
    458  beforeInputEvents = [];
    459  inputEvents = [];
    460  range = document.createRange();
    461  range.selectNode(document.getElementById("select1"));
    462  selection.addRange(range);
    463  range = document.createRange();
    464  range.selectNode(document.getElementById("select2"));
    465  selection.addRange(range);
    466  getTableEditor().deleteTableCell(1);
    467  todo_is(editor.innerHTML, "<table><tbody>" +
    468                              '<tr><td rowspan="1">cell1-1</td><td>cell1-2</td></tr>' +
    469                              "<tr><td>cell3-1</td></tr>" +
    470                            "</tbody></table>",
    471          "nsITableEditor.deleteTableCellContents(1) should adjust rowspan when spanned <tr>'s last child cell element is removed (when 2 cell elements are selected)");
    472  is(beforeInputEvents.length, 1,
    473     'Only one "beforeinput" event should be fired when spanned <tr>\'s last child cell element is removed (when 2 cell elements are selected)');
    474  checkInputEvent(beforeInputEvents[0], "when spanned <tr>'s last child cell element is removed (when 2 cell elements are selected)");
    475  is(inputEvents.length, 1,
    476     'Only one "input" event should be fired when spanned <tr>\'s last child cell element is removed (when 2 cell elements are selected)');
    477  checkInputEvent(inputEvents[0], "when spanned <tr>'s last child cell element is removed (when 2 cell elements are selected)");
    478 
    479  // XXX broken case, neither the selected cell nor the second row is removed.
    480  selection.removeAllRanges();
    481  editor.innerHTML = "<table>" +
    482                       '<tr><td rowspan="3">cell1-1</td><td>cell1-2</td></tr>' +
    483                       '<tr><td id="select">cell2-2</td></tr>' +
    484                       "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    485                     "</table>";
    486  beforeInputEvents = [];
    487  inputEvents = [];
    488  range = document.createRange();
    489  range.selectNode(document.getElementById("select"));
    490  selection.addRange(range);
    491  getTableEditor().deleteTableCell(1);
    492  todo_is(editor.innerHTML, "<table><tbody>" +
    493                              '<tr><td rowspan="2">cell1-1</td><td>cell1-2</td></tr>' +
    494                              "<tr><td>cell3-2</td></tr>" +
    495                            "</tbody></table>",
    496          "nsITableEditor.deleteTableCellContents(1) should adjust rowspan when spanned <tr>'s last child cell element is removed (removing middle row)");
    497  is(beforeInputEvents.length, 1,
    498          'Only one "beforeinput" event should be fired when spanned <tr>\'s last child cell element is removed (removing middle row)');
    499  checkInputEvent(beforeInputEvents[0], "when spanned <tr>'s last child cell element is removed (removing middle row)");
    500  todo_is(inputEvents.length, 1,
    501          'Only one "input" event should be fired when spanned <tr>\'s last child cell element is removed (removing middle row)');
    502  if (inputEvents.length) {
    503    checkInputEvent(inputEvents[0], "when spanned <tr>'s last child cell element is removed (removing middle row)");
    504  }
    505 
    506  selection.removeAllRanges();
    507  editor.innerHTML = "<table>" +
    508                       '<tr><td rowspan="3">cell1-1</td><td>cell1-2</td></tr>' +
    509                       '<tr><td id="select1">cell2-2</td></tr>' +
    510                       '<tr><td>cell3-1</td><td id="select2">cell3-2</td></tr>' +
    511                     "</table>";
    512  beforeInputEvents = [];
    513  inputEvents = [];
    514  range = document.createRange();
    515  range.selectNode(document.getElementById("select1"));
    516  selection.addRange(range);
    517  range = document.createRange();
    518  range.selectNode(document.getElementById("select2"));
    519  selection.addRange(range);
    520  getTableEditor().deleteTableCell(1);
    521  todo_is(editor.innerHTML, "<table><tbody>" +
    522                              '<tr><td rowspan="2">cell1-1</td><td>cell1-2</td></tr>' +
    523                            "</tbody></table>",
    524          "nsITableEditor.deleteTableCellContents(1) should adjust rowspan when spanned <tr>'s last child cell element and remove the last row");
    525  is(beforeInputEvents.length, 1,
    526     'Only one "beforeinput" event should be fired when spanned <tr>\'s last child cell element and remove the last row');
    527  checkInputEvent(beforeInputEvents[0], "when spanned <tr>'s last child cell element and remove the last row");
    528  is(inputEvents.length, 1,
    529     'Only one "input" event should be fired when spanned <tr>\'s last child cell element and remove the last row');
    530  checkInputEvent(inputEvents[0], "when spanned <tr>'s last child cell element and remove the last row");
    531 
    532  // colspan
    533  selection.removeAllRanges();
    534  editor.innerHTML = "<table>" +
    535                       '<tr><td id="select" colspan="2">cell1-1</td><td>cell1-3</td></tr>' +
    536                       "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    537                     "</table>";
    538  beforeInputEvents = [];
    539  inputEvents = [];
    540  range = document.createRange();
    541  range.selectNode(document.getElementById("select"));
    542  selection.addRange(range);
    543  getTableEditor().deleteTableCell(1);
    544  is(editor.innerHTML, "<table><tbody>" +
    545                         "<tr><td>cell1-3</td></tr>" +
    546                         "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    547                       "</tbody></table>",
    548     "nsITableEditor.deleteTableCellContents(1) should just remove the cell spanning columns");
    549  is(beforeInputEvents.length, 1,
    550     'Only one "beforeinput" event should be fired when removing the cell spanning columns');
    551  checkInputEvent(beforeInputEvents[0], "when removing the cell spanning columns");
    552  is(inputEvents.length, 1,
    553     'Only one "input" event should be fired when removing the cell spanning columns');
    554  checkInputEvent(inputEvents[0], "when removing the cell spanning columns");
    555 
    556  selection.removeAllRanges();
    557  editor.innerHTML = "<table>" +
    558                       '<tr><td id="select1" colspan="2">cell1-1</td><td>cell1-3</td></tr>' +
    559                       '<tr><td>cell2-1</td><td id="select2">cell2-2</td><td>cell2-3</td></tr>' +
    560                     "</table>";
    561  beforeInputEvents = [];
    562  inputEvents = [];
    563  range = document.createRange();
    564  range.selectNode(document.getElementById("select1"));
    565  selection.addRange(range);
    566  range = document.createRange();
    567  range.selectNode(document.getElementById("select2"));
    568  selection.addRange(range);
    569  getTableEditor().deleteTableCell(1);
    570  is(editor.innerHTML, "<table><tbody>" +
    571                         "<tr><td>cell1-3</td></tr>" +
    572                         "<tr><td>cell2-1</td><td>cell2-3</td></tr>" +
    573                       "</tbody></table>",
    574     "nsITableEditor.deleteTableCellContents(1) should just remove the cell spanning columns and the other selected cell element");
    575  is(beforeInputEvents.length, 1,
    576     'Only one "beforeinput" event should be fired when removing the cell spanning columns and the other selected cell element');
    577  checkInputEvent(beforeInputEvents[0], "when removing the cell spanning columns and the other selected cell element");
    578  is(inputEvents.length, 1,
    579     'Only one "input" event should be fired when removing the cell spanning columns and the other selected cell element');
    580  checkInputEvent(inputEvents[0], "when removing the cell spanning columns and the other selected cell element");
    581 
    582  // XXX broken case, colspan is not adjusted.
    583  selection.removeAllRanges();
    584  editor.innerHTML = "<table>" +
    585                       '<tr><td colspan="2">cell1-1</td><td>cell1-3</td></tr>' +
    586                       '<tr><td>cell2-1</td><td id="select">cell2-2</td><td>cell2-3</td></tr>' +
    587                     "</table>";
    588  beforeInputEvents = [];
    589  inputEvents = [];
    590  range = document.createRange();
    591  range.selectNode(document.getElementById("select"));
    592  selection.addRange(range);
    593  getTableEditor().deleteTableCell(1);
    594  todo_is(editor.innerHTML, "<table><tbody>" +
    595                              '<tr><td colspan="1">cell1-1</td><td>cell1-3</td></tr>' +
    596                              "<tr><td>cell2-1</td><td>cell2-3</td></tr>" +
    597                            "</tbody></table>",
    598          "nsITableEditor.deleteTableCellContents(1) should adjust different row's colspan when corresponding cell element is removed");
    599  is(beforeInputEvents.length, 1,
    600     'Only one "beforeinput" event should be fired when corresponding cell element is removed');
    601  checkInputEvent(beforeInputEvents[0], "when corresponding cell element is removed");
    602  is(inputEvents.length, 1,
    603     'Only one "input" event should be fired when corresponding cell element is removed');
    604  checkInputEvent(inputEvents[0], "when corresponding cell element is removed");
    605 
    606  selection.removeAllRanges();
    607  editor.innerHTML = "<table>" +
    608                       '<tr><td colspan="2">cell1-1</td><td>cell1-3</td></tr>' +
    609                       '<tr><td>cell2-1</td><td id="select1">cell2-2</td><td id="select2">cell2-3</td></tr>' +
    610                     "</table>";
    611  beforeInputEvents = [];
    612  inputEvents = [];
    613  range = document.createRange();
    614  range.selectNode(document.getElementById("select1"));
    615  selection.addRange(range);
    616  range = document.createRange();
    617  range.selectNode(document.getElementById("select2"));
    618  selection.addRange(range);
    619  getTableEditor().deleteTableCell(1);
    620  todo_is(editor.innerHTML, "<table><tbody>" +
    621                              '<tr><td colspan="1">cell1-1</td><td>cell1-3</td></tr>' +
    622                              "<tr><td>cell2-1</td></tr>" +
    623                            "</tbody></table>",
    624          "nsITableEditor.deleteTableCellContents(1) should adjust different row's colspan when corresponding cell element is removed (when 2 cell elements are selected)");
    625  is(beforeInputEvents.length, 1,
    626     'Only one "beforeinput" event should be fired when corresponding cell element is removed (when 2 cell elements are selected)');
    627  checkInputEvent(beforeInputEvents[0], "when corresponding cell element is removed (when 2 cell elements are selected)");
    628  is(inputEvents.length, 1,
    629     'Only one "input" event should be fired when corresponding cell element is removed (when 2 cell elements are selected)');
    630  checkInputEvent(inputEvents[0], "when corresponding cell element is removed (when 2 cell elements are selected)");
    631 
    632  selection.removeAllRanges();
    633  editor.innerHTML = "<table>" +
    634                       '<tr><td>cell1-1</td><td id="select1">cell1-2</td><td>cell1-4</td></tr>' +
    635                       '<tr><td id="select2" colspan="2">cell2-1</td><td>cell2-3</td><td>cell2-4</td></tr>' +
    636                     "</table>";
    637  beforeInputEvents = [];
    638  inputEvents = [];
    639  range = document.createRange();
    640  range.selectNode(document.getElementById("select1"));
    641  selection.addRange(range);
    642  range = document.createRange();
    643  range.selectNode(document.getElementById("select2"));
    644  selection.addRange(range);
    645  getTableEditor().deleteTableCell(1);
    646  is(editor.innerHTML, "<table><tbody>" +
    647                              "<tr><td>cell1-1</td><td>cell1-4</td></tr>" +
    648                              "<tr><td>cell2-3</td><td>cell2-4</td></tr>" +
    649                            "</tbody></table>",
    650          "nsITableEditor.deleteTableCellContents(1) should adjust different row's colspan when corresponding cell element is removed (when 2 cell elements are selected)");
    651  is(beforeInputEvents.length, 1,
    652     'Only one "beforeinput" event should be fired when corresponding cell element is removed (when 2 cell elements are selected)');
    653  checkInputEvent(beforeInputEvents[0], "when corresponding cell element is removed (when 2 cell elements are selected)");
    654  is(inputEvents.length, 1,
    655     'Only one "input" event should be fired when corresponding cell element is removed (when 2 cell elements are selected)');
    656  checkInputEvent(inputEvents[0], "when corresponding cell element is removed (when 2 cell elements are selected)");
    657 
    658  // When a cell contains first selection range, it should be removed.
    659  selection.removeAllRanges();
    660  editor.innerHTML = "<table>" +
    661                       '<tr><td id="select">cell1-1</td><td>cell1-2</td><td>cell1-3</td></tr>' +
    662                       "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    663                     "</table>";
    664  beforeInputEvents = [];
    665  inputEvents = [];
    666  selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
    667                             document.getElementById("select").firstChild, 1);
    668  getTableEditor().deleteTableCell(1);
    669  is(editor.innerHTML, "<table><tbody>" +
    670                         "<tr><td>cell1-2</td><td>cell1-3</td></tr>" +
    671                         "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    672                       "</tbody></table>",
    673     "nsITableEditor.deleteTableCellContents(1) should remove only a cell containing first selection range when there is no selected cell element");
    674  is(beforeInputEvents.length, 1,
    675     'Only one "beforeinput" event should be fired when there is no selected cell element');
    676  checkInputEvent(beforeInputEvents[0], "when there is no selected cell element");
    677  is(inputEvents.length, 1,
    678     'Only one "input" event should be fired when there is no selected cell element');
    679  checkInputEvent(inputEvents[0], "when there is no selected cell element");
    680 
    681  selection.removeAllRanges();
    682  editor.innerHTML = "<table>" +
    683                       '<tr><td id="select">cell1-1</td><td>cell1-2</td><td>cell1-3</td></tr>' +
    684                       "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    685                     "</table>";
    686  beforeInputEvents = [];
    687  inputEvents = [];
    688  selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
    689                             document.getElementById("select").firstChild, 1);
    690  getTableEditor().deleteTableCell(2);
    691  is(editor.innerHTML, "<table><tbody>" +
    692                         "<tr><td>cell1-3</td></tr>" +
    693                         "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
    694                       "</tbody></table>",
    695     "nsITableEditor.deleteTableCellContents(2) should remove only 2 cell elements starting from a cell containing first selection range when there is no selected cell element");
    696  is(beforeInputEvents.length, 1,
    697     'Only one "beforeinput" event should be fired when there is no selected cell element');
    698  checkInputEvent(beforeInputEvents[0], "when there is no selected cell element");
    699  is(inputEvents.length, 1,
    700     'Only one "input" event should be fired when there is no selected cell element');
    701  checkInputEvent(inputEvents[0], "when there is no selected cell element");
    702 
    703  editor.removeEventListener("input", onInput);
    704 
    705  SimpleTest.finish();
    706 });
    707 
    708 function getTableEditor() {
    709  var editingSession = SpecialPowers.wrap(window).docShell.editingSession;
    710  return editingSession.getEditorForWindow(window).QueryInterface(SpecialPowers.Ci.nsITableEditor);
    711 }
    712 
    713 </script>
    714 </body>
    715 
    716 </html>