tor-browser

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

paste.https.html (10112B)


      1 <!doctype html>
      2 <html>
      3 <head>
      4 <meta charset="utf-8">
      5 <meta name="timeout" content="long">
      6 <meta name="variant" content="?white-space=normal">
      7 <meta name="variant" content="?white-space=pre">
      8 <meta name="variant" content="?white-space=pre-line">
      9 <meta name="variant" content="?white-space=pre-wrap">
     10 <title>Pasting rich text into contenteditable=plaintext-only</title>
     11 <script src="/resources/testharness.js"></script>
     12 <script src="/resources/testharnessreport.js"></script>
     13 <script src="/resources/testdriver.js"></script>
     14 <script src="/resources/testdriver-vendor.js"></script>
     15 <script src="/resources/testdriver-actions.js"></script>
     16 <script src="../include/editor-test-utils.js"></script>
     17 <script>
     18 "use strict";
     19 
     20 const searchParams = new URLSearchParams(document.location.search);
     21 const whiteSpace = searchParams.get("white-space");
     22 const useBR = whiteSpace == "normal";
     23 
     24 addEventListener("load", () => {
     25  const placeholderForCopy = document.createElement("div");
     26  document.body.appendChild(placeholderForCopy);
     27  const editingHost = document.createElement("div");
     28  editingHost.style.whiteSpace = whiteSpace;
     29  editingHost.setAttribute("contenteditable", "plaintext-only");
     30  document.body.appendChild(editingHost);
     31  editingHost.focus();
     32  editingHost.getBoundingClientRect();
     33  const utils = new EditorTestUtils(editingHost);
     34  let lastBeforeInput;
     35  editingHost.addEventListener("beforeinput", event => lastBeforeInput = event);
     36 
     37  /**
     38   * Pasting HTML into contenteditable=plaintext-only should work as pasting
     39   * text which is serialized by the browser or OS.  Then, `beforeinput` event
     40   * should have only dataTransfer and it should have "text/html" format to
     41   * make it possible that web apps can serialize the data by themselves to
     42   * avoid the browser/OS dependency.  Finally, if white-space style is normal,
     43   * line breaks should appear as <br>.  Otherwise, either <br> or \n is fine
     44   * because both breaks the lines.
     45   */
     46 
     47  promise_test(async t => {
     48    placeholderForCopy.innerHTML = "<b>abc</b>";
     49    document.activeElement?.blur();
     50    await test_driver.click(placeholderForCopy);
     51    getSelection().selectAllChildren(placeholderForCopy);
     52    await utils.sendCopyShortcutKey();
     53    utils.setupEditingHost("A[]B");
     54    lastBeforeInput = undefined;
     55    await utils.sendPasteShortcutKey();
     56    test(() => {
     57      assert_equals(lastBeforeInput?.inputType, "insertFromPaste", `inputType should be "insertFromPaste"`);
     58      assert_equals(lastBeforeInput?.data, null, `data should be null`);
     59      assert_true(
     60        String(lastBeforeInput?.dataTransfer?.getData("text/html")).includes(placeholderForCopy.innerHTML),
     61        `dataTransfer should have the copied HTML source`
     62      );
     63    }, `${t.name}: beforeinput`);
     64    test(() => {
     65      assert_equals(editingHost.innerHTML, "AabcB", "<b> should not be pasted");
     66    }, `${t.name}: pasted result`);
     67  }, "Pasting text in <b>");
     68 
     69  promise_test(async t => {
     70    placeholderForCopy.innerHTML = "<span>abc</span>";
     71    document.activeElement?.blur();
     72    await test_driver.click(placeholderForCopy);
     73    getSelection().selectAllChildren(placeholderForCopy);
     74    await utils.sendCopyShortcutKey();
     75    utils.setupEditingHost("A[]B");
     76    lastBeforeInput = undefined;
     77    await utils.sendPasteShortcutKey();
     78    test(() => {
     79      assert_equals(lastBeforeInput?.inputType, "insertFromPaste", `inputType should be "insertFromPaste"`);
     80      assert_equals(lastBeforeInput?.data, null, `data should be null`);
     81      assert_true(
     82        String(lastBeforeInput?.dataTransfer?.getData("text/html")).includes(placeholderForCopy.innerHTML),
     83        `dataTransfer should have the copied HTML source`
     84      );
     85    }, `${t.name}: beforeinput`);
     86    test(() => {
     87      assert_equals(editingHost.innerHTML, "AabcB", "<span> should not be pasted");
     88    }, `${t.name}: pasted result`);
     89  }, "Pasting text in <span>");
     90 
     91  promise_test(async t => {
     92    placeholderForCopy.innerHTML = "abc";
     93    document.activeElement?.blur();
     94    await test_driver.click(placeholderForCopy);
     95    getSelection().selectAllChildren(placeholderForCopy);
     96    await utils.sendCopyShortcutKey();
     97    utils.setupEditingHost("<b>A[]B</b>");
     98    lastBeforeInput = undefined;
     99    await utils.sendPasteShortcutKey();
    100    test(() => {
    101      assert_equals(lastBeforeInput?.inputType, "insertFromPaste", `inputType should be "insertFromPaste"`);
    102      assert_equals(lastBeforeInput?.data, null, `data should be null`);
    103      assert_true(
    104        String(lastBeforeInput?.dataTransfer?.getData("text/html")).includes(placeholderForCopy.innerHTML),
    105        `dataTransfer should have the copied HTML source`
    106      );
    107    }, `${t.name}: beforeinput`);
    108    test(() => {
    109      assert_equals(editingHost.innerHTML, "<b>AabcB</b>", "text should be inserted into the editable <b>");
    110    }, `${t.name}: pasted result`);
    111  }, "Pasting text into editable <b>");
    112 
    113  promise_test(async t => {
    114    placeholderForCopy.innerHTML = "<i>abc</i>";
    115    document.activeElement?.blur();
    116    await test_driver.click(placeholderForCopy);
    117    getSelection().selectAllChildren(placeholderForCopy);
    118    await utils.sendCopyShortcutKey();
    119    utils.setupEditingHost("<b>A[]B</b>");
    120    lastBeforeInput = undefined;
    121    await utils.sendPasteShortcutKey();
    122    test(() => {
    123      assert_equals(lastBeforeInput?.inputType, "insertFromPaste", `inputType should be "insertFromPaste"`);
    124      assert_equals(lastBeforeInput?.data, null, `data should be null`);
    125      assert_true(
    126        String(lastBeforeInput?.dataTransfer?.getData("text/html")).includes(placeholderForCopy.innerHTML),
    127        `dataTransfer should have the copied HTML source`
    128      );
    129    }, `${t.name}: beforeinput`);
    130    test(() => {
    131      assert_equals(editingHost.innerHTML, "<b>AabcB</b>", "text should be inserted into the editable <b> without copied <i>");
    132    }, `${t.name}: pasted result`);
    133  }, "Pasting text in <i> into editable <b>");
    134 
    135  promise_test(async t => {
    136    placeholderForCopy.innerHTML = "<div>abc</div><div>def</div>";
    137    document.activeElement?.blur();
    138    await test_driver.click(placeholderForCopy);
    139    getSelection().selectAllChildren(placeholderForCopy);
    140    await utils.sendCopyShortcutKey();
    141    utils.setupEditingHost("A[]B");
    142    lastBeforeInput = undefined;
    143    await utils.sendPasteShortcutKey();
    144    test(() => {
    145      assert_equals(lastBeforeInput?.inputType, "insertFromPaste", `inputType should be "insertFromPaste"`);
    146      assert_equals(lastBeforeInput?.data, null, `data should be null`);
    147      assert_true(
    148        String(lastBeforeInput?.dataTransfer?.getData("text/html")).includes(placeholderForCopy.innerHTML),
    149        `dataTransfer should have the copied HTML source`
    150      );
    151    }, `${t.name}: beforeinput`);
    152    test(() => {
    153      if (useBR) {
    154        assert_in_array(
    155          editingHost.innerHTML,
    156          [
    157            "Aabc<br>defB",
    158            "A<br>abc<br>def<br>B",
    159          ],
    160          "Each paragraph should be pasted as a line"
    161        );
    162      } else {
    163        assert_in_array(
    164          editingHost.innerHTML,
    165          [
    166            "Aabc\ndefB",
    167            "A\nabc\ndef\nB",
    168          ],
    169          "Each paragraph should be pasted as a line"
    170        );
    171      }
    172    }, `${t.name}: pasted result`);
    173  }, "Pasting 2 paragraphs");
    174 
    175  promise_test(async t => {
    176    placeholderForCopy.innerHTML = "<div>abc</div><div>def</div>";
    177    document.activeElement?.blur();
    178    await test_driver.click(placeholderForCopy);
    179    getSelection().selectAllChildren(placeholderForCopy);
    180    await utils.sendCopyShortcutKey();
    181    utils.setupEditingHost("<b>A[]B</b>");
    182    lastBeforeInput = undefined;
    183    await utils.sendPasteShortcutKey();
    184    test(() => {
    185      assert_equals(lastBeforeInput?.inputType, "insertFromPaste", `inputType should be "insertFromPaste"`);
    186      assert_equals(lastBeforeInput?.data, null, `data should be null`);
    187      assert_true(
    188        String(lastBeforeInput?.dataTransfer?.getData("text/html")).includes(placeholderForCopy.innerHTML),
    189        `dataTransfer should have the copied HTML source`
    190      );
    191    }, `${t.name}: beforeinput`);
    192    test(() => {
    193      if (useBR) {
    194        assert_in_array(
    195          editingHost.innerHTML,
    196          [
    197            "<b>Aabc<br>defB</b>",
    198            "<b>A<br>abc<br>def<br>B</b>",
    199          ],
    200          "Each paragraph should be pasted as a line"
    201        );
    202      } else {
    203        assert_in_array(
    204          editingHost.innerHTML,
    205          [
    206            "<b>Aabc\ndefB</b>",
    207            "<b>A\nabc\ndef\nB</b>",
    208          ],
    209          "Each paragraph should be pasted as a line"
    210        );
    211      }
    212    }, `${t.name}: pasted result`);
    213  }, "Pasting 2 paragraphs into <b>");
    214 
    215  promise_test(async t => {
    216    placeholderForCopy.innerHTML = "<div><b>abc</b></div><div><b>def</b></div>";
    217    document.activeElement?.blur();
    218    await test_driver.click(placeholderForCopy);
    219    getSelection().selectAllChildren(placeholderForCopy);
    220    await utils.sendCopyShortcutKey();
    221    utils.setupEditingHost("A[]B");
    222    lastBeforeInput = undefined;
    223    await utils.sendPasteShortcutKey();
    224    test(() => {
    225      assert_equals(lastBeforeInput?.inputType, "insertFromPaste", `inputType should be "insertFromPaste"`);
    226      assert_equals(lastBeforeInput?.data, null, `data should be null`);
    227      assert_true(
    228        String(lastBeforeInput?.dataTransfer?.getData("text/html")).includes(placeholderForCopy.innerHTML),
    229        `dataTransfer should have the copied HTML source`
    230      );
    231    }, `${t.name}: beforeinput`);
    232    test(() => {
    233      if (useBR) {
    234        assert_in_array(
    235          editingHost.innerHTML,
    236          [
    237            "Aabc<br>defB",
    238            "A<br>abc<br>def<br>B",
    239          ],
    240          "Each paragraph should be pasted as a line"
    241        );
    242      } else {
    243        assert_in_array(
    244          editingHost.innerHTML,
    245          [
    246            "Aabc\ndefB",
    247            "A\nabc\ndef\nB",
    248          ],
    249          "Each paragraph should be pasted as a line"
    250        );
    251      }
    252    }, `${t.name}: pasted result`);
    253  }, "Pasting 2 paragraphs whose text is bold");
    254 }, {once: true});
    255 </script>
    256 </head>
    257 <body></body>
    258 </html>