diff options
Diffstat (limited to 'testing/web-platform/tests/input-events/input-events-typing.html')
-rw-r--r-- | testing/web-platform/tests/input-events/input-events-typing.html | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/testing/web-platform/tests/input-events/input-events-typing.html b/testing/web-platform/tests/input-events/input-events-typing.html new file mode 100644 index 0000000000..a894beea9b --- /dev/null +++ b/testing/web-platform/tests/input-events/input-events-typing.html @@ -0,0 +1,285 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Input Event typing tests</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/resources/testdriver-actions.js"></script> +<div id="rich" contenteditable></div> +<textarea id="plain"></textarea> +<script> +let inputEventsLog = []; +const rich = document.getElementById('rich'); +const plain = document.getElementById('plain'); + +function log(event) { + const clone = new event.constructor(event.type, event); + clone.state = rich.innerHTML; + inputEventsLog.push(clone); +} + +function resetRich() { + inputEventsLog = []; + rich.innerHTML = ''; +} + +rich.addEventListener('beforeinput', log); +rich.addEventListener('input', log); + +promise_test(async function() { + this.add_cleanup(resetRich); + rich.focus(); + const message = 'Hello'; + await test_driver.send_keys(rich, message); + // 10 events (5 beforeinput + 5 input events) + assert_equals(inputEventsLog.length, 10); + for (let i = 0; i < inputEventsLog.length; i += 2) { + const beforeInputEvent = inputEventsLog[i]; + const inputEvent = inputEventsLog[i + 1]; + assert_equals(beforeInputEvent.type, 'beforeinput'); + assert_equals(inputEvent.type, 'input'); + assert_equals(beforeInputEvent.inputType, 'insertText'); + assert_equals(inputEvent.inputType, 'insertText'); + assert_equals(beforeInputEvent.data, inputEvent.data); + assert_equals(inputEvent.data, message[i / 2]); + assert_equals(beforeInputEvent.state + message[i / 2], inputEvent.state); + } +}, 'It triggers beforeinput and input events on text typing'); + +promise_test(async function() { + this.add_cleanup(resetRich); + rich.focus(); + await test_driver.send_keys(rich, "\uE006"); // Return + + assert_equals(inputEventsLog.length, 2); + const beforeInputEvent = inputEventsLog[0]; + const inputEvent = inputEventsLog[1]; + assert_equals(beforeInputEvent.type, 'beforeinput'); + assert_equals(inputEvent.type, 'input'); + assert_equals(beforeInputEvent.inputType, 'insertParagraph'); + assert_equals(inputEvent.inputType, 'insertParagraph'); + assert_equals(beforeInputEvent.data, inputEvent.data); +}, 'It triggers beforeinput and input events on typing RETURN'); + +promise_test(async function() { + this.add_cleanup(resetRich); + rich.focus(); + await new test_driver.Actions() + .keyDown('\uE008') // Shift + .keyDown('\uE006') // Return + .keyUp('\uE006') + .keyUp('\uE008') + .send(); + + assert_equals(inputEventsLog.length, 2); + const [beforeInputEvent, inputEvent] = inputEventsLog; + assert_equals(beforeInputEvent.type, 'beforeinput'); + assert_equals(inputEvent.type, 'input'); + assert_equals(beforeInputEvent.inputType, 'insertLineBreak'); + assert_equals(inputEvent.inputType, 'insertLineBreak'); + assert_equals(beforeInputEvent.data, inputEvent.data); +}, 'It triggers beforeinput and input events on typing Shift+RETURN'); + +promise_test(async function() { + this.add_cleanup(resetRich); + rich.innerHTML = '<p>Preexisting <i id="caret">c</i>ontent</p>'; + const caret = document.querySelector('#caret'); + await test_driver.click(caret); + await test_driver.send_keys(caret, "\uE017"); // Delete + + assert_equals(inputEventsLog.length, 2); + const [beforeInputEvent, inputEvent] = inputEventsLog; + assert_equals(beforeInputEvent.type, 'beforeinput'); + assert_equals(inputEvent.type, 'input'); + assert_equals(beforeInputEvent.inputType, 'deleteContentForward'); + assert_equals(inputEvent.inputType, 'deleteContentForward'); + assert_equals(beforeInputEvent.data, inputEvent.data); +}, 'It triggers beforeinput and input events on typing DELETE with pre-existing content'); + +promise_test(async function() { + this.add_cleanup(resetRich); + rich.focus(); + await test_driver.send_keys(rich, "\uE017"); // Delete + assert_equals(inputEventsLog.length, 2); + const [beforeInputEvent, inputEvent] = inputEventsLog; + assert_equals(beforeInputEvent.type, 'beforeinput'); + assert_equals(inputEvent.type, 'input'); + assert_equals(beforeInputEvent.inputType, 'deleteContentForward'); + assert_equals(inputEvent.inputType, 'deleteContentForward'); + assert_equals(beforeInputEvent.data, inputEvent.data); +}, 'It triggers beforeinput and input events on typing DELETE with no pre-existing content'); + +promise_test(async function() { + this.add_cleanup(resetRich); + rich.innerHTML = '<p>Preexisting <i id="caret">c</i>ontent</p>'; + + await test_driver.click(document.querySelector('#caret')); + await test_driver.send_keys(rich, "\uE003"); // Back Space + + assert_equals(inputEventsLog.length, 2); + const [beforeInputEvent, inputEvent] = inputEventsLog; + assert_equals(beforeInputEvent.type, 'beforeinput'); + assert_equals(inputEvent.type, 'input'); + assert_equals(beforeInputEvent.inputType, 'deleteContentBackward'); + assert_equals(inputEvent.inputType, 'deleteContentBackward'); + assert_equals(beforeInputEvent.data, inputEvent.data); +}, 'It triggers beforeinput and input events on typing BACK_SPACE with pre-existing content'); + +promise_test(async function() { + this.add_cleanup(resetRich); + rich.focus(); + await test_driver.send_keys(rich, "\uE003"); // Back Space + + assert_equals(inputEventsLog.length, 2); + const [beforeInputEvent, inputEvent] = inputEventsLog; + assert_equals(beforeInputEvent.type, 'beforeinput'); + assert_equals(inputEvent.type, 'input'); + assert_equals(beforeInputEvent.inputType, 'deleteContentBackward'); + assert_equals(inputEvent.inputType, 'deleteContentBackward'); + assert_equals(beforeInputEvent.data, inputEvent.data); +}, 'It triggers beforeinput and input events on typing BACK_SPACE with no pre-existing content'); + +promise_test(async function() { + this.add_cleanup(resetRich); + rich.focus(); + await test_driver.send_keys(rich, "hello"); + + // Decide whether to use Key.COMMAND (mac) or Key.CONTROL (everything else) + const modifierKey = navigator.platform === "MacIntel" ? '\u2318' : '\uE009'; + + // Undo + await new test_driver.Actions() + .keyDown(modifierKey) + .keyDown('z') + .keyUp('z') + .keyUp(modifierKey) + .send(); + // Redo + await new test_driver.Actions() + .keyDown(modifierKey) + .keyDown('\uE008') // Shift + .keyDown('z') + .keyUp('z') + .keyUp('\uE008') + .keyUp(modifierKey) + .send(); + + // Ignore the initial typing of 'hello' + const historyInputEventsLog = inputEventsLog.slice(10); + + assert_equals(historyInputEventsLog.length, 4); + const inputTypes = ['historyUndo', 'historyRedo']; + for (let i = 0; i < historyInputEventsLog.length; i += 2) { + // We are increaisng i by 2 as there should always be matching beforeinput and input events. + const beforeInputEvent = historyInputEventsLog[i]; + const inputEvent = historyInputEventsLog[i + 1]; + assert_equals(beforeInputEvent.type, 'beforeinput'); + assert_equals(inputEvent.type, 'input'); + assert_equals(beforeInputEvent.inputType, inputTypes[i / 2]); + assert_equals(inputEvent.inputType, inputTypes[i / 2]); + assert_equals(beforeInputEvent.data, inputEvent.data); + } +}, 'It triggers beforeinput and input events on typing Undo and Redo key combinations with an existing history'); + +promise_test(async function() { + this.add_cleanup(resetRich); + rich.focus(); + // Decide whether to use Key.COMMAND (mac) or Key.CONTROL (everything else) + const modifierKey = navigator.platform === "MacIntel" ? '\u2318' : '\uE009'; + + // Undo + await new test_driver.Actions() + .keyDown(modifierKey) + .keyDown('z') + .keyUp('z') + .keyUp(modifierKey) + .send(); + // Redo + await new test_driver.Actions() + .keyDown(modifierKey) + .keyDown('\uE008') // Shift + .keyDown('z') + .keyUp('z') + .keyUp('\uE008') + .keyUp(modifierKey) + .send(); + + assert_equals(inputEventsLog.length, 4); + const inputTypes = ['historyUndo', 'historyRedo']; + for (let i = 0; i < inputEventsLog.length; i += 2) { + const beforeInputEvent = inputEventsLog[i]; + const inputEvent = inputEventsLog[i + 1]; + assert_equals(beforeInputEvent.type, 'beforeinput'); + assert_equals(inputEvent.type, 'input'); + assert_equals(beforeInputEvent.inputType, inputTypes[i / 2]); + assert_equals(inputEvent.inputType, inputTypes[i / 2]); + assert_equals(beforeInputEvent.data, inputEvent.data); + } +}, 'It triggers beforeinput and input events on typing Undo and Redo key combinations without an existing history'); + +promise_test(async function() { + this.add_cleanup(resetRich); + const expectedResult = [ + // Pressing 'a'. + 'plain-keydown-a', + 'plain-keypress-a', + 'plain-beforeinput-a-null', + 'plain-input-a-null', + 'plain-keyup-a', + // Pressing Shift-'b'. + 'plain-keydown-B', + 'plain-keypress-B', + 'plain-beforeinput-B-null', + 'plain-input-B-null', + 'plain-keyup-B', + // Pressing 'c'. + 'rich-keydown-c', + 'rich-keypress-c', + 'rich-beforeinput-c-null', + 'rich-input-c-null', + 'rich-keyup-c', + // Pressing Shift-'d'. + 'rich-keydown-D', + 'rich-keypress-D', + 'rich-beforeinput-D-null', + 'rich-input-D-null', + 'rich-keyup-D', + ]; + const result = []; + + for (const eventType of ['beforeinput', 'input', 'keydown', 'keypress', 'keyup']) { + const listener = event => { + if (event.key === 'Shift') return; + const eventInfo = [event.target.id, event.type, event.data || event.key]; + if (event instanceof InputEvent) eventInfo.push(String(event.dataTransfer)); + result.push(eventInfo.join('-')); + } + rich.addEventListener(eventType, listener); + plain.addEventListener(eventType, listener); + } + + plain.focus(); + await new test_driver.Actions() + .keyDown('a') + .keyUp('a') + .keyDown('\uE008') // Shift + .keyDown('b') + .keyUp('b') + .keyUp('\uE008') + .send(); + + rich.focus(); + await new test_driver.Actions() + .keyDown('c') + .keyUp('c') + .keyDown('\uE008') // Shift + .keyDown('d') + .keyUp('d') + .keyUp('\uE008') + .send(); + + assert_equals(expectedResult.length, result.length); + expectedResult.forEach((er, index) => assert_equals(er, result[index])); +}, 'InputEvents have correct data/order when typing on textarea and contenteditable'); +</script> |