tor-browser

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

test_nsITableEditor_insertTableRow.html (21140B)


      1 <!DOCTYPE>
      2 <html>
      3 <head>
      4  <title>Test for nsITableEditor.insertTableRow()</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, 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}`);
     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().insertTableRow(1, false);
     80  is(editor.innerHTML, "out of table<table><tbody><tr><td>default content</td></tr></tbody></table>",
     81     "nsITableEditor.insertTableRow(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.insertTableRow(1, false) even though it will do nothing');
     84  checkInputEvent(beforeInputEvents[0], "when selection is collapsed outside of table element (nsITableEditor.insertTableRow(1, false))");
     85  is(inputEvents.length, 0,
     86     'No "input" event should be fired when a call of nsITableEditor.insertTableRow(1, false) does nothing');
     87 
     88  beforeInputEvents = [];
     89  inputEvents = [];
     90  getTableEditor().insertTableRow(1, true);
     91  is(editor.innerHTML, "out of table<table><tbody><tr><td>default content</td></tr></tbody></table>",
     92     "nsITableEditor.insertTableRow(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.insertTableRow(1, true) even though it will do nothing');
     95  checkInputEvent(beforeInputEvents[0], "when selection is collapsed outside of table element (nsITableEditor.insertTableRow(1, true))");
     96  is(inputEvents.length, 0,
     97     'No "input" event should be fired when a call of nsITableEditor.insertTableRow(1, true) does nothing');
     98 
     99  selection.removeAllRanges();
    100  try {
    101    beforeInputEvents = [];
    102    inputEvents = [];
    103    getTableEditor().insertTableRow(1, false);
    104    ok(false, "getTableEditor().insertTableRow(1, false) without selection ranges should throw exception");
    105  } catch (e) {
    106    ok(true, "getTableEditor().insertTableRow(1, false) without selection ranges should throw exception");
    107    is(beforeInputEvents.length, 0,
    108       'No "beforeinput" event should be fired when nsITableEditor.insertTableRow(1, false) causes exception due to no selection range');
    109    is(inputEvents.length, 0,
    110       'No "input" event should be fired when nsITableEditor.insertTableRow(1, false) causes exception due to no selection range');
    111  }
    112  try {
    113    beforeInputEvents = [];
    114    inputEvents = [];
    115    getTableEditor().insertTableRow(1, true);
    116    ok(false, "getTableEditor().insertTableRow(1, true) without selection ranges should throw exception");
    117  } catch (e) {
    118    ok(true, "getTableEditor().insertTableRow(1, true) without selection ranges should throw exception");
    119    is(beforeInputEvents.length, 0,
    120       'No "beforeinput" event should be fired when nsITableEditor.insertTableRow(1, true) causes exception due to no selection range');
    121    is(inputEvents.length, 0,
    122       'No "input" event should be fired when nsITableEditor.insertTableRow(1, true) causes exception due to no selection range');
    123  }
    124 
    125  selection.removeAllRanges();
    126  editor.innerHTML = "<table>" +
    127                       "<tr><td>cell1-1</td><td>cell1-2</td></tr>" +
    128                       '<tr><td id="select">cell2-1</td><td>cell2-2</td></tr>' +
    129                       "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    130                     "</table>";
    131  editor.focus();
    132  beforeInputEvents = [];
    133  inputEvents = [];
    134  selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
    135                             document.getElementById("select").firstChild, 0);
    136  getTableEditor().insertTableRow(1, false);
    137  is(editor.innerHTML, "<table><tbody>" +
    138                         "<tr><td>cell1-1</td><td>cell1-2</td></tr>" +
    139                         '<tr><td valign="top"><br></td><td valign="top"><br></td></tr>' +
    140                         '<tr><td id="select">cell2-1</td><td>cell2-2</td></tr>' +
    141                         "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    142                       "</tbody></table>",
    143     "nsITableEditor.insertTableRow(1, false) should insert a row above the second row");
    144  is(beforeInputEvents.length, 1,
    145     'Only one "beforeinput" event should be fired when selection is collapsed in a cell in second row (before)');
    146  checkInputEvent(beforeInputEvents[0], "when selection is collapsed in a cell in second row (before)");
    147  is(inputEvents.length, 1,
    148     'Only one "input" event should be fired when selection is collapsed in a cell in second row (before)');
    149  checkInputEvent(inputEvents[0], "when selection is collapsed in a cell in second row (before)");
    150 
    151  selection.removeAllRanges();
    152  editor.innerHTML = "<table>" +
    153                       "<tr><td>cell1-1</td><td>cell1-2</td></tr>" +
    154                       '<tr><td id="select">cell2-1</td><td>cell2-2</td></tr>' +
    155                       "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    156                     "</table>";
    157  editor.focus();
    158  beforeInputEvents = [];
    159  inputEvents = [];
    160  selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
    161                             document.getElementById("select").firstChild, 0);
    162  getTableEditor().insertTableRow(1, true);
    163  is(editor.innerHTML, "<table><tbody>" +
    164                         "<tr><td>cell1-1</td><td>cell1-2</td></tr>" +
    165                         '<tr><td id="select">cell2-1</td><td>cell2-2</td></tr>' +
    166                         '<tr><td valign="top"><br></td><td valign="top"><br></td></tr>' +
    167                         "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    168                       "</tbody></table>",
    169     "nsITableEditor.insertTableRow(1, true) should insert a row below the second row");
    170  is(beforeInputEvents.length, 1,
    171     'Only one "beforeinput" event should be fired when selection is collapsed in a cell in second row (after)');
    172  checkInputEvent(beforeInputEvents[0], "when selection is collapsed in a cell in second row (after)");
    173  is(inputEvents.length, 1,
    174     'Only one "input" event should be fired when selection is collapsed in a cell in second row (after)');
    175  checkInputEvent(inputEvents[0], "when selection is collapsed in a cell in second row (after)");
    176 
    177  selection.removeAllRanges();
    178  editor.innerHTML = "<table>" +
    179                       '<tr><td>cell1-1</td><td rowspan="2">cell1-2</td></tr>' +
    180                       '<tr><td id="select">cell2-1</td></tr>' +
    181                       "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    182                     "</table>";
    183  editor.focus();
    184  beforeInputEvents = [];
    185  inputEvents = [];
    186  selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
    187                             document.getElementById("select").firstChild, 0);
    188  getTableEditor().insertTableRow(1, false);
    189  is(editor.innerHTML, "<table><tbody>" +
    190                         '<tr><td>cell1-1</td><td rowspan="3">cell1-2</td></tr>' +
    191                         '<tr><td valign="top"><br></td></tr>' +
    192                         '<tr><td id="select">cell2-1</td></tr>' +
    193                         "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    194                       "</tbody></table>",
    195     "nsITableEditor.insertTableRow(1, false) should insert a row above the second row and rowspan in the first row should be increased");
    196  is(beforeInputEvents.length, 1,
    197     'Only one "beforeinput" event should be fired when selection is collapsed in a cell in second row which has row-spanned cell (before)');
    198  checkInputEvent(beforeInputEvents[0], "when selection is collapsed in a cell in second row which has row-spanned cell (before)");
    199  is(inputEvents.length, 1,
    200     'Only one "input" event should be fired when selection is collapsed in a cell in second row which has row-spanned cell (before)');
    201  checkInputEvent(inputEvents[0], "when selection is collapsed in a cell in second row which has row-spanned cell (before)");
    202 
    203  selection.removeAllRanges();
    204  editor.innerHTML = "<table>" +
    205                       '<tr><td>cell1-1</td><td rowspan="3">cell1-2</td></tr>' +
    206                       '<tr><td id="select">cell2-1</td></tr>' +
    207                       "<tr><td>cell3-1</td></tr>" +
    208                     "</table>";
    209  editor.focus();
    210  beforeInputEvents = [];
    211  inputEvents = [];
    212  selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
    213                             document.getElementById("select").firstChild, 0);
    214  getTableEditor().insertTableRow(1, true);
    215  is(editor.innerHTML, "<table><tbody>" +
    216                         '<tr><td>cell1-1</td><td rowspan="4">cell1-2</td></tr>' +
    217                         '<tr><td id="select">cell2-1</td></tr>' +
    218                         '<tr><td valign="top"><br></td></tr>' +
    219                         "<tr><td>cell3-1</td></tr>" +
    220                       "</tbody></table>",
    221     "nsITableEditor.insertTableRow(1, true) should insert a row below the second row and rowspan in the first row should be increased");
    222  is(beforeInputEvents.length, 1,
    223     'Only one "beforeinput" event should be fired when selection is collapsed in a cell in second row which has row-spanned cell (after)');
    224  checkInputEvent(beforeInputEvents[0], "when selection is collapsed in a cell in second row which has row-spanned cell (after)");
    225  is(inputEvents.length, 1,
    226     'Only one "input" event should be fired when selection is collapsed in a cell in second row which has row-spanned cell (after)');
    227  checkInputEvent(inputEvents[0], "when selection is collapsed in a cell in second row which has row-spanned cell (after)");
    228 
    229  selection.removeAllRanges();
    230  editor.innerHTML = "<table>" +
    231                       '<tr><td>cell1-1</td><td id="select" rowspan="2">cell1-2</td></tr>' +
    232                       "<tr><td>cell2-1</td></tr>" +
    233                       "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    234                     "</table>";
    235  editor.focus();
    236  beforeInputEvents = [];
    237  inputEvents = [];
    238  selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
    239                             document.getElementById("select").firstChild, 1);
    240  getTableEditor().insertTableRow(2, false);
    241  is(editor.innerHTML, "<table><tbody>" +
    242                         '<tr><td valign="top"><br></td><td valign="top"><br></td></tr>' +
    243                         '<tr><td valign="top"><br></td><td valign="top"><br></td></tr>' +
    244                         '<tr><td>cell1-1</td><td id="select" rowspan="2">cell1-2</td></tr>' +
    245                         "<tr><td>cell2-1</td></tr>" +
    246                         "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    247                       "</tbody></table>",
    248     "nsITableEditor.insertTableRow(2, false) should insert 2 rows above the first row");
    249  is(beforeInputEvents.length, 1,
    250     'Only one "beforeinput" event should be fired when selection is collapsed in a cell which is row-spanning (before)');
    251  checkInputEvent(beforeInputEvents[0], "when selection is collapsed in a cell which is row-spanning (before)");
    252  is(inputEvents.length, 1,
    253     'Only one "input" event should be fired when selection is collapsed in a cell which is row-spanning (before)');
    254  checkInputEvent(inputEvents[0], "when selection is collapsed in a cell which is row-spanning (before)");
    255 
    256  selection.removeAllRanges();
    257  editor.innerHTML = "<table>" +
    258                       '<tr><td>cell1-1</td><td id="select" rowspan="2">cell1-2</td></tr>' +
    259                       "<tr><td>cell2-1</td></tr>" +
    260                       "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    261                     "</table>";
    262  editor.focus();
    263  beforeInputEvents = [];
    264  inputEvents = [];
    265  selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
    266                             document.getElementById("select").firstChild, 1);
    267  getTableEditor().insertTableRow(2, true);
    268  is(editor.innerHTML, "<table><tbody>" +
    269                         '<tr><td>cell1-1</td><td id="select" rowspan="2">cell1-2</td></tr>' +
    270                         "<tr><td>cell2-1</td></tr>" +
    271                         '<tr><td valign="top"><br></td><td valign="top"><br></td></tr>' +
    272                         '<tr><td valign="top"><br></td><td valign="top"><br></td></tr>' +
    273                         "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    274                       "</tbody></table>",
    275     "nsITableEditor.insertTableRow(2, false) should insert 2 rows below the second row (i.e., below the bottom row of the row-spanning cell");
    276  is(beforeInputEvents.length, 1,
    277     'Only one "beforeinput" event should be fired when selection is collapsed in a cell which is row-spanning (after)');
    278  checkInputEvent(beforeInputEvents[0], "when selection is collapsed in a cell which is row-spanning (after)");
    279  is(inputEvents.length, 1,
    280     'Only one "input" event should be fired when selection is collapsed in a cell which is row-spanning (after)');
    281  checkInputEvent(inputEvents[0], "when selection is collapsed in a cell which is row-spanning (after)");
    282 
    283  (function testInsertBeforeRowFollowingTextNode() {
    284    selection.removeAllRanges();
    285    editor.innerHTML =
    286      "<table>" +
    287        "<tr><td>cell1-1</td><td>cell1-2</td></tr>\n" +
    288        '<tr><td id="select">cell2-1</td><td>cell2-2</td></tr>\n' +
    289        "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    290      "</table>";
    291    editor.focus();
    292    beforeInputEvents = [];
    293    inputEvents = [];
    294    selection.setBaseAndExtent(
    295      document.getElementById("select").firstChild,
    296      0,
    297      document.getElementById("select").firstChild,
    298      0
    299    );
    300    getTableEditor().insertTableRow(1, false);
    301    is(
    302      editor.innerHTML,
    303      "<table><tbody>" +
    304        "<tr><td>cell1-1</td><td>cell1-2</td></tr>\n" +
    305        '<tr><td valign="top"><br></td><td valign="top"><br></td></tr>' +
    306        '<tr><td id="select">cell2-1</td><td>cell2-2</td></tr>\n' +
    307        "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    308      "</tbody></table>",
    309      "testInsertBeforeRowFollowingTextNode: nsITableEditor.insertTableRow(1, false) should insert a row above the second row");
    310    is(
    311      beforeInputEvents.length,
    312      1,
    313      'testInsertBeforeRowFollowingTextNode: Only one "beforeinput" event should be fired'
    314    );
    315    checkInputEvent(
    316      beforeInputEvents[0],
    317      "when selection is collapsed in a cell whose row follows a text node (testInsertBeforeRowFollowingTextNode)"
    318    );
    319    is(
    320      inputEvents.length,
    321      1,
    322      'testInsertBeforeRowFollowingTextNode: Only one "input" event should be fired'
    323    );
    324    checkInputEvent(
    325      inputEvents[0],
    326      "when selection is collapsed in a cell whose row follows a text node (testInsertBeforeRowFollowingTextNode)"
    327    );
    328  })();
    329 
    330  (function testInsertAfterRowFollowedTextNode() {
    331    selection.removeAllRanges();
    332    editor.innerHTML =
    333      "<table>" +
    334        "<tr><td>cell1-1</td><td>cell1-2</td></tr>\n" +
    335        '<tr><td id="select">cell2-1</td><td>cell2-2</td></tr>\n' +
    336        "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    337      "</table>";
    338    editor.focus();
    339    beforeInputEvents = [];
    340    inputEvents = [];
    341    selection.setBaseAndExtent(
    342      document.getElementById("select").firstChild,
    343      0,
    344      document.getElementById("select").firstChild,
    345      0
    346    );
    347    getTableEditor().insertTableRow(1, true);
    348    is(
    349      editor.innerHTML,
    350      "<table><tbody>" +
    351        "<tr><td>cell1-1</td><td>cell1-2</td></tr>\n" +
    352        '<tr><td id="select">cell2-1</td><td>cell2-2</td></tr>' +
    353        '<tr><td valign="top"><br></td><td valign="top"><br></td></tr>\n' +
    354        "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
    355      "</tbody></table>",
    356      "testInsertAfterRowFollowedTextNode: nsITableEditor.insertTableRow(1, true) should insert a row above the second row");
    357    is(
    358      beforeInputEvents.length,
    359      1,
    360      'testInsertAfterRowFollowedTextNode: Only one "beforeinput" event should be fired'
    361    );
    362    checkInputEvent(
    363      beforeInputEvents[0],
    364      "when selection is collapsed in a cell whose row follows a text node (testInsertAfterRowFollowedTextNode)"
    365    );
    366    is(
    367      inputEvents.length,
    368      1,
    369      'testInsertAfterRowFollowedTextNode: Only one "input" event should be fired'
    370    );
    371    checkInputEvent(
    372      inputEvents[0],
    373      "when selection is collapsed in a cell whose row follows a text node (testInsertAfterRowFollowedTextNode)"
    374    );
    375  })();
    376 
    377  (function testInsertAfterLastRow() {
    378    selection.removeAllRanges();
    379    editor.innerHTML =
    380      "<table>" +
    381        "<tr><td>cell1-1</td><td>cell1-2</td></tr>" +
    382        '<tr><td id="select">cell2-1</td><td>cell2-2</td></tr>' +
    383      "</table>";
    384    editor.focus();
    385    beforeInputEvents = [];
    386    inputEvents = [];
    387    selection.collapse(document.getElementById("select").firstChild, 0);
    388    getTableEditor().insertTableRow(1, true);
    389    is(
    390      editor.innerHTML,
    391      "<table><tbody>" +
    392        "<tr><td>cell1-1</td><td>cell1-2</td></tr>" +
    393        '<tr><td id="select">cell2-1</td><td>cell2-2</td></tr>' +
    394        '<tr><td valign="top"><br></td><td valign="top"><br></td></tr>' +
    395      "</tbody></table>",
    396      "testInsertAfterLastRow: nsITableEditor.insertTableRow(1, true) should insert a row after the last row"
    397    );
    398    is(
    399      beforeInputEvents.length,
    400      1,
    401      'testInsertAfterLastRow: Only one "beforeinput" event should be fired'
    402    );
    403    checkInputEvent(
    404      beforeInputEvents[0],
    405      "when selection is collapsed in a cell whose row follows a text node (testInsertAfterLastRow)"
    406    );
    407    is(
    408      inputEvents.length,
    409      1,
    410      'testInsertAfterLastRow: Only one "input" event should be fired'
    411    );
    412    checkInputEvent(
    413      inputEvents[0],
    414      "when selection is collapsed in a cell whose row follows a text node (testInsertAfterLastRow)"
    415    );
    416  })();
    417 
    418  editor.removeEventListener("beforeinput", onBeforeInput);
    419  editor.removeEventListener("input", onInput);
    420 
    421  SimpleTest.finish();
    422 });
    423 
    424 function getTableEditor() {
    425  var editingSession = SpecialPowers.wrap(window).docShell.editingSession;
    426  return editingSession.getEditorForWindow(window).QueryInterface(SpecialPowers.Ci.nsITableEditor);
    427 }
    428 
    429 </script>
    430 </body>
    431 
    432 </html>