tor-browser

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

modifying-selection-with-non-primary-mouse-button.tentative.html (9690B)


      1 <!doctype html>
      2 <html>
      3 <head>
      4 <meta charset="utf-8">
      5 <meta name="variant" content="?middle">
      6 <meta name="variant" content="?secondary">
      7 <title>Testing default action of `mousedown` of middle button and `mouseup` of middle/secondary button</title>
      8 <script src="/resources/testharness.js"></script>
      9 <script src="/resources/testharnessreport.js"></script>
     10 <script src="/resources/testdriver.js"></script>
     11 <script src="/resources/testdriver-vendor.js"></script>
     12 <script src="/resources/testdriver-actions.js"></script>
     13 <style>
     14 span {
     15  white-space: nowrap;
     16 }
     17 </style>
     18 </head>
     19 <body>
     20 <div contenteditable></div>
     21 <script>
     22 "use strict";
     23 
     24 const button = location.search.substr(1);
     25 
     26 function getButtonType(actions) {
     27  return button == "middle" ? actions.ButtonType.MIDDLE : actions.ButtonType.RIGHT;
     28 }
     29 
     30 var editor = document.querySelector("div[contenteditable]");
     31 var span1, span2, link;
     32 var selection = getSelection();
     33 
     34 function preventDefault(event) {
     35  event.preventDefault();
     36 }
     37 editor.addEventListener("paste", preventDefault, {capture: true});
     38 document.addEventListener("contextmenu", preventDefault, {capture: true});
     39 
     40 function resetEditor() {
     41  editor.innerHTML =
     42    '<span id="span1">first span.</span><br><span id="span2">second span.</span><br><a id="link" href="#top">link.</a>';
     43  span1 = document.getElementById("span1");
     44  span2 = document.getElementById("span2");
     45  link = document.getElementById("link");
     46 }
     47 
     48 promise_test(async () => {
     49  resetEditor();
     50  editor.blur();
     51  let actions = new test_driver.Actions();
     52  await actions
     53    .pointerMove(0, 0)
     54    .pointerMove(0, 0, {origin: span1})
     55    .pointerDown({button: getButtonType(actions)})
     56    .pointerUp({button: getButtonType(actions)})
     57    .send();
     58 
     59  assert_equals(document.activeElement, editor,
     60    "The clicked editor should get focus");
     61  assert_true(selection.isCollapsed,
     62    `Selection should be collapsed after ${button} button click`);
     63  assert_equals(selection.focusNode, span1.firstChild,
     64    `Selection should be collapsed in the first <span> element which was clicked by ${button} button`);
     65 }, `${button} click should set focus to clicked editable element and collapse selection around the clicked point`);
     66 
     67 promise_test(async () => {
     68  resetEditor();
     69  editor.focus();
     70  selection.collapse(span1.firstChild, 2);
     71  let actions = new test_driver.Actions();
     72  await actions
     73    .pointerMove(0, 0)
     74    .pointerMove(0, 0, {origin: span2})
     75    .pointerDown({button: getButtonType(actions)})
     76    .pointerUp({button: getButtonType(actions)})
     77    .send();
     78 
     79  assert_equals(document.activeElement, editor,
     80    "The clicked editor should keep having focus");
     81  assert_true(selection.isCollapsed,
     82    `Selection should be collapsed after ${button} button click`);
     83  assert_equals(selection.focusNode, span2.firstChild,
     84    `Selection should be collapsed in the second <span> element which was clicked by ${button} button`);
     85 }, `${button} click should move caret in an editable element`);
     86 
     87 promise_test(async () => {
     88  resetEditor();
     89  editor.focus();
     90  selection.collapse(span1.firstChild, 2);
     91  addEventListener("mousedown", preventDefault);
     92  let actions = new test_driver.Actions();
     93  await actions
     94    .pointerMove(0, 0)
     95    .pointerMove(0, 0, {origin: span2})
     96    .pointerDown({button: getButtonType(actions)})
     97    .pointerUp({button: getButtonType(actions)})
     98    .send();
     99  removeEventListener("mousedown", preventDefault);
    100 
    101  assert_equals(selection.focusNode, span1.firstChild,
    102    "Selection should keep collapsed selection in the first <span> element");
    103  assert_equals(selection.focusOffset, 2,
    104    "Selection should keep collapsed selection at 2 of the first <span> element");
    105 }, `${button} click shouldn't move caret in an editable element if the default of mousedown event is prevented`);
    106 
    107 promise_test(async () => {
    108  resetEditor();
    109  editor.focus();
    110  selection.collapse(span1.firstChild, 2);
    111  addEventListener("pointerdown", preventDefault);
    112  let actions = new test_driver.Actions();
    113  await actions
    114    .pointerMove(0, 0)
    115    .pointerMove(0, 0, {origin: span2})
    116    .pointerDown({button: getButtonType(actions)})
    117    .pointerUp({button: getButtonType(actions)})
    118    .send();
    119  removeEventListener("pointerdown", preventDefault);
    120 
    121  assert_equals(selection.focusNode, span1.firstChild,
    122    "Selection should keep collapsed selection in the first <span> element");
    123  assert_equals(selection.focusOffset, 2,
    124    "Selection should keep collapsed selection at 2 of the first <span> element");
    125 }, `${button} click shouldn't move caret in an editable element if the default of pointerdown event is prevented`);
    126 
    127 promise_test(async () => {
    128  resetEditor();
    129  editor.focus();
    130  selection.collapse(span1.firstChild, 2);
    131  let contextmenuFired = false;
    132  function onContextMenu() {
    133    contextmenuFired = true;
    134  }
    135  document.addEventListener("contextmenu", onContextMenu, {capture: true});
    136  let actions = new test_driver.Actions();
    137  await actions
    138    .pointerMove(0, 0)
    139    .pointerMove(0, 0, {origin: span2})
    140    .keyDown("\uE008")
    141    .pointerDown({button: getButtonType(actions)})
    142    .pointerUp({button: getButtonType(actions)})
    143    .keyUp("\uE008")
    144    .send();
    145  document.removeEventListener("contextmenu", onContextMenu, {capture: true});
    146 
    147  if (button != "secondary" || contextmenuFired) {
    148    assert_equals(selection.anchorNode, span1.firstChild,
    149      "Selection#anchorNode should keep in the first <span> element");
    150    assert_equals(selection.anchorOffset, 2,
    151      "Selection#anchorNode should keep at 2 of the first <span> element");
    152    assert_equals(selection.focusNode, span2.firstChild,
    153      `Selection#focusNode should be in the second <span> element which was clicked by ${button} button`);
    154  } else {
    155    // Special case for Firefox.  Firefox users can forcibly open context menu
    156    // with pressing shift key.  In this case, users may want the secondary
    157    // button click to work as without Shift key press.
    158    assert_true(selection.isCollapsed,
    159      `Selection should be collapsed after ${button} button click because contextmenu was not opened with Shift key`);
    160    assert_equals(selection.focusNode, span2.firstChild,
    161      `Selection should be collapsed in the second <span> element which was clicked by ${
    162        button
    163      } button because contextmenu was not opened with Shift key`);
    164  }
    165 }, `Shift + ${button} click should extend the selection`);
    166 
    167 promise_test(async () => {
    168  resetEditor();
    169  editor.focus();
    170  selection.collapse(span1.firstChild, 2);
    171  let actions = new test_driver.Actions();
    172  await actions
    173    .pointerMove(0, 0)
    174    .pointerMove(0, 0, {origin: link})
    175    .keyDown("\uE008")
    176    .pointerDown({button: getButtonType(actions)})
    177    .pointerUp({button: getButtonType(actions)})
    178    .keyUp("\uE008")
    179    .send();
    180 
    181  assert_equals(selection.focusNode, link.firstChild,
    182    `Selection#focusNode should be in the <a href> element which was clicked by ${button} button`);
    183  assert_true(selection.isCollapsed,
    184    "Selection#isCollapsed should be true");
    185 }, `Shift + ${button} click in a link shouldn't extend the selection`);
    186 
    187 promise_test(async () => {
    188  resetEditor();
    189  editor.focus();
    190  selection.collapse(span1.firstChild, 2);
    191  editor.addEventListener("pointerdown", () => {
    192    assert_true(selection.isCollapsed,
    193      "Selection shouldn't be modified before pointerdown event");
    194    assert_equals(selection.focusNode, span1.firstChild,
    195      "Selection should stay in the first <span> element when pointerdown event is fired (focusNode)");
    196    assert_equals(selection.focusOffset, 2,
    197      "Selection should stay in the first <span> element when pointerdown event is fired (focusOffset)");
    198  }, {once: true});
    199  editor.addEventListener("mousedown", () => {
    200    assert_true(selection.isCollapsed,
    201      "Selection shouldn't be modified before mousedown event");
    202    assert_equals(selection.focusNode, span1.firstChild,
    203      "Selection should stay in the first <span> element when mousedown event is fired (focusNode)");
    204    assert_equals(selection.focusOffset, 2,
    205      "Selection should stay in the first <span> element when mousedown event is fired (focusOffset)");
    206  }, {once: true});
    207  editor.addEventListener("pointerup", () => {
    208    assert_true(selection.isCollapsed,
    209      "Selection should be collapsed before pointerup event");
    210    assert_equals(selection.focusNode, span2.firstChild,
    211      `selection should be collapsed in the second <span> element which was clicked by ${button} button before pointerup event`);
    212  }, {once: true});
    213  let focusOffsetAtMouseUp;
    214  editor.addEventListener("mouseup", () => {
    215    assert_true(selection.isCollapsed,
    216      "Selection should be collapsed before mouseup event");
    217    assert_equals(selection.focusNode, span2.firstChild,
    218      `Selection should be collapsed in the second <span> element which was clicked by ${button} button before mouseup event`);
    219    focusOffsetAtMouseUp = selection.focusOffset;
    220  }, {once: true});
    221  let actions = new test_driver.Actions();
    222  await actions
    223    .pointerMove(0, 0)
    224    .pointerMove(0, 0, {origin: span2})
    225    .pointerDown({button: getButtonType(actions)})
    226    .pointerMove(0, 0, {origin: span1})
    227    .pointerUp({button: getButtonType(actions)})
    228    .send();
    229 
    230  assert_true(selection.isCollapsed,
    231    `Selection shouldn't be extended by pointer moves during pressing ${button} button`);
    232  assert_equals(selection.focusNode, span2.firstChild,
    233    "Selection#focusNode should stay in the second <span> element");
    234  assert_equals(selection.focusOffset, focusOffsetAtMouseUp,
    235    "Selection#focusOffset should stay in the second <span> element");
    236 }, `${button} mouse button down should move caret, but its button up shouldn't move caret`);
    237 
    238 </script>
    239 </body>
    240 </html>