diff options
Diffstat (limited to 'testing/web-platform/tests/uievents')
12 files changed, 315 insertions, 0 deletions
diff --git a/testing/web-platform/tests/uievents/idlharness.window.js b/testing/web-platform/tests/uievents/idlharness.window.js index c3919e3558..ca8d23e4f6 100644 --- a/testing/web-platform/tests/uievents/idlharness.window.js +++ b/testing/web-platform/tests/uievents/idlharness.window.js @@ -16,6 +16,7 @@ idl_test( CompositionEvent: ['new CompositionEvent("event")'], UIEvent: ['new UIEvent("event")'], InputEvent: ['new InputEvent("event")'], + TextEvent: ['(() => { const ev = document.createEvent("TextEvent"); ev.initTextEvent("event"); return ev; })()'], }); } ); diff --git a/testing/web-platform/tests/uievents/textInput/api.html b/testing/web-platform/tests/uievents/textInput/api.html new file mode 100644 index 0000000000..a88184e500 --- /dev/null +++ b/testing/web-platform/tests/uievents/textInput/api.html @@ -0,0 +1,88 @@ +<!doctype html> +<meta charset=utf-8> +<title>textInput: API</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<input class=test-el> +<textarea class=test-el></textarea> +<div contenteditable class=test-el></div> +<script src="support/common.js"></script> +<script> +test(() => { + assert_throws_js(TypeError, () => { + new TextEvent('textInput'); + }); +}, "No constructor"); + +test(() => { + const e = document.createEvent('TextEvent'); + assert_equals(Object.getPrototypeOf(e), window.TextEvent.prototype); + assert_equals(Object.getPrototypeOf(Object.getPrototypeOf(e)), window.UIEvent.prototype); + assert_equals(Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(e))), window.Event.prototype); +}, "document.CreateEvent('TextEvent') prototype chain"); + +test(() => { + const e = document.createEvent('TextEvent'); + assert_throws_js(TypeError, () => { e.initTextEvent(); }); +}, "initTextEvent() no arguments"); + +test(() => { + const e = document.createEvent('TextEvent'); + e.initTextEvent('foo'); + assert_equals(e.type, 'foo'); + assert_equals(e.bubbles, false); + assert_equals(e.cancelable, false); + assert_equals(e.view, null); + assert_equals(e.data, 'undefined'); +}, "initTextEvent('foo')"); + +test(() => { + const e = document.createEvent('TextEvent'); + e.initTextEvent('foo', true, true, window, 'bar'); + assert_equals(e.type, 'foo'); + assert_equals(e.bubbles, true); + assert_equals(e.cancelable, true); + assert_equals(e.view, window); + assert_equals(e.data, 'bar'); +}, "initTextEvent('foo', true, true, window, 'bar')"); + +test(() => { + const div = document.createElement('div'); + let textinputCount = 0; + let textInputCount = 0; + div.addEventListener('textinput', e => { + assert_equals(e.type, 'textinput'); + textinputCount++; + }); + div.addEventListener('textInput', e => { + assert_equals(e.type, 'textInput'); + textInputCount++; + }); + const textinputEvent = document.createEvent('TextEvent'); + textinputEvent.initTextEvent('textinput'); + div.dispatchEvent(textinputEvent); + + const textInputEvent = document.createEvent('TextEvent'); + textInputEvent.initTextEvent('textInput'); + div.dispatchEvent(textInputEvent); + + assert_equals(textinputCount, 1); + assert_equals(textInputCount, 1); +}, "case sensitivity: textInput vs textinput"); + +const els = document.querySelectorAll('.test-el'); +for (const el of els) { + promise_test(t => { + return new Promise((resolve, reject) => { + el.addEventListener('textInput', reject); + el.addEventListener('input', t.step_func(e => { + const actualValue = 'value' in el ? el.value : el.textContent; + assert_equals(actualValue, 'a'); + resolve(); + })); + el.focus(); + document.execCommand('insertText', false, 'a'); + }); + }, `execCommand('insertText', false, 'a'), ${elDesc(el)}` ); +} +</script> diff --git a/testing/web-platform/tests/uievents/textInput/backspace.html b/testing/web-platform/tests/uievents/textInput/backspace.html new file mode 100644 index 0000000000..c9b2f8bee4 --- /dev/null +++ b/testing/web-platform/tests/uievents/textInput/backspace.html @@ -0,0 +1,16 @@ +<!doctype html> +<meta charset=utf-8> +<title>textInput: backspace</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> +<style> +[contenteditable] { border: thin inset silver; } +</style> +<p>Press Backspace in each text field below.</p> +<input class=test-el value=abc> +<textarea class=test-el>abc</textarea> +<div contenteditable=true class=test-el>abc</div> +<script src="support/common.js"></script> +<script src="support/no-textInput.sub.js?key=Backspace&selectionStart=2&selectionEnd=2&expectedValue=ac"></script> diff --git a/testing/web-platform/tests/uievents/textInput/basic.html b/testing/web-platform/tests/uievents/textInput/basic.html new file mode 100644 index 0000000000..6335167faa --- /dev/null +++ b/testing/web-platform/tests/uievents/textInput/basic.html @@ -0,0 +1,16 @@ +<!doctype html> +<meta charset=utf-8> +<title>textInput: basic</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> +<style> +[contenteditable] { border: thin inset silver; } +</style> +<p>Type "a" into each text field below.</p> +<input class=test-el> +<textarea class=test-el></textarea> +<div contenteditable=true class=test-el></div> +<script src="support/common.js"></script> +<script src="support/basic.sub.js?key=a&selectionStart=0&selectionEnd=0&expectedValue=a"></script> diff --git a/testing/web-platform/tests/uievents/textInput/delete-selection.html b/testing/web-platform/tests/uievents/textInput/delete-selection.html new file mode 100644 index 0000000000..f77e8c6e98 --- /dev/null +++ b/testing/web-platform/tests/uievents/textInput/delete-selection.html @@ -0,0 +1,16 @@ +<!doctype html> +<meta charset=utf-8> +<title>textInput: delete selection</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> +<style> +[contenteditable] { border: thin inset silver; } +</style> +<p>Press Delete (Fn+Backspace for macOS) in each text field below.</p> +<input class=test-el value=abc> +<textarea class=test-el>abc</textarea> +<div contenteditable=true class=test-el>abc</div> +<script src="support/common.js"></script> +<script src="support/no-textInput.sub.js?key=Delete&selectionStart=1&selectionEnd=2&expectedValue=ac"></script> diff --git a/testing/web-platform/tests/uievents/textInput/delete.html b/testing/web-platform/tests/uievents/textInput/delete.html new file mode 100644 index 0000000000..2d696fba71 --- /dev/null +++ b/testing/web-platform/tests/uievents/textInput/delete.html @@ -0,0 +1,16 @@ +<!doctype html> +<meta charset=utf-8> +<title>textInput: delete</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> +<style> +[contenteditable] { border: thin inset silver; } +</style> +<p>Press Delete (Fn+Backspace for macOS) in each text field below.</p> +<input class=test-el value=abc> +<textarea class=test-el>abc</textarea> +<div contenteditable=true class=test-el>abc</div> +<script src="support/common.js"></script> +<script src="support/no-textInput.sub.js?key=Delete&selectionStart=1&selectionEnd=1&expectedValue=ac"></script> diff --git a/testing/web-platform/tests/uievents/textInput/enter-input.html b/testing/web-platform/tests/uievents/textInput/enter-input.html new file mode 100644 index 0000000000..032503694d --- /dev/null +++ b/testing/web-platform/tests/uievents/textInput/enter-input.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset=utf-8> +<title>textInput: Enter key for input element</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> +<style> +[contenteditable] { border: thin inset silver; } +</style> +<p>Press Enter in the text field below.</p> +<input class=test-el> +<script src="support/common.js"></script> +<script src="support/no-textInput.sub.js?key=Enter&selectionStart=0&selectionEnd=0&expectedValue="></script> diff --git a/testing/web-platform/tests/uievents/textInput/enter-textarea-contenteditable.html b/testing/web-platform/tests/uievents/textInput/enter-textarea-contenteditable.html new file mode 100644 index 0000000000..60891df982 --- /dev/null +++ b/testing/web-platform/tests/uievents/textInput/enter-textarea-contenteditable.html @@ -0,0 +1,15 @@ +<!doctype html> +<meta charset=utf-8> +<title>textInput: Enter key for textarea and contenteditable</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> +<style> +[contenteditable] { border: thin inset silver; } +</style> +<p>Press Enter in each text field below.</p> +<textarea class=test-el></textarea> +<div contenteditable=true class=test-el></div> +<script src="support/common.js"></script> +<script src="support/basic.sub.js?key=Enter&selectionStart=0&selectionEnd=0&expectedValue=\n"></script> diff --git a/testing/web-platform/tests/uievents/textInput/smiley-manual.html b/testing/web-platform/tests/uievents/textInput/smiley-manual.html new file mode 100644 index 0000000000..7781f6e1b0 --- /dev/null +++ b/testing/web-platform/tests/uievents/textInput/smiley-manual.html @@ -0,0 +1,17 @@ +<!doctype html> +<meta charset=utf-8> +<title>textInput: smiley (manual)</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> +[contenteditable] { border: thin inset silver; } +</style> +<p>Type "🙂" into each text field below.</p> +<input class=test-el> +<textarea class=test-el></textarea> +<div contenteditable=true class=test-el></div> +<script> +setup({ explicit_timeout: true }); +</script> +<script src="support/common.js"></script> +<script src="support/basic.sub.js?key=🙂&selectionStart=0&selectionEnd=0&expectedValue=🙂"></script> diff --git a/testing/web-platform/tests/uievents/textInput/support/basic.sub.js b/testing/web-platform/tests/uievents/textInput/support/basic.sub.js new file mode 100644 index 0000000000..55d2f0d1e6 --- /dev/null +++ b/testing/web-platform/tests/uievents/textInput/support/basic.sub.js @@ -0,0 +1,49 @@ +const els = document.querySelectorAll('.test-el'); +const key = "{{GET[key]}}"; +const keyRaw = keyMapping[key] || key; +const expectedData = key === "Enter" ? "\n" : key; +const selectionStart = {{GET[selectionStart]}}; +const selectionEnd = {{GET[selectionEnd]}}; +const expectedValue = "{{GET[expectedValue]}}"; + +for (const el of els) { + promise_test(t => { + return new Promise((resolve, reject) => { + let beforeinputEvents = 0; + let textInputEvents = 0; + el.addEventListener('beforeinput', t.step_func(e => { + beforeinputEvents++; + })); + el.addEventListener('textInput', t.step_func(e => { + textInputEvents++; + assert_equals(beforeinputEvents, 1); + assert_equals(e.data, expectedData); + assert_true(e.bubbles); + assert_true(e.cancelable); + assert_equals(e.view, window); + assert_equals(e.detail, 0); + assert_true(e instanceof window.TextEvent); + })); + el.addEventListener('input', t.step_func(e => { + assert_equals(textInputEvents, 1); + if (expectedValue === "\n" && !(el instanceof HTMLInputElement) && !(el instanceof HTMLTextAreaElement)) { + // New paragraph in contenteditable during editing is weird. + // innerHTML is <div><br></div><div><br></div> + // ...but later changes to <br> + // So, check that there's at least one <br>. + assert_true(getValue(el).indexOf('<br>') > -1); + } else { + assert_equals(getValue(el), expectedValue); + } + resolve(); + })); + el.onfocus = t.step_func(e => { + if (window.test_driver) { + test_driver.send_keys(el, keyRaw); + } + }); + el.focus(); + setSelection(el, selectionStart, selectionEnd); + }); + }, `${document.title}, ${elDesc(el)}`); +} diff --git a/testing/web-platform/tests/uievents/textInput/support/common.js b/testing/web-platform/tests/uievents/textInput/support/common.js new file mode 100644 index 0000000000..25c39da3e2 --- /dev/null +++ b/testing/web-platform/tests/uievents/textInput/support/common.js @@ -0,0 +1,38 @@ +function elDesc(el) { + let rv = `<${el.localName}`; + if (el.hasAttribute('contenteditable')) { + rv += ` contenteditable="${el.getAttribute('contenteditable')}"`; + } + if (el.hasAttribute('type')) { + rv += ` type="${el.getAttribute('type')}"`; + } + rv += `>`; + return rv; +} + +function setSelection(el, selectionStart, selectionEnd) { + if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) { + el.selectionStart = selectionStart; + el.selectionEnd = selectionEnd; + } else { + const s = getSelection(); + s.removeAllRanges(); + const r = new Range(); + r.setStart(el.firstChild || el, selectionStart); + r.setEnd(el.firstChild || el, selectionEnd); + s.addRange(r); + } +} + +function getValue(el) { + if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) { + return el.value; + } + return el.innerHTML; +} + +const keyMapping = { + "Enter": "\uE006", + "Backspace": "\uE003", + "Delete": "\uE017", +}; diff --git a/testing/web-platform/tests/uievents/textInput/support/no-textInput.sub.js b/testing/web-platform/tests/uievents/textInput/support/no-textInput.sub.js new file mode 100644 index 0000000000..332cbf08f2 --- /dev/null +++ b/testing/web-platform/tests/uievents/textInput/support/no-textInput.sub.js @@ -0,0 +1,29 @@ +const els = document.querySelectorAll('.test-el'); +const key = "{{GET[key]}}"; +const keyRaw = keyMapping[key] || key; +const expectedData = key === "Enter" ? "\n" : key; +const selectionStart = {{GET[selectionStart]}}; +const selectionEnd = {{GET[selectionEnd]}}; +const expectedValue = "{{GET[expectedValue]}}"; + +for (const el of els) { + promise_test(t => { + return new Promise((resolve, reject) => { + el.addEventListener('textInput', reject); + el.addEventListener('keyup', t.step_func(e => { + if (e.key !== key) { + return; + } + assert_equals(getValue(el), expectedValue); + resolve(); + })); + el.onfocus = t.step_func(e => { + if (window.test_driver) { + test_driver.send_keys(el, keyRaw); + } + }); + el.focus(); + setSelection(el, selectionStart, selectionEnd); + }); + }, `${document.title}, ${elDesc(el)}`); +} |