tor-browser

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

input-events-get-target-ranges.html (5831B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <title>InputEvent.getTargetRanges() behavior</title>
      4 <script src="/resources/testharness.js"></script>
      5 <script src="/resources/testharnessreport.js"></script>
      6 <script src="/resources/testdriver.js"></script>
      7 <script src="/resources/testdriver-actions.js"></script>
      8 <script src="/resources/testdriver-vendor.js"></script>
      9 <p>To manually run this test, please follow the steps below:<br/>
     10 1. Place caret at the end of 'hel<i>lo wo</i><b>rld</b>'.<br/>
     11 2. Press Ctrl-Backspace (Alt-Backspace on macOS) to delete word backwards.<br/>
     12 3. Place caret at the end of 'test2' => Press 'a' key.<br/>
     13 4. Select 'test2a' => Press 'b' key.<br/>
     14 5. Select 'b' => Bold text through context menu or Command-b on macOS.<br/>
     15 6. Place caret at the end of 'test3' => Press 'a' key => Press Backspace key.<br/>
     16 <br/>
     17 If a "PASS" result appears the test passes, otherwise it fails</p>
     18 <p id="test1_editable" contenteditable>hel<i>lo wo</i><b>rld</b></p>
     19 <p id="test2_editable" contenteditable>test2</p>
     20 <textarea id="test3_plain">test3</textarea>
     21 <script>
     22 function resolveWhen(condition) {
     23  return new Promise((resolve, reject) => {
     24    function tick() {
     25      if (condition())
     26        resolve();
     27      else
     28        requestAnimationFrame(tick.bind(this));
     29    }
     30    tick();
     31  });
     32 }
     33 
     34 let modifier_key = "\uE009";
     35 if(navigator.platform.includes('Mac'))
     36    modifier_key = "\uE03D";
     37 const commands = {
     38    COPY: 'copy',
     39    CUT: 'cut',
     40    PASTE: 'paste',
     41    SELECTALL: 'select all',
     42    DELETEALL: 'delete all',
     43    BOLD: 'bold',
     44 }
     45 const backspace = "\uE003";
     46 
     47 function clickOnTarget(target) {
     48  return new test_driver.Actions()
     49      .pointerMove(0, 0, {origin: target})
     50      .pointerDown()
     51      .pointerUp()
     52      .send();
     53 }
     54 
     55 function sendTextCommand(command) {
     56  let command_key = "";
     57  if(command == "copy")
     58    command_key = "c";
     59  else if (command == "cut")
     60    command_key = "x";
     61  else if (command == "paste")
     62    command_key = "v";
     63  else if (command == "select all")
     64    command_key = "a";
     65  else if (command == "delete all")
     66    command_key = backspace;
     67  else if (command == "bold")
     68    command_key = "b";
     69  return new test_driver.Actions()
     70      .keyDown(modifier_key)
     71      .keyDown(command_key)
     72      .keyUp(command_key)
     73      .keyUp(modifier_key)
     74      .send();
     75 }
     76 
     77 function sendTextCommandAtTarget(target, command) {
     78  return clickOnTarget(target).then(() => {
     79    return sendTextCommand(command);
     80  });
     81 }
     82 
     83 function addTextAtTarget(target, char) {
     84  return test_driver.send_keys(target, char);
     85 }
     86 
     87 promise_test(async test => {
     88    const test1_editable = document.getElementById('test1_editable');
     89    let lastBeforeInput;
     90    test1_editable.addEventListener('beforeinput', test.step_func(function() {
     91        assert_equals(event.inputType, 'deleteWordBackward');
     92        const ranges = event.getTargetRanges();
     93        assert_equals(ranges.length, 1);
     94        const range = ranges[0];
     95        assert_true(range instanceof StaticRange);
     96        assert_equals(range.startOffset, 3);
     97        assert_equals(range.startContainer.textContent, 'lo wo');
     98        assert_equals(range.endOffset, 3);
     99        assert_equals(range.endContainer.textContent, 'rld');
    100        assert_equals(test1_editable.innerHTML, 'hel<i>lo wo</i><b>rld</b>');
    101        lastBeforeInput = event;
    102    }));
    103 
    104    test1_editable.addEventListener('input', test.step_func(function() {
    105        assert_equals(event.inputType, 'deleteWordBackward');
    106        assert_equals(test1_editable.innerHTML, 'hel<i>lo&nbsp;</i>');
    107        assert_equals(lastBeforeInput.inputType, 'deleteWordBackward');
    108        assert_equals(lastBeforeInput.getTargetRanges().length, 0,
    109            'getTargetRanges() should be empty after the event has finished dispatching.');
    110    }));
    111 
    112    await sendTextCommandAtTarget(test1_editable, commands.DELETEALL);
    113    await resolveWhen(() => { return test1_editable.innerHTML == 'hel<i>lo&nbsp;</i>' });
    114 }, 'getTargetRanges() returns correct range and cleared after dispatch.');
    115 
    116 promise_test(async test => {
    117    const expectedEventLog = ['test2-5-test2-5', 'test2a-0-test2a-6', 'b-0-b-1'];
    118    const actualEventLog = [];
    119 
    120    const test2_editable = document.getElementById('test2_editable');
    121    test2_editable.addEventListener('beforeinput', test.step_func(function() {
    122        const ranges = event.getTargetRanges();
    123        assert_equals(ranges.length, 1);
    124        const range = ranges[0];
    125        actualEventLog.push(
    126            `${range.startContainer.textContent}-${range.startOffset}-${range.endContainer.textContent}-${range.endOffset}`);
    127    }));
    128 
    129    await addTextAtTarget(test2_editable, "a");
    130    await sendTextCommandAtTarget(test2_editable, commands.SELECTALL);
    131    await addTextAtTarget(test2_editable, "b");
    132    await sendTextCommandAtTarget(test2_editable, commands.SELECTALL);
    133    await sendTextCommand(commands.BOLD);
    134    await resolveWhen(() => { return actualEventLog.length == expectedEventLog.length });
    135    assert_array_equals(actualEventLog, expectedEventLog,
    136                        `Expected: ${expectedEventLog}; Actual: ${actualEventLog}.`);
    137 }, 'Actions other than deletion should have current selection as target ranges.');
    138 
    139 promise_test(async test => {
    140    const test3_plain = document.getElementById('test3_plain');
    141    let event_type;
    142    test3_plain.addEventListener('beforeinput', test.step_func(function() {
    143        assert_equals(event.getTargetRanges().length, 0,
    144            'getTargetRanges() should return empty array on textarea.');
    145 
    146        if (event.inputType === 'deleteContentBackward')
    147            event_type = event.inputType;
    148    }));
    149 
    150    await addTextAtTarget(test3_plain, "a");
    151    await addTextAtTarget(test3_plain, backspace);
    152    await resolveWhen(() => { return event_type == 'deleteContentBackward' });
    153 }, 'Textarea should have empty target range.');
    154 </script>