tor-browser

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

join-pre-and-other-block.html (10391B)


      1 <!doctype html>
      2 <html>
      3 <head>
      4 <meta charset="utf-8">
      5 <meta name="variant" content="?method=backspace&block=div">
      6 <meta name="variant" content="?method=backspace&block=p">
      7 <meta name="variant" content="?method=backspace&block=blockquote">
      8 <meta name="variant" content="?method=forwarddelete&block=div">
      9 <meta name="variant" content="?method=forwarddelete&block=p">
     10 <meta name="variant" content="?method=forwarddelete&block=blockquote">
     11 <meta name="variant" content="?method=select-boundary&block=div">
     12 <meta name="variant" content="?method=select-boundary&block=p">
     13 <meta name="variant" content="?method=select-boundary&block=blockquote">
     14 <title>Tests for joining pre and other block element</title>
     15 <script src="/resources/testharness.js"></script>
     16 <script src="/resources/testharnessreport.js"></script>
     17 <script src="/resources/testdriver.js"></script>
     18 <script src="/resources/testdriver-vendor.js"></script>
     19 <script src="/resources/testdriver-actions.js"></script>
     20 <script src="../include/editor-test-utils.js"></script>
     21 </head>
     22 <body>
     23 <div contenteditable></div>
     24 <script>
     25 "use strict";
     26 
     27 const searchParams = new URLSearchParams(document.location.search);
     28 const testingBackspace = searchParams.get("method") == "backspace";
     29 const testingSelectBoundary = searchParams.get("method") == "select-boundary";
     30 const commandName =
     31  testingBackspace || testingSelectBoundary ? "delete" : "forwarddelete";
     32 const editingHost = document.querySelector("div[contenteditable]");
     33 const caretInLeft = (() => {
     34  if (testingSelectBoundary) {
     35    return "[";
     36  }
     37  return testingBackspace ? "" : "[]";
     38 })();
     39 const caretInRight = (() => {
     40  if (testingSelectBoundary) {
     41    return "]";
     42  }
     43  return testingBackspace ? "[]" : "";
     44 })();
     45 const tag = searchParams.get("block");
     46 
     47 // These expectations are odd because they don't preserve white-space style
     48 // coming from another element.  However, this is traditional behavior so that
     49 // browsers should not change the behavior.
     50 const tests = [
     51  {
     52    initialHTML:
     53      `<pre>abc${caretInLeft}</pre>` +
     54        `<${tag}>${caretInRight}def</${tag}>`,
     55    expectedHTML: [
     56      "<pre>abcdef</pre>",
     57    ],
     58  },
     59  {
     60    initialHTML:
     61      `<${tag}>abc${caretInLeft}</${tag}>` +
     62        `<pre>${caretInRight}def</pre>`,
     63    expectedHTML: [
     64      `<${tag}>abcdef</${tag}>`,
     65    ],
     66    expectedHTMLWithStyledPre: [
     67      `<${tag}>abc<span style="white-space:pre">def</span></${tag}>`,
     68    ],
     69  },
     70  {
     71    initialHTML:
     72      `<pre>abc${caretInLeft}</pre>` +
     73        `<${tag}>${caretInRight}def<br>ghi</${tag}>`,
     74    expectedHTML: [
     75      `<pre>abcdef</pre>` +
     76        `<${tag}>ghi</${tag}>`,
     77    ],
     78  },
     79  {
     80    initialHTML:
     81      `<pre>abc${caretInLeft}</pre>` +
     82        `<${tag}>${caretInRight}def<div>ghi</div></${tag}>`,
     83    expectedHTML: [
     84      "<pre>abcdef</pre>" +
     85        `<${tag}><div>ghi</div></${tag}>`,
     86    ],
     87    skip: tag == "p",
     88  },
     89  {
     90    initialHTML:
     91      `<${tag}>abc${caretInLeft}</${tag}>` +
     92        `<pre>${caretInRight}def\nghi</pre>`,
     93    expectedHTML: [
     94      `<${tag}>abcdef</${tag}>` +
     95        "<pre>ghi</pre>",
     96    ],
     97    expectedHTMLWithStyledPre: [
     98      `<${tag}>abc<span style="white-space:pre">def</span></${tag}>` +
     99        "<pre>ghi</pre>",
    100    ],
    101  },
    102  {
    103    initialHTML:
    104      `<${tag}>abc${caretInLeft}</${tag}>` +
    105        `<pre>${caretInRight}def<br>ghi</pre>`,
    106    expectedHTML: [
    107      `<${tag}>abcdef</${tag}>` +
    108        "<pre>ghi</pre>",
    109    ],
    110    expectedHTMLWithStyledPre: [
    111      `<${tag}>abc<span style="white-space:pre">def</span></${tag}>` +
    112        "<pre>ghi</pre>",
    113    ],
    114  },
    115  {
    116    initialHTML:
    117      `<pre>abc${caretInLeft}</pre>` +
    118        `<${tag}><b>${caretInRight}def</b></${tag}>`,
    119    expectedHTML: [
    120      "<pre>abc<b>def</b></pre>",
    121    ],
    122  },
    123  {
    124    initialHTML:
    125      `<pre>abc${caretInLeft}</pre>` +
    126         `<${tag}><b>${caretInRight}def<br>ghi</b></${tag}>`,
    127    expectedHTML: [
    128      "<pre>abc<b>def</b></pre>" +
    129        `<${tag}><b>ghi</b></${tag}>`,
    130    ],
    131  },
    132  {
    133    initialHTML:
    134      `<${tag}>abc${caretInLeft}</${tag}>` +
    135        `<pre><b>${caretInRight}def\nghi</b></pre>`,
    136    expectedHTML: [
    137      `<${tag}>abc<b>def</b></${tag}>` +
    138        "<pre><b>ghi</b></pre>",
    139    ],
    140    expectedHTMLWithStyledPre: [
    141      `<${tag}>abc<b style="white-space:pre">def</b></${tag}>` +
    142        "<pre><b>ghi</b></pre>",
    143      `<${tag}>abc<span style="white-space:pre"><b>def</b></span></${tag}>` +
    144        "<pre><b>ghi</b></pre>",
    145    ],
    146  },
    147  {
    148    initialHTML:
    149      `<${tag}>abc${caretInLeft}</${tag}>` +
    150        `<pre><b>${caretInRight}def<br>ghi</b></pre>`,
    151    expectedHTML: [
    152      `<${tag}>abc<b>def</b></${tag}>` +
    153        "<pre><b>ghi</b></pre>",
    154    ],
    155    expectedHTMLWithStyledPre: [
    156      `<${tag}>abc<b style="white-space:pre">def</b></${tag}>` +
    157        "<pre><b>ghi</b></pre>",
    158      `<${tag}>abc<span style="white-space:pre"><b>def</b></span></${tag}>` +
    159        "<pre><b>ghi</b></pre>",
    160    ],
    161  },
    162  {
    163    initialHTML:
    164      `<${tag}>abc${caretInLeft}</${tag}>` +
    165        `<pre><b>${caretInRight}def</b>\nghi</pre>`,
    166    expectedHTML: [
    167      `<${tag}>abc<b>def</b></${tag}>` +
    168        "<pre>ghi</pre>",
    169    ],
    170    expectedHTMLWithStyledPre: [
    171      `<${tag}>abc<b style="white-space:pre">def</b></${tag}>` +
    172        "<pre>ghi</pre>",
    173      `<${tag}>abc<span style="white-space:pre"><b>def</b></span></${tag}>` +
    174        "<pre>ghi</pre>",
    175    ],
    176  },
    177  {
    178    initialHTML:
    179      `<${tag}>abc${caretInLeft}</${tag}>` +
    180        `<pre><b>${caretInRight}def</b><br>ghi</pre>`,
    181    expectedHTML: [
    182      `<${tag}>abc<b>def</b></${tag}>` +
    183        "<pre>ghi</pre>",
    184    ],
    185    expectedHTMLWithStyledPre: [
    186      `<${tag}>abc<b style="white-space:pre">def</b></${tag}>` +
    187        "<pre>ghi</pre>",
    188      `<${tag}>abc<span style="white-space:pre"><b>def</b></span></${tag}>` +
    189        "<pre>ghi</pre>",
    190    ],
    191  },
    192  {
    193    initialHTML:
    194      `<${tag}>abc${caretInLeft}</${tag}>` +
    195        `<pre><b>${caretInRight}def\n</b>ghi</pre>`,
    196    expectedHTML: [
    197      `<${tag}>abc<b>def</b></${tag}>` +
    198        "<pre>ghi</pre>",
    199    ],
    200    expectedHTMLWithStyledPre: [
    201      `<${tag}>abc<b style="white-space:pre">def</b></${tag}>` +
    202        `<pre>ghi</pre>`,
    203      `<${tag}>abc<span style="white-space:pre"><b>def</b></span></${tag}>` +
    204        "<pre>ghi</pre>",
    205    ],
    206  },
    207  {
    208    initialHTML:
    209      `<${tag}>abc${caretInLeft}</${tag}>` +
    210        `<pre><b>${caretInRight}def<br></b>ghi</pre>`,
    211    expectedHTML: [
    212      `<${tag}>abc<b>def</b></${tag}>` +
    213        "<pre>ghi</pre>",
    214    ],
    215    expectedHTMLWithStyledPre: [
    216      `<${tag}>abc<b style="white-space:pre">def</b></${tag}>` +
    217        "<pre>ghi</pre>",
    218      `<${tag}>abc<span style="white-space:pre"><b>def</b></span></${tag}>` +
    219        "<pre>ghi</pre>",
    220    ],
    221  },
    222  // One linefeed at start of <pre> should be ignored.
    223  // Note that if setupEditingHost() does not touch the text node in <pre>,
    224  // the leading line break is ignored, but if it touches the text node,
    225  // the value is set to as-is.  Therefore, the following tests can work
    226  // with empty caretInRight value.
    227  {
    228    initialHTML:
    229      `<${tag}>abc${caretInLeft}</${tag}>` +
    230        `<pre>\ndef\nghi</pre>`,
    231    expectedHTML: [
    232      `<${tag}>abcdef</${tag}>` +
    233        `<pre>ghi</pre>`,
    234    ],
    235    expectedHTMLWithStyledPre: [
    236      `<${tag}>abc<span style="white-space:pre">def</span></${tag}>` +
    237        "<pre>ghi</pre>",
    238    ],
    239    skip: caretInRight !== "",
    240  },
    241  // When there are two line breaks at start of <pre>, the first one should be
    242  // ignored by the parser but the second one should make empty first line.
    243  // Therefore, the first empty line should be removed.
    244  {
    245    initialHTML:
    246      `<${tag}>abc${caretInLeft}</${tag}>` +
    247        `<pre>\n\ndef\nghi</pre>`,
    248    expectedHTML: [
    249      `<${tag}>abc</${tag}>` +
    250        "<pre>def\nghi</pre>",
    251    ],
    252    skip: caretInRight !== "",
    253  },
    254 ];
    255 const utils = new EditorTestUtils(editingHost);
    256 
    257 const betweenBlockAndPre = new RegExp(`</${tag}><pre>`);
    258 const betweenPreAndBlock = new RegExp(`</pre><${tag}>`);
    259 function putStyleElement() {
    260  const styleElement = document.createElement("style");
    261  styleElement.textContent = "pre { white-space: pre; }";
    262  document.head.appendChild(styleElement);
    263 }
    264 
    265 for (const specifyPreStyle of [false, true]) {
    266  for (const t of tests) {
    267    if (t.skip) {
    268      continue;
    269    }
    270    if (specifyPreStyle && !t.expectedHTMLWithStyledPre) {
    271      continue;
    272    }
    273    promise_test(async () => {
    274      if (specifyPreStyle) {
    275        putStyleElement();
    276      }
    277      try {
    278        utils.setupEditingHost(t.initialHTML);
    279        await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey());
    280        utils.normalizeStyleAttributeValues();
    281        assert_in_array(
    282          editingHost.innerHTML,
    283          specifyPreStyle ? t.expectedHTMLWithStyledPre : t.expectedHTML,
    284          `white-space should${
    285            !specifyPreStyle ? " not" : ""
    286          } be preserved by <span> elements`
    287        );
    288      } finally {
    289        if (specifyPreStyle) {
    290          document.querySelector("style")?.remove();
    291        }
    292      }
    293    }, `${commandName} at ${t.initialHTML.replace(/\n/g, "\\n")}${
    294      specifyPreStyle ? " (with <style>pre { white-space: pre; }</style>)" : ""
    295    }`);
    296 
    297    // Repeat same tests with inserting a line break between the paragraphs.
    298    const initialHTMLWithLineBreak =
    299      t.initialHTML
    300        .replace(betweenBlockAndPre, `</${tag}>\n<pre>`)
    301        .replace(betweenPreAndBlock, `</pre>\n<${tag}>`);
    302    promise_test(async () => {
    303      if (specifyPreStyle) {
    304        putStyleElement();
    305      }
    306      try {
    307        utils.setupEditingHost(initialHTMLWithLineBreak);
    308        await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey());
    309        utils.normalizeStyleAttributeValues();
    310        assert_in_array(
    311          editingHost.innerHTML,
    312          specifyPreStyle ? t.expectedHTMLWithStyledPre : t.expectedHTML,
    313          `white-space should${
    314            !specifyPreStyle ? " not" : ""
    315          } be preserved by <span> elements (testing with a line break between paragraphs)`
    316        );
    317      } finally {
    318        if (specifyPreStyle) {
    319          document.querySelector("style")?.remove();
    320        }
    321      }
    322    }, `${commandName} at ${initialHTMLWithLineBreak.replace(/\n/g, "\\n")}${
    323      specifyPreStyle ? " (with <style>pre { white-space: pre; }</style>)" : ""
    324    }`);
    325  }
    326 }
    327 </script>
    328 </body>
    329 </html>