tor-browser

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

test_nsIEditor_insertNode.html (6852B)


      1 <!doctype>
      2 <html>
      3 <head>
      4 <meta charset="utf-8">
      5 <title>nsIEditor.insertNode</title>
      6 <script src="/tests/SimpleTest/SimpleTest.js"></script>
      7 <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
      8 <script>
      9 "use strict";
     10 
     11 function stringifyInputEvent(aEvent) {
     12  if (!aEvent) {
     13    return "null";
     14  }
     15  return `${aEvent.type}: { inputType=${aEvent.inputType} }`;
     16 }
     17 
     18 function getRangeDescription(range) {
     19  function getNodeDescription(node) {
     20    if (!node) {
     21      return "null";
     22    }
     23    switch (node.nodeType) {
     24      case Node.TEXT_NODE:
     25        return `${node.nodeName} "${node.data}"`;
     26      case Node.ELEMENT_NODE:
     27        return `<${node.nodeName.toLowerCase()}>`;
     28      default:
     29        return `${node.nodeName}`;
     30    }
     31  }
     32  if (range === null) {
     33    return "null";
     34  }
     35  if (range === undefined) {
     36    return "undefined";
     37  }
     38  return range.startContainer == range.endContainer &&
     39    range.startOffset == range.endOffset
     40    ? `(${getNodeDescription(range.startContainer)}, ${range.startOffset})`
     41    : `(${getNodeDescription(range.startContainer)}, ${
     42        range.startOffset
     43      }) - (${getNodeDescription(range.endContainer)}, ${range.endOffset})`;
     44 }
     45 
     46 SimpleTest.waitForExplicitFinish();
     47 SimpleTest.waitForFocus(() => {
     48  const editingHost = document.querySelector("div[contenteditable]");
     49  const editor =
     50    SpecialPowers.wrap(window).docShell.editingSession.getEditorForWindow(window);
     51 
     52  editingHost.focus();
     53 
     54  let events = [];
     55  editingHost.addEventListener("input", event => events.push(event));
     56 
     57  (function test_insert_text_to_start() {
     58    editor.insertNode(document.createTextNode("abc"), editingHost, 0);
     59    is(
     60      editingHost.innerHTML,
     61      "abc<br>",
     62      "test_insert_text_to_start: insertNode() should insert new text node at start of the container"
     63    );
     64    is(
     65      events.length,
     66      1,
     67      "test_insert_text_to_start: Only one input event should be fired when insertNode() inserts a text node"
     68    );
     69    is(
     70      stringifyInputEvent(events[0]),
     71      stringifyInputEvent({ type: "input", inputType: "" }),
     72      "test_insert_text_to_start: input event should be fired when inserting a node"
     73    );
     74    is(
     75      getRangeDescription(getSelection().getRangeAt(0)),
     76      getRangeDescription({
     77        startContainer: editingHost,
     78        startOffset: 1,
     79        endContainer: editingHost,
     80        endOffset: 1,
     81      }),
     82      "test_insert_text_to_start: insertNode() should collapse selection after the inserted text node"
     83    );
     84  })();
     85 
     86  (function test_insert_span_to_big_index() {
     87    events = [];
     88    editingHost.innerHTML = "abc";
     89    const span = document.createElement("span");
     90    span.textContent = "def";
     91    editor.insertNode(span, editingHost, 1000);
     92    is(
     93      editingHost.innerHTML,
     94      "abc<span>def</span>",
     95      "test_insert_span_to_big_index: insertNode() with big index should insert new node at end of the container"
     96    );
     97    is(
     98      events.length,
     99      1,
    100      "test_insert_span_to_big_index: Only one input event should be fired when insertNode() inserts a node"
    101    );
    102    is(
    103      stringifyInputEvent(events[0]),
    104      stringifyInputEvent({ type: "input", inputType: "" }),
    105      "test_insert_span_to_big_index: input event should be fired when inserting a node"
    106    );
    107    is(
    108      getRangeDescription(getSelection().getRangeAt(0)),
    109      getRangeDescription({
    110        startContainer: editingHost,
    111        startOffset: 2,
    112        endContainer: editingHost,
    113        endOffset: 2,
    114      }),
    115      "test_insert_span_to_big_index: insertNode() should collapse selection after the inserted node"
    116    );
    117  })();
    118 
    119  (function test_preserve_selection() {
    120    events = [];
    121    editingHost.innerHTML = "abc";
    122    const span = document.createElement("span");
    123    span.textContent = "def";
    124    getSelection().collapse(editingHost, 0);
    125    editor.insertNode(span, editingHost, 1, true);
    126    is(
    127      editingHost.innerHTML,
    128      "abc<span>def</span>",
    129      "test_preserve_selection: insertNode() should insert new node at end of the container"
    130    );
    131    is(
    132      events.length,
    133      1,
    134      "test_preserve_selection: Only one input event should be fired when insertNode() inserts a node"
    135    );
    136    is(
    137      stringifyInputEvent(events[0]),
    138      stringifyInputEvent({ type: "input", inputType: "" }),
    139      "test_preserve_selection: input event should be fired when inserting a node"
    140    );
    141    is(
    142      getRangeDescription(getSelection().getRangeAt(0)),
    143      getRangeDescription({
    144        startContainer: editingHost,
    145        startOffset: 0,
    146        endContainer: editingHost,
    147        endOffset: 0,
    148      }),
    149      "test_preserve_selection: insertNode() should not collapse selection after the inserted node"
    150    );
    151  })();
    152 
    153  (function test_not_preserve_selection_nested_by_beforeinput() {
    154    editingHost.innerHTML = "abc";
    155    const span1 = document.createElement("span");
    156    span1.textContent = "def";
    157    const span2 = document.createElement("span");
    158    span2.textContent = "ghi";
    159    getSelection().collapse(editingHost, 0);
    160    editingHost.addEventListener("beforeinput", () => {
    161      editor.insertNode(span1, editingHost, 1);
    162    }, {once: true});
    163    editor.insertNode(span2, editingHost, 2, true);
    164    is(
    165      editingHost.innerHTML,
    166      "abc<span>def</span><span>ghi</span>",
    167      "test_not_preserve_selection_nested_by_beforeinput: both insertNode() should work"
    168    );
    169    is(
    170      getRangeDescription(getSelection().getRangeAt(0)),
    171      getRangeDescription({
    172        startContainer: editingHost,
    173        startOffset: 2,
    174        endContainer: editingHost,
    175        endOffset: 2,
    176      }),
    177      "test_not_preserve_selection_nested_by_beforeinput: only insertNode() called in beforeinput listener should update selection"
    178    );
    179  })();
    180 
    181  (function test_not_preserve_selection_nested_by_input() {
    182    editingHost.innerHTML = "abc";
    183    const span1 = document.createElement("span");
    184    span1.textContent = "def";
    185    const span2 = document.createElement("span");
    186    span2.textContent = "ghi";
    187    getSelection().collapse(editingHost, 0);
    188    editingHost.addEventListener("input", () => {
    189      editor.insertNode(span2, editingHost, 2);
    190    }, {once: true});
    191    editor.insertNode(span1, editingHost, 1, true);
    192    is(
    193      editingHost.innerHTML,
    194      "abc<span>def</span><span>ghi</span>",
    195      "test_not_preserve_selection_nested_by_input: both insertNode() should work"
    196    );
    197    is(
    198      getRangeDescription(getSelection().getRangeAt(0)),
    199      getRangeDescription({
    200        startContainer: editingHost,
    201        startOffset: 3,
    202        endContainer: editingHost,
    203        endOffset: 3,
    204      }),
    205      "test_not_preserve_selection_nested_by_input: only insertNode() called in input listener should update selection"
    206    );
    207  })();
    208 
    209  SimpleTest.finish();
    210 });
    211 </script>
    212 </head>
    213 <body><div contenteditable><br></div></body>
    214 </html>