tor-browser

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

test_nsIHTMLEditor_insertElementAtSelection.html (6824B)


      1 <!doctype html>
      2 <html>
      3 <head>
      4 <meta charset="utf-8">
      5 <title>Testing `nsIHTMLEditor.insertElementAtSelection()`</title>
      6 <script src="/tests/SimpleTest/SimpleTest.js"></script>
      7 <link rel="stylesheet" href="/tests/SimpleTest/test.css">
      8 </head>
      9 <body>
     10 <script>
     11 SimpleTest.waitForExplicitFinish();
     12 SimpleTest.waitForFocus(runTests);
     13 
     14 function getRangeDescription(range) {
     15  function getNodeDescription(node) {
     16    if (!node) {
     17      return "null";
     18    }
     19    switch (node.nodeType) {
     20      case Node.TEXT_NODE:
     21      case Node.COMMENT_NODE:
     22      case Node.CDATA_SECTION_NODE:
     23        return `${node.nodeName} "${node.data}"`;
     24      case Node.ELEMENT_NODE:
     25        return `<${node.nodeName.toLowerCase()}${
     26          node.hasAttribute("id")
     27            ? ` id="${node.getAttribute("id")}"`
     28            : ""
     29          }${
     30          node.hasAttribute("class")
     31            ? ` class="${node.getAttribute("class")}"`
     32            : ""
     33          }${
     34          node.hasAttribute("contenteditable")
     35            ? ` contenteditable="${node.getAttribute("contenteditable")}"`
     36            : ""
     37        }>`;
     38      default:
     39        return `${node.nodeName}`;
     40    }
     41  }
     42  if (range === null) {
     43    return "null";
     44  }
     45  if (range === undefined) {
     46    return "undefined";
     47  }
     48  return range.startContainer == range.endContainer &&
     49    range.startOffset == range.endOffset
     50    ? `(${getNodeDescription(range.startContainer)}, ${range.startOffset})`
     51    : `(${getNodeDescription(range.startContainer)}, ${
     52        range.startOffset
     53      }) - (${getNodeDescription(range.endContainer)}, ${range.endOffset})`;
     54 }
     55 
     56 function doTest(aEditingHost, aHTMLEditor, aDeleteSelection) {
     57  const description = `aDeleteSelection=${aDeleteSelection}:`;
     58  (() => {
     59    aEditingHost.innerHTML = "abc";
     60    aEditingHost.focus();
     61    getSelection().collapse(aEditingHost.firstChild, 0);
     62    const p = document.createElement("p");
     63    p.appendChild(document.createElement("br"));
     64    aHTMLEditor.insertElementAtSelection(p, aDeleteSelection);
     65    is(
     66      aEditingHost.innerHTML,
     67      "<p><br></p>abc",
     68      `${description} The <p> element should be inserted before the text node when selection is collapsed at start of the text node`
     69    );
     70    is(
     71      getRangeDescription(getSelection().getRangeAt(0)),
     72      '(<div contenteditable="">, 1)',
     73      `${description} The selection should be collapsed after the inserted <p> element`
     74    );
     75  })();
     76  (() => {
     77    aEditingHost.innerHTML = "abc";
     78    aEditingHost.focus();
     79    getSelection().collapse(aEditingHost.firstChild, 1);
     80    const p = document.createElement("p");
     81    p.appendChild(document.createElement("br"));
     82    aHTMLEditor.insertElementAtSelection(p, aDeleteSelection);
     83    is(
     84      aEditingHost.innerHTML,
     85      "a<p><br></p>bc",
     86      `${description} The <p> element should be inserted middle of the text node when selection is collapsed at middle of the text node`
     87    );
     88    is(
     89      getRangeDescription(getSelection().getRangeAt(0)),
     90      '(<div contenteditable="">, 2)',
     91      `${description} The selection should be collapsed after the inserted <p> element (i.e., at right text node)`
     92    );
     93  })();
     94  (() => {
     95    aEditingHost.innerHTML = "abc";
     96    aEditingHost.focus();
     97    getSelection().collapse(aEditingHost.firstChild, 3);
     98    const p = document.createElement("p");
     99    p.appendChild(document.createElement("br"));
    100    aHTMLEditor.insertElementAtSelection(p, aDeleteSelection);
    101    is(
    102      aEditingHost.innerHTML,
    103      "abc<p><br></p>",
    104      `${description} The <p> element should be inserted after the text node when selection is collapsed at end of the text node`
    105    );
    106    is(
    107      getRangeDescription(getSelection().getRangeAt(0)),
    108      '(<div contenteditable="">, 2)',
    109      `${description} The selection should be collapsed at end of the editing host`
    110    );
    111  })();
    112  (() => {
    113    aEditingHost.innerHTML = "abc";
    114    aEditingHost.focus();
    115    getSelection().setBaseAndExtent(aEditingHost.firstChild, 0, aEditingHost.firstChild, 1);
    116    const p = document.createElement("p");
    117    p.appendChild(document.createElement("br"));
    118    aHTMLEditor.insertElementAtSelection(p, aDeleteSelection);
    119    is(
    120      aEditingHost.innerHTML,
    121      aDeleteSelection ? "<p><br></p>bc" : "a<p><br></p>bc",
    122      `${description} The <p> element should be inserted after selected character when selection selects the first character of the text node`
    123    );
    124    is(
    125      getRangeDescription(getSelection().getRangeAt(0)),
    126      `(<div contenteditable="">, ${aDeleteSelection ? "1" : "2"})`,
    127      `${description} The selection should be collapsed after the inserted <p> element (when selection selected the first character)`
    128    );
    129  })();
    130  (() => {
    131    aEditingHost.innerHTML = "abc";
    132    aEditingHost.focus();
    133    getSelection().setBaseAndExtent(aEditingHost.firstChild, 1, aEditingHost.firstChild, 2);
    134    const p = document.createElement("p");
    135    p.appendChild(document.createElement("br"));
    136    aHTMLEditor.insertElementAtSelection(p, aDeleteSelection);
    137    is(
    138      aEditingHost.innerHTML,
    139      aDeleteSelection ? "a<p><br></p>c" : "ab<p><br></p>c",
    140      `${description} The <p> element should be inserted after selected character when selection selects a middle character of the text node`
    141    );
    142    is(
    143      getRangeDescription(getSelection().getRangeAt(0)),
    144      '(<div contenteditable="">, 2)',
    145      `${description} The selection should be collapsed after the inserted <p> element (i.e., at right text node, when selection selected the middle character)`
    146    );
    147  })();
    148  (() => {
    149    aEditingHost.innerHTML = "abc";
    150    aEditingHost.focus();
    151    getSelection().setBaseAndExtent(aEditingHost.firstChild, 2, aEditingHost.firstChild, 3);
    152    const p = document.createElement("p");
    153    p.appendChild(document.createElement("br"));
    154    aHTMLEditor.insertElementAtSelection(p, aDeleteSelection);
    155    is(
    156      aEditingHost.innerHTML,
    157      aDeleteSelection ? "ab<p><br></p>" : "abc<p><br></p>",
    158      `${description} The <p> element should be inserted after selected character when selection selects the last character of the text node`
    159    );
    160    is(
    161      getRangeDescription(getSelection().getRangeAt(0)),
    162      '(<div contenteditable="">, 2)',
    163      `${description} The selection should be collapsed at end of the editing host (when selection selected the last character)`
    164    );
    165  })();
    166 }
    167 
    168 async function runTests() {
    169  const editingHost = document.createElement("div");
    170  editingHost.setAttribute("contenteditable", "");
    171  document.body.appendChild(editingHost);
    172  const editor =
    173    SpecialPowers.
    174      wrap(window).
    175      docShell.
    176      editingSession.
    177      getEditorForWindow(window).
    178      QueryInterface(SpecialPowers.Ci.nsIHTMLEditor);
    179  doTest(editingHost, editor, true);
    180  doTest(editingHost, editor, false);
    181  SimpleTest.finish();
    182 }
    183 </script>
    184 </body>
    185 </html>