| <!DOCTYPE html> |
| <meta charset="utf-8"> |
| <title>Cut and Paste should trigger corresponding InputEvent</title> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <p>To manually run this test, please follow the steps below:<br/> |
| 1. Select 'plain' => Cut (e.g. Ctrl/Cmd-X) => Paste (e.g. Ctrl/Cmd-V).<br/> |
| 2. Select 'rich' => Cut => Paste.<br/> |
| 3. Select 'prevent' => Paste.<br/> |
| 4. Select 'prevent' => Cut => Select 'normal' => Paste.<br/> |
| <br/> |
| If a "PASS" result appears the test passes, otherwise it fails</p> |
| <textarea id="test1_plain">plain</textarea> |
| <p id="test2_editable" contenteditable><b>rich</b></p> |
| <p id="test3_editable_prevent" contenteditable>prevent</p> |
| <p id="test3_editable_normal" contenteditable>normal</p> |
| <script> |
| async_test(t => { |
| const expectedEventLog = [ |
| 'cut-[null]', 'beforeinput-deleteByCut', 'input-deleteByCut', |
| 'paste-[null]', 'beforeinput-insertFromPaste', 'input-insertFromPaste']; |
| const actualEventLog = []; |
| |
| for (let eventType of ['beforeinput', 'input', 'cut', 'paste']) { |
| document.getElementById('test1_plain').addEventListener(eventType, t.step_func(event => { |
| if (event.type === 'beforeinput' && event.inputType === 'insertFromPaste') { |
| assert_equals(event.data, 'plain'); |
| assert_equals(event.dataTransfer, null); |
| } |
| |
| actualEventLog.push(`${event.type}-${event.inputType || '[null]'}`); |
| if (actualEventLog.length === expectedEventLog.length) { |
| assert_array_equals(actualEventLog, expectedEventLog, |
| `Expected: ${expectedEventLog}; Actual: ${actualEventLog}.`); |
| t.done(); |
| } |
| })); |
| } |
| }, 'Event order and data on textarea.'); |
| |
| async_test(t => { |
| const expectedEventLog = [ |
| 'cut-[null]', 'beforeinput-deleteByCut', 'input-deleteByCut', |
| 'paste-[null]', 'beforeinput-insertFromPaste', 'input-insertFromPaste']; |
| const actualEventLog = []; |
| |
| for (let eventType of ['beforeinput', 'input', 'cut', 'paste']) { |
| document.getElementById('test2_editable').addEventListener(eventType, t.step_func(event => { |
| if (event.type === 'beforeinput' && event.inputType === 'insertFromPaste') { |
| assert_equals(event.data, null); |
| assert_equals(event.dataTransfer.getData('text/plain'), 'rich'); |
| assert_regexp_match(event.dataTransfer.getData('text/html'), /<b.*>rich<\/b>$/); |
| } |
| |
| actualEventLog.push(`${event.type}-${event.inputType || '[null]'}`); |
| if (actualEventLog.length === expectedEventLog.length) { |
| assert_array_equals(actualEventLog, expectedEventLog, |
| `Expected: ${expectedEventLog}; Actual: ${actualEventLog}.`); |
| t.done(); |
| } |
| })); |
| } |
| }, 'Event order and dataTransfer on contenteditable.'); |
| |
| async_test(t => { |
| const prevent = document.getElementById('test3_editable_prevent'); |
| const normal = document.getElementById('test3_editable_normal'); |
| prevent.addEventListener('beforeinput', t.step_func(event => { |
| if (event.inputType === 'deleteByCut' || |
| event.inputType === 'insertFromPaste') { |
| event.preventDefault(); |
| } |
| })); |
| |
| normal.addEventListener('input', t.step_func(event => { |
| if (event.inputType === 'insertFromPaste') { |
| assert_equals(prevent.textContent, 'prevent'); |
| assert_equals(normal.textContent, 'prevent'); |
| t.done(); |
| } |
| })); |
| }, 'preventDefault() should prevent DOM modification but allow clipboard updates.'); |
| </script> |