tor-browser

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

input-events-cut-paste.html (5408B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <title>Cut and Paste should trigger corresponding InputEvent</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 <script type="text/javascript" src="pointerevent_support.js"></script>
     10 <p>To manually run this test, please follow the steps below:<br/>
     11 1. Select 'plain' => Cut (e.g. Ctrl/Cmd-X) => Paste (e.g. Ctrl/Cmd-V).<br/>
     12 2. Select 'rich' => Cut => Paste.<br/>
     13 3. Select 'prevent' => Paste.<br/>
     14 4. Select 'prevent' => Cut => Select 'normal' => Paste.<br/>
     15 <br/>
     16 If a "PASS" result appears the test passes, otherwise it fails</p>
     17 <textarea id="test1_plain">plain</textarea>
     18 <p id="test2_editable" contenteditable><b>rich</b></p>
     19 <p id="test3_editable_prevent" contenteditable>prevent</p>
     20 <p id="test3_editable_normal" contenteditable>normal</p>
     21 <script>
     22 
     23 function resolveWhen(condition) {
     24  return new Promise((resolve, reject) => {
     25    function tick() {
     26      if (condition())
     27        resolve();
     28      else
     29        requestAnimationFrame(tick.bind(this));
     30    }
     31    tick();
     32  });
     33 }
     34 
     35 let modifier_key = "\uE009";
     36 if(navigator.platform.includes('Mac'))
     37    modifier_key = "\uE03D";
     38 const commands = {
     39    COPY: 'copy',
     40    CUT: 'cut',
     41    PASTE: 'paste',
     42 }
     43 function selectTextCommand(target, command) {
     44  let command_key = "";
     45  if(command == "copy")
     46    command_key = "c";
     47  else if (command == "cut")
     48    command_key = "x";
     49  else if (command == "paste")
     50    command_key = "v";
     51  return new test_driver.Actions()
     52      .pointerMove(0, 0, {origin: target})
     53      .pointerDown()
     54      .pointerUp()
     55      .addTick()
     56      .keyDown(modifier_key)
     57      .keyDown("a")
     58      .keyUp("a")
     59      .keyDown(command_key)
     60      .keyUp(command_key)
     61      .keyUp(modifier_key)
     62      .send();
     63 }
     64 
     65 function selectTextCutAndPaste(target1, target2) {
     66  return selectTextCommand(target1, commands.CUT).then(() => {
     67    return selectTextCommand(target2, commands.PASTE);
     68  })
     69 }
     70 
     71 promise_test(async test => {
     72  const expectedEventLog = [
     73        'cut-[null]', 'beforeinput-deleteByCut', 'input-deleteByCut',
     74        'paste-[null]', 'beforeinput-insertFromPaste', 'input-insertFromPaste'];
     75  const actualEventLog = [];
     76  const text1 = document.getElementById("test1_plain");
     77 
     78  for (let eventType of ['beforeinput', 'input', 'cut', 'paste']) {
     79      text1.addEventListener(eventType, test.step_func(function() {
     80          if (event.type === 'beforeinput' && event.inputType === 'insertFromPaste') {
     81              assert_equals(event.data, 'plain');
     82              assert_equals(event.dataTransfer, null);
     83          }
     84 
     85          actualEventLog.push(`${event.type}-${event.inputType || '[null]'}`);
     86      }));
     87  }
     88  await selectTextCutAndPaste(text1, text1);
     89  await resolveWhen(() => { return actualEventLog.length == expectedEventLog.length });
     90  assert_array_equals(actualEventLog, expectedEventLog,
     91                      `Expected: ${expectedEventLog}; Actual: ${actualEventLog}.`);
     92 }, 'Event order and data on textarea.');
     93 
     94 promise_test(async test => {
     95    const expectedEventLog = [
     96        'cut-[null]', 'beforeinput-deleteByCut', 'input-deleteByCut',
     97        'paste-[null]', 'beforeinput-insertFromPaste', 'input-insertFromPaste'];
     98    const actualEventLog = [];
     99    const text2 = document.getElementById("test2_editable");
    100 
    101    for (let eventType of ['beforeinput', 'input', 'cut', 'paste']) {
    102        text2.addEventListener(eventType, test.step_func(function() {
    103            if (event.type === 'beforeinput' && event.inputType === 'insertFromPaste') {
    104                assert_equals(event.data, null);
    105                assert_equals(event.dataTransfer.getData('text/plain'), 'rich');
    106                assert_regexp_match(event.dataTransfer.getData('text/html'), /<b.*>rich<\/b>$/);
    107            }
    108 
    109            actualEventLog.push(`${event.type}-${event.inputType || '[null]'}`);
    110        }));
    111    }
    112    await selectTextCutAndPaste(text2, text2);
    113    await resolveWhen(() => { return actualEventLog.length == expectedEventLog.length });
    114    assert_array_equals(actualEventLog, expectedEventLog,
    115                        `Expected: ${expectedEventLog}; Actual: ${actualEventLog}.`);
    116 }, 'Event order and dataTransfer on contenteditable.');
    117 
    118 promise_test(async test => {
    119    const prevent = document.getElementById('test3_editable_prevent');
    120    const normal = document.getElementById('test3_editable_normal');
    121    prevent.addEventListener('beforeinput', test.step_func(function() {
    122        if (event.inputType === 'deleteByCut' ||
    123            event.inputType === 'insertFromPaste') {
    124            event.preventDefault();
    125        }
    126    }));
    127 
    128    normal.addEventListener('input', test.step_func(function() {
    129        if (event.inputType === 'insertFromPaste') {
    130            assert_equals(prevent.textContent, 'prevent');
    131            assert_equals(normal.textContent, 'prevent');
    132        }
    133    }));
    134 
    135    await selectTextCommand(prevent, commands.PASTE);
    136    await selectTextCutAndPaste(prevent, normal);
    137    await resolveWhen(() => { return normal.textContent == 'prevent' });
    138    assert_equals(prevent.textContent, 'prevent');
    139    assert_equals(normal.textContent, 'prevent');
    140 }, 'preventDefault() should prevent DOM modification but allow clipboard updates.');
    141 </script>