tor-browser

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

delete-in-child-of-head.tentative.html (17427B)


      1 <!doctype html>
      2 <html>
      3 <head>
      4 <meta chareset="utf-8">
      5 <meta name="timeout" content="long">
      6 <meta name="variant" content="?designMode=off&method=backspace">
      7 <meta name="variant" content="?designMode=off&method=forwarddelete">
      8 <meta name="variant" content="?designMode=on&method=backspace">
      9 <meta name="variant" content="?designMode=on&method=forwarddelete">
     10 <title>Join paragraphs in the head element</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 </head>
     18 <body>
     19 <iframe srcdoc=""></iframe>
     20 <script>
     21 "use strict";
     22 
     23 const searchParams = new URLSearchParams(document.location.search);
     24 const testingBackspace = searchParams.get("method") == "backspace";
     25 const commandName = testingBackspace ? "delete" : "forwarddelete";
     26 const testingDesignMode = searchParams.get("designMode") == "on";
     27 
     28 const iframe = document.querySelector("iframe");
     29 const minimumSrcDoc =
     30  "<html>" +
     31    '<head style="display:block">' +
     32      "<title>iframe</title>" +
     33      "<script src='/resources/testdriver.js'></" + "script>" +
     34      "<script src='/resources/testdriver-vendor.js'></" + "script>" +
     35      "<script src='/resources/testdriver-actions.js'></" + "script>" +
     36    "</head>" +
     37    "<body><br></body>" +
     38  "</html>";
     39 
     40 async function initializeAndWaitForLoad(iframeElement, srcDocValue) {
     41  const waitForLoad =
     42    new Promise(
     43      resolve => iframeElement.addEventListener("load", resolve, {once: true})
     44    );
     45  iframeElement.srcdoc = srcDocValue;
     46  await waitForLoad;
     47  if (testingDesignMode) {
     48    iframeElement.contentDocument.designMode = "on";
     49  } else {
     50    iframeElement.contentDocument.documentElement.setAttribute("contenteditable", "");
     51  }
     52  iframeElement.contentWindow.focus();
     53  iframeElement.contentDocument.execCommand("defaultParagraphSeparator", false, "div");
     54 }
     55 
     56 function removeResourceScriptElements(node) {
     57  node.querySelectorAll("script").forEach(
     58    element => {
     59      if (element.getAttribute("src")?.startsWith("/resources")) {
     60        element.remove()
     61      }
     62    }
     63  );
     64 }
     65 
     66 // DO NOT USE multi-line comment in this file, then, you can comment out
     67 // unnecessary tests when you need to attach the browser with a debugger.
     68 
     69 // For backward compatibility, normal block elements in <head> should be
     70 // joined by deletion.
     71 promise_test(async () => {
     72  await initializeAndWaitForLoad(iframe, minimumSrcDoc);
     73  const childDoc = iframe.contentDocument;
     74  const utils = new EditorTestUtils(childDoc.documentElement);
     75  const div1 = childDoc.createElement("div");
     76  div1.innerHTML = "abc";
     77  const div2 = childDoc.createElement("div");
     78  div2.innerHTML = "def";
     79  childDoc.head.appendChild(div1);
     80  childDoc.head.appendChild(div2);
     81  // Now: <head><title>...</title><div>abc</div><div>def</div></head>...
     82  childDoc.getSelection().collapse(
     83    testingBackspace ? div2.firstChild : div1.firstChild,
     84    testingBackspace ? 0 : div1.firstChild.length
     85  );
     86  await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey());
     87  removeResourceScriptElements(childDoc);
     88  childDoc.head.removeAttribute("style");
     89 
     90  assert_in_array(
     91    childDoc.documentElement.innerHTML,
     92    [
     93      '<head><title>iframe</title><div>abcdef</div></head><body><br></body>',
     94      '<head><title>iframe</title><div>abcdef<br></div></head><body><br></body>',
     95    ],
     96    "The <div> elements should be merged"
     97  );
     98  assert_equals(
     99    div1.isConnected ^ div2.isConnected,
    100    1,
    101    "One <div> element should be removed, and the other should stay"
    102  );
    103 }, `${commandName} in <div> elements in <head> should join them`);
    104 
    105 // The following void elements shouldn't be deleted for avoiding various
    106 // affection to the document.
    107 for (const tag of ["meta", "title", "style", "script", "link", "base", "template"]) {
    108  promise_test(async () => {
    109    await initializeAndWaitForLoad(iframe, minimumSrcDoc);
    110    const childDoc = iframe.contentDocument;
    111    const utils = new EditorTestUtils(childDoc.documentElement);
    112    const div1 = childDoc.createElement("div");
    113    div1.innerHTML = "abc";
    114    const div2 = childDoc.createElement("div");
    115    div2.innerHTML = "def";
    116    const element = childDoc.createElement(tag);
    117    childDoc.head.appendChild(div1);
    118    childDoc.head.appendChild(element);
    119    childDoc.head.appendChild(div2);
    120    // Now: <head><title>...</title><div>abc</div><tag/><div>def</div></head>...
    121    childDoc.getSelection().collapse(
    122      testingBackspace ? div2.firstChild : div1.firstChild,
    123      testingBackspace ? 0 : div1.firstChild.length
    124    );
    125    await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey());
    126    removeResourceScriptElements(childDoc);
    127    childDoc.head.removeAttribute("style");
    128 
    129    if (["title", "style", "script", "template"].includes(tag)) {
    130      assert_in_array(
    131        childDoc.documentElement.innerHTML,
    132        [
    133          `<head><title>iframe</title><div>abcdef</div><${tag}></${tag}></head><body><br></body>`,
    134          `<head><title>iframe</title><div>abcdef<br></div><${tag}></${tag}></head><body><br></body>`,
    135          `<head><title>iframe</title><${tag}></${tag}><div>abcdef</div></head><body><br></body>`,
    136          `<head><title>iframe</title><${tag}></${tag}><div>abcdef<br></div></head><body><br></body>`,
    137        ],
    138        `The <div> elements should be merged without deleting <${tag}>`
    139      );
    140    } else {
    141      assert_in_array(
    142        childDoc.documentElement.innerHTML,
    143        [
    144          `<head><title>iframe</title><div>abcdef</div><${tag}></head><body><br></body>`,
    145          `<head><title>iframe</title><div>abcdef<br></div><${tag}></head><body><br></body>`,
    146          `<head><title>iframe</title><${tag}><div>abcdef</div></head><body><br></body>`,
    147          `<head><title>iframe</title><${tag}><div>abcdef<br></div></head><body><br></body>`,
    148        ],
    149        `The <div> elements should be merged without deleting <${tag}>`
    150      );
    151    }
    152  }, `${commandName} around invisible <${tag}> should not delete it at joining paragraphs`);
    153 }
    154 
    155 // Visible <script>, <style>, <title> elements shouldn't be joined
    156 promise_test(async () => {
    157  await initializeAndWaitForLoad(iframe, minimumSrcDoc);
    158  const childDoc = iframe.contentDocument;
    159  const utils = new EditorTestUtils(childDoc.documentElement);
    160  const script1 = childDoc.createElement("script");
    161  script1.innerHTML = "// abc";
    162  script1.setAttribute("style", "display:block");
    163  const script2 = childDoc.createElement("script");
    164  script2.innerHTML = "// def";
    165  script2.setAttribute("style", "display:block");
    166  childDoc.head.appendChild(script1);
    167  childDoc.head.appendChild(script2);
    168  // Now: <head><title>...</title><script>// abc</ script><script>// def</ script></head>...
    169  childDoc.getSelection().collapse(
    170    testingBackspace ? script2.firstChild : script1.firstChild,
    171    testingBackspace ? 0 : script1.firstChild.length
    172  );
    173  await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey());
    174  removeResourceScriptElements(childDoc);
    175  childDoc.head.removeAttribute("style");
    176  script1.removeAttribute("style");
    177  script2.removeAttribute("style");
    178 
    179  assert_equals(
    180    childDoc.documentElement.innerHTML,
    181    "<head><title>iframe</title><script>// abc</" + "script><script>// def</" + "script></head><body><br></body>",
    182    "Visible <script> elements shouldn't be merged"
    183  );
    184 }, `${commandName} in visible <script> elements in <head> should not join them`);
    185 
    186 promise_test(async () => {
    187  await initializeAndWaitForLoad(iframe, minimumSrcDoc);
    188  const childDoc = iframe.contentDocument;
    189  const utils = new EditorTestUtils(childDoc.documentElement);
    190  const style1 = childDoc.createElement("style");
    191  style1.innerHTML = "abc";
    192  style1.setAttribute("style", "display:block");
    193  const style2 = childDoc.createElement("style");
    194  style2.innerHTML = "def";
    195  style2.setAttribute("style", "display:block");
    196  childDoc.head.appendChild(style1);
    197  childDoc.head.appendChild(style2);
    198  // Now: <head><title>...</title><style>abc</style><style>def</style></head>...
    199  childDoc.getSelection().collapse(
    200    testingBackspace ? style2.firstChild : style1.firstChild,
    201    testingBackspace ? 0 : style1.firstChild.length
    202  );
    203  await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey());
    204  removeResourceScriptElements(childDoc);
    205  childDoc.head.removeAttribute("style");
    206  style1.removeAttribute("style");
    207  style2.removeAttribute("style");
    208 
    209  assert_equals(
    210    childDoc.documentElement.innerHTML,
    211    "<head><title>iframe</title><style>abc</style><style>def</style></head><body><br></body>",
    212    "Visible <style> elements shouldn't be merged"
    213  );
    214 }, `${commandName} in visible <style> elements in <head> should not join them`);
    215 
    216 promise_test(async () => {
    217  await initializeAndWaitForLoad(iframe, minimumSrcDoc);
    218  const childDoc = iframe.contentDocument;
    219  const utils = new EditorTestUtils(childDoc.documentElement);
    220  const title1 = childDoc.createElement("title");
    221  title1.innerHTML = "abc";
    222  title1.setAttribute("style", "display:block");
    223  const title2 = childDoc.createElement("title");
    224  title2.innerHTML = "def";
    225  title2.setAttribute("style", "display:block");
    226  childDoc.head.appendChild(title1);
    227  childDoc.head.appendChild(title2);
    228  // Now: <head><title>...</title><title>abc</title><title>def</title></head>...
    229  childDoc.getSelection().collapse(
    230    testingBackspace ? title2.firstChild : title1.firstChild,
    231    testingBackspace ? 0 : title1.firstChild.length
    232  );
    233  await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey());
    234  removeResourceScriptElements(childDoc);
    235  childDoc.head.removeAttribute("style");
    236  title1.removeAttribute("style");
    237  title2.removeAttribute("style");
    238 
    239  assert_equals(
    240    childDoc.documentElement.innerHTML,
    241    "<head><title>iframe</title><title>abc</title><title>def</title></head><body><br></body>",
    242    "Visible <title> elements shouldn't be merged"
    243  );
    244 }, `${commandName} in visible <title> elements in <head> should not join them`);
    245 
    246 // Visible <script>, <style>, <title> shouldn't be joined with following <div>
    247 promise_test(async () => {
    248  await initializeAndWaitForLoad(iframe, minimumSrcDoc);
    249  const childDoc = iframe.contentDocument;
    250  const utils = new EditorTestUtils(childDoc.documentElement);
    251  const script = childDoc.createElement("script");
    252  script.innerHTML = "// abc";
    253  script.setAttribute("style", "display:block");
    254  const div = childDoc.createElement("div");
    255  div.innerHTML = "// def";
    256  childDoc.head.appendChild(script);
    257  childDoc.head.appendChild(div);
    258  // Now: <head><title>...</title><script>// abc</ script><div>// def</div></head>...
    259  childDoc.getSelection().collapse(
    260    testingBackspace ? div.firstChild : script.firstChild,
    261    testingBackspace ? 0 : script.firstChild.length
    262  );
    263  await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey());
    264  removeResourceScriptElements(childDoc);
    265  childDoc.head.removeAttribute("style");
    266  script.removeAttribute("style");
    267 
    268  assert_equals(
    269    childDoc.documentElement.innerHTML,
    270    "<head><title>iframe</title><script>// abc</" + "script><div>// def</div></head><body><br></body>",
    271    "Visible <script> and <div> shouldn't be merged"
    272  );
    273 }, `${commandName} at boundary of <script> and <div> in <head> should not join them`);
    274 
    275 promise_test(async () => {
    276  await initializeAndWaitForLoad(iframe, minimumSrcDoc);
    277  const childDoc = iframe.contentDocument;
    278  const utils = new EditorTestUtils(childDoc.documentElement);
    279  const style = childDoc.createElement("style");
    280  style.innerHTML = "abc";
    281  style.setAttribute("style", "display:block");
    282  const div = childDoc.createElement("div");
    283  div.innerHTML = "def";
    284  childDoc.head.appendChild(style);
    285  childDoc.head.appendChild(div);
    286  // Now: <head><title>...</title><style>abc</style><div>def</div></head>...
    287  childDoc.getSelection().collapse(
    288    testingBackspace ? div.firstChild : style.firstChild,
    289    testingBackspace ? 0 : style.firstChild.length
    290  );
    291  await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey());
    292  removeResourceScriptElements(childDoc);
    293  childDoc.head.removeAttribute("style");
    294  style.removeAttribute("style");
    295 
    296  assert_equals(
    297    childDoc.documentElement.innerHTML,
    298    "<head><title>iframe</title><style>abc</style><div>def</div></head><body><br></body>",
    299    "Visible <style> and <div> shouldn't be merged"
    300  );
    301 }, `${commandName} at boundary of <style> and <div> in <head> should not join them`);
    302 
    303 promise_test(async () => {
    304  await initializeAndWaitForLoad(iframe, minimumSrcDoc);
    305  const childDoc = iframe.contentDocument;
    306  const utils = new EditorTestUtils(childDoc.documentElement);
    307  const title = childDoc.createElement("title");
    308  title.innerHTML = "abc";
    309  title.setAttribute("title", "display:block");
    310  const div = childDoc.createElement("div");
    311  div.innerHTML = "def";
    312  childDoc.head.appendChild(title);
    313  childDoc.head.appendChild(div);
    314  // Now: <head><title>...</title><title>abc</title><div>def</div></head>...
    315  childDoc.getSelection().collapse(
    316    testingBackspace ? div.firstChild : title.firstChild,
    317    testingBackspace ? 0 : title.firstChild.length
    318  );
    319  await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey());
    320  removeResourceScriptElements(childDoc);
    321  childDoc.head.removeAttribute("style");
    322  title.removeAttribute("style");
    323 
    324  assert_equals(
    325    childDoc.documentElement.innerHTML,
    326    "<head><title>iframe</title><title>abc</title><div>def</div></head><body><br></body>",
    327    "Visible <title> and <div> shouldn't be merged"
    328  );
    329 }, `${commandName} at boundary of <title> and <div> in <head> should not join them`);
    330 
    331 // Visible <script>, <style>, <title> shouldn't be joined with preceding <div>
    332 promise_test(async () => {
    333  await initializeAndWaitForLoad(iframe, minimumSrcDoc);
    334  const childDoc = iframe.contentDocument;
    335  const utils = new EditorTestUtils(childDoc.documentElement);
    336  const div = childDoc.createElement("div");
    337  div.innerHTML = "// abc";
    338  const script = childDoc.createElement("script");
    339  script.innerHTML = "// def";
    340  script.setAttribute("style", "display:block");
    341  childDoc.head.appendChild(div);
    342  childDoc.head.appendChild(script);
    343  // Now: <head><title>...</title><div>// abc</div><script>// def</ script></head>...
    344  childDoc.getSelection().collapse(
    345    testingBackspace ? script.firstChild : div.firstChild,
    346    testingBackspace ? 0 : div.firstChild.length
    347  );
    348  await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey());
    349  removeResourceScriptElements(childDoc);
    350  childDoc.head.removeAttribute("style");
    351  script.removeAttribute("style");
    352 
    353  assert_equals(
    354    childDoc.documentElement.innerHTML,
    355    "<head><title>iframe</title><div>// abc</div><script>// def</" + "script></head><body><br></body>",
    356    "<div> and visible <script> shouldn't be merged"
    357  );
    358 }, `${commandName} at boundary of <div> and <script> in <head> should not join them`);
    359 
    360 promise_test(async () => {
    361  await initializeAndWaitForLoad(iframe, minimumSrcDoc);
    362  const childDoc = iframe.contentDocument;
    363  const utils = new EditorTestUtils(childDoc.documentElement);
    364  const div = childDoc.createElement("div");
    365  div.innerHTML = "abc";
    366  const style = childDoc.createElement("style");
    367  style.innerHTML = "def";
    368  style.setAttribute("style", "display:block");
    369  childDoc.head.appendChild(div);
    370  childDoc.head.appendChild(style);
    371  // Now: <head><title>...</title><div>abc</div><style>def</style></head>...
    372  childDoc.getSelection().collapse(
    373    testingBackspace ? style.firstChild : div.firstChild,
    374    testingBackspace ? 0 : div.firstChild.length
    375  );
    376  await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey());
    377  removeResourceScriptElements(childDoc);
    378  childDoc.head.removeAttribute("style");
    379  style.removeAttribute("style");
    380 
    381  assert_equals(
    382    childDoc.documentElement.innerHTML,
    383    "<head><title>iframe</title><div>abc</div><style>def</style></head><body><br></body>",
    384    "<div> and visible <style> shouldn't be merged"
    385  );
    386 }, `${commandName} at boundary of <div> and <style> in <head> should not join them`);
    387 
    388 promise_test(async () => {
    389  await initializeAndWaitForLoad(iframe, minimumSrcDoc);
    390  const childDoc = iframe.contentDocument;
    391  const utils = new EditorTestUtils(childDoc.documentElement);
    392  const div = childDoc.createElement("div");
    393  div.innerHTML = "abc";
    394  const title = childDoc.createElement("title");
    395  title.innerHTML = "def";
    396  title.setAttribute("style", "display:block");
    397  childDoc.head.appendChild(div);
    398  childDoc.head.appendChild(title);
    399  // Now: <head><title>...</title><div>abc</div><title>def</title></head>...
    400  childDoc.getSelection().collapse(
    401    testingBackspace ? title.firstChild : div.firstChild,
    402    testingBackspace ? 0 : div.firstChild.length
    403  );
    404  await (testingBackspace ? utils.sendBackspaceKey() : utils.sendDeleteKey());
    405  removeResourceScriptElements(childDoc);
    406  childDoc.head.removeAttribute("style");
    407  title.removeAttribute("style");
    408 
    409  assert_equals(
    410    childDoc.documentElement.innerHTML,
    411    "<head><title>iframe</title><div>abc</div><title>def</title></head><body><br></body>",
    412    "<div> and visible <title> shouldn't be merged"
    413  );
    414 }, `${commandName} at boundary of <div> and <title> in <head> should not join them`);
    415 
    416 </script>
    417 </body>
    418 </html>