tor-browser

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

input-events-delete-selection.html (8159B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8" />
      3 <title>
      4  Input Event tests for deletion with non-collapsed selection
      5 </title>
      6 <script src="/resources/testharness.js"></script>
      7 <script src="/resources/testharnessreport.js"></script>
      8 <script src="/resources/testdriver.js"></script>
      9 <script src="/resources/testdriver-vendor.js"></script>
     10 <script src="/resources/testdriver-actions.js"></script>
     11 <div id="rich" contenteditable></div>
     12 <script>
     13  let inputEventsLog = [];
     14  const rich = document.getElementById("rich");
     15  const isMacOS = navigator.platform.indexOf("Mac") === 0;
     16  const MODIFIER_KEY = isMacOS ? "\uE00A" : "\uE009"; // Alt on Mac, Ctrl on others
     17 
     18  function log(event) {
     19    inputEventsLog.push({
     20      type: event.type,
     21      inputType: event.inputType,
     22      data: event.data,
     23    });
     24  }
     25 
     26  function resetRich() {
     27    inputEventsLog = [];
     28    rich.innerHTML = "";
     29  }
     30 
     31  function selectText(startNode, startOffset, endNode, endOffset) {
     32    const selection = window.getSelection();
     33    const range = document.createRange();
     34    range.setStart(startNode, startOffset);
     35    range.setEnd(endNode, endOffset);
     36    selection.removeAllRanges();
     37    selection.addRange(range);
     38  }
     39 
     40  rich.addEventListener("beforeinput", log);
     41  rich.addEventListener("input", log);
     42 
     43  // Test Ctrl+Backspace with non-collapsed selection
     44  promise_test(async function () {
     45    this.add_cleanup(resetRich);
     46    rich.innerHTML = "hello world";
     47    rich.focus();
     48 
     49    const textNode = rich.firstChild;
     50    // Select "or" in "world"
     51    selectText(textNode, 6, textNode, 8);
     52 
     53    // Simulate Ctrl+Backspace (Alt+Backspace on Mac)
     54    await new test_driver.Actions()
     55      .keyDown(MODIFIER_KEY)
     56      .keyDown("\uE003") // Backspace
     57      .keyUp("\uE003")
     58      .keyUp(MODIFIER_KEY)
     59      .send();
     60 
     61    assert_equals(inputEventsLog.length, 2, "Should have 2 events");
     62    const [beforeInputEvent, inputEvent] = inputEventsLog;
     63    assert_equals(beforeInputEvent.type, "beforeinput");
     64    assert_equals(inputEvent.type, "input");
     65    // When deleting a selection, inputType should be deleteContentBackward
     66    assert_equals(
     67      beforeInputEvent.inputType,
     68      "deleteContentBackward",
     69      "Ctrl+Backspace with selection should report deleteContentBackward"
     70    );
     71    assert_equals(
     72      inputEvent.inputType,
     73      "deleteContentBackward",
     74      "Ctrl+Backspace with selection should report deleteContentBackward"
     75    );
     76  }, "Ctrl+Backspace with non-collapsed selection should report deleteContentBackward");
     77 
     78  // Test Ctrl+Backspace with caret (collapsed selection)
     79  promise_test(async function () {
     80    this.add_cleanup(resetRich);
     81    rich.innerHTML = "hello world";
     82    rich.focus();
     83 
     84    const textNode = rich.firstChild;
     85    // Place caret after "world"
     86    selectText(textNode, 11, textNode, 11);
     87 
     88    // Simulate Ctrl+Backspace (Alt+Backspace on Mac)
     89    await new test_driver.Actions()
     90      .keyDown(MODIFIER_KEY)
     91      .keyDown("\uE003") // Backspace
     92      .keyUp("\uE003")
     93      .keyUp(MODIFIER_KEY)
     94      .send();
     95 
     96    assert_equals(inputEventsLog.length, 2, "Should have 2 events");
     97    const [beforeInputEvent, inputEvent] = inputEventsLog;
     98    assert_equals(beforeInputEvent.type, "beforeinput");
     99    assert_equals(inputEvent.type, "input");
    100    // With caret, should be deleteWordBackward
    101    assert_equals(
    102      beforeInputEvent.inputType,
    103      "deleteWordBackward",
    104      "Ctrl+Backspace with caret should report deleteWordBackward"
    105    );
    106    assert_equals(
    107      inputEvent.inputType,
    108      "deleteWordBackward",
    109      "Ctrl+Backspace with caret should report deleteWordBackward"
    110    );
    111  }, "Ctrl+Backspace with caret should report deleteWordBackward");
    112 
    113  // Test Ctrl+Delete with non-collapsed selection
    114  promise_test(async function () {
    115    this.add_cleanup(resetRich);
    116    rich.innerHTML = "hello world";
    117    rich.focus();
    118 
    119    const textNode = rich.firstChild;
    120    // Select "ell" in "hello"
    121    selectText(textNode, 1, textNode, 4);
    122 
    123    // Simulate Ctrl+Delete (Alt+Delete on Mac)
    124    await new test_driver.Actions()
    125      .keyDown(MODIFIER_KEY)
    126      .keyDown("\uE017") // Delete
    127      .keyUp("\uE017")
    128      .keyUp(MODIFIER_KEY)
    129      .send();
    130 
    131    assert_equals(inputEventsLog.length, 2, "Should have 2 events");
    132    const [beforeInputEvent, inputEvent] = inputEventsLog;
    133    assert_equals(beforeInputEvent.type, "beforeinput");
    134    assert_equals(inputEvent.type, "input");
    135    // When deleting a selection, inputType should be deleteContentForward
    136    assert_equals(
    137      beforeInputEvent.inputType,
    138      "deleteContentForward",
    139      "Ctrl+Delete with selection should report deleteContentForward"
    140    );
    141    assert_equals(
    142      inputEvent.inputType,
    143      "deleteContentForward",
    144      "Ctrl+Delete with selection should report deleteContentForward"
    145    );
    146  }, "Ctrl+Delete with non-collapsed selection should report deleteContentForward");
    147 
    148  // Test Ctrl+Delete with caret (collapsed selection)
    149  promise_test(async function () {
    150    this.add_cleanup(resetRich);
    151    rich.innerHTML = "hello world";
    152    rich.focus();
    153 
    154    const textNode = rich.firstChild;
    155    // Place caret before "world"
    156    selectText(textNode, 6, textNode, 6);
    157 
    158    // Simulate Ctrl+Delete (Alt+Delete on Mac)
    159    await new test_driver.Actions()
    160      .keyDown(MODIFIER_KEY)
    161      .keyDown("\uE017") // Delete
    162      .keyUp("\uE017")
    163      .keyUp(MODIFIER_KEY)
    164      .send();
    165 
    166    assert_equals(inputEventsLog.length, 2, "Should have 2 events");
    167    const [beforeInputEvent, inputEvent] = inputEventsLog;
    168    assert_equals(beforeInputEvent.type, "beforeinput");
    169    assert_equals(inputEvent.type, "input");
    170    // With caret, should be deleteWordForward
    171    assert_equals(
    172      beforeInputEvent.inputType,
    173      "deleteWordForward",
    174      "Ctrl+Delete with caret should report deleteWordForward"
    175    );
    176    assert_equals(
    177      inputEvent.inputType,
    178      "deleteWordForward",
    179      "Ctrl+Delete with caret should report deleteWordForward"
    180    );
    181  }, "Ctrl+Delete with caret should report deleteWordForward");
    182 
    183  // Test regular Backspace with non-collapsed selection (should still be deleteContentBackward)
    184  promise_test(async function () {
    185    this.add_cleanup(resetRich);
    186    rich.innerHTML = "hello world";
    187    rich.focus();
    188 
    189    const textNode = rich.firstChild;
    190    // Select "lo wo"
    191    selectText(textNode, 3, textNode, 8);
    192 
    193    // Simulate Backspace (without Ctrl)
    194    await test_driver.send_keys(rich, "\uE003"); // Backspace
    195 
    196    assert_equals(inputEventsLog.length, 2, "Should have 2 events");
    197    const [beforeInputEvent, inputEvent] = inputEventsLog;
    198    assert_equals(beforeInputEvent.type, "beforeinput");
    199    assert_equals(inputEvent.type, "input");
    200    assert_equals(
    201      beforeInputEvent.inputType,
    202      "deleteContentBackward",
    203      "Regular Backspace with selection should report deleteContentBackward"
    204    );
    205    assert_equals(
    206      inputEvent.inputType,
    207      "deleteContentBackward",
    208      "Regular Backspace with selection should report deleteContentBackward"
    209    );
    210  }, "Regular Backspace with non-collapsed selection should report deleteContentBackward");
    211 
    212  // Test regular Delete with non-collapsed selection (should be deleteContentForward)
    213  promise_test(async function () {
    214    this.add_cleanup(resetRich);
    215    rich.innerHTML = "hello world";
    216    rich.focus();
    217 
    218    const textNode = rich.firstChild;
    219    // Select "lo wo"
    220    selectText(textNode, 3, textNode, 8);
    221 
    222    // Simulate Delete (without Ctrl)
    223    await test_driver.send_keys(rich, "\uE017"); // Delete
    224 
    225    assert_equals(inputEventsLog.length, 2, "Should have 2 events");
    226    const [beforeInputEvent, inputEvent] = inputEventsLog;
    227    assert_equals(beforeInputEvent.type, "beforeinput");
    228    assert_equals(inputEvent.type, "input");
    229    assert_equals(
    230      beforeInputEvent.inputType,
    231      "deleteContentForward",
    232      "Regular Delete with selection should report deleteContentForward"
    233    );
    234    assert_equals(
    235      inputEvent.inputType,
    236      "deleteContentForward",
    237      "Regular Delete with selection should report deleteContentForward"
    238    );
    239  }, "Regular Delete with non-collapsed selection should report deleteContentForward");
    240 </script>