From b262d770c961f83af55ac0e0894fadfcba73c179 Mon Sep 17 00:00:00 2001 From: "alexey.kamaev" Date: Wed, 18 Apr 2018 16:08:26 +0300 Subject: [PATCH 1/5] [WIP] process TextInput event on typing (closes #1956) --- .../automation/playback/type/type-text.js | 81 +++++++++----- .../index-test.js | 10 +- .../fixtures/regression/gh-1054/test.js | 3 +- .../regression/gh-1956/pages/index.html | 105 ++++++++++++++++++ .../fixtures/regression/gh-1956/test.js | 63 +++++++++++ .../gh-1956/testcafe-fixtures/index.js | 64 +++++++++++ 6 files changed, 298 insertions(+), 28 deletions(-) create mode 100644 test/functional/fixtures/regression/gh-1956/pages/index.html create mode 100644 test/functional/fixtures/regression/gh-1956/test.js create mode 100644 test/functional/fixtures/regression/gh-1956/testcafe-fixtures/index.js diff --git a/src/client/automation/playback/type/type-text.js b/src/client/automation/playback/type/type-text.js index 1f0d99fad89..67712f611fe 100644 --- a/src/client/automation/playback/type/type-text.js +++ b/src/client/automation/playback/type/type-text.js @@ -64,6 +64,26 @@ function _typeTextInElementNode (elementNode, text, offset) { textSelection.selectByNodesAndOffsets(selectPosition, selectPosition); } +function _typeTextInChildTextNode (element, selection, text) { + let startNode = selection.startPos.node; + + // NOTE: startNode could be moved or deleted on textInput event. Need ensure startNode. + if (!domUtils.isElementContainsNode(element, startNode)) { + selection = _excludeInvisibleSymbolsFromSelection(_getSelectionInElement(element)); + startNode = selection.startPos.node; + } + + const startOffset = selection.startPos.offset; + const endOffset = selection.endPos.offset; + const nodeValue = startNode.nodeValue; + const selectPosition = { node: startNode, offset: startOffset + text.length }; + + startNode.nodeValue = nodeValue.substring(0, startOffset) + text + + nodeValue.substring(endOffset, nodeValue.length); + + textSelection.selectByNodesAndOffsets(selectPosition, selectPosition); +} + function _excludeInvisibleSymbolsFromSelection (selection) { var startNode = selection.startPos.node; var startOffset = selection.startPos.offset; @@ -84,26 +104,44 @@ function _excludeInvisibleSymbolsFromSelection (selection) { return selection; } +// NOTE: typing can be prevented in Chrome/Edge but can not be prevented in IE11 or Firefox +// Firefox does not support TextInput event +// Safari support TextInput event but adds e.data to node value. So let's ignore it +function simulateTextInput (element, text) { + const isTextInputIgnoredByBrowser = [ browserUtils.isFirefox, browserUtils.isSafari ].some(browser => browser); + const isInputEventRequired = isTextInputIgnoredByBrowser || eventSimulator.textInput(element, text); + + return isInputEventRequired || browserUtils.isIE11; +} + function _typeTextToContentEditable (element, text) { - var currentSelection = _getSelectionInElement(element); - var startNode = currentSelection.startPos.node; - var endNode = currentSelection.endPos.node; + var currentSelection = _getSelectionInElement(element); + var startNode = currentSelection.startPos.node; + var endNode = currentSelection.endPos.node; + var needProcessInput = true; + var needRaiseInputEvent = true; // NOTE: some browsers raise the 'input' event after the element // content is changed, but in others we should do it manually. - var inputEventRaised = false; var onInput = () => { - inputEventRaised = true; + needRaiseInputEvent = false; + }; + + // NOTE: IE11 does not raise input event when type to contenteditable + + var beforeContentChanged = () => { + needProcessInput = simulateTextInput(element, text); + needRaiseInputEvent = needProcessInput && !browserUtils.isIE11; }; var afterContentChanged = () => { nextTick() .then(() => { - if (!inputEventRaised) + if (needRaiseInputEvent) eventSimulator.input(element); - listeners.removeInternalEventListener(window, 'input', onInput); + listeners.removeInternalEventListener(window, ['input'], onInput); }); }; @@ -126,27 +164,16 @@ function _typeTextToContentEditable (element, text) { if (!startNode || !domUtils.isContentEditableElement(startNode) || !domUtils.isRenderedNode(startNode)) return; - // NOTE: we can type only to the text nodes; for nodes with the 'element-node' type, we use a special behavior - if (domUtils.isElementNode(startNode)) { - _typeTextInElementNode(startNode, text, currentSelection.startPos.offset); + beforeContentChanged(); - afterContentChanged(); - return; + if (needProcessInput) { + // NOTE: we can type only to the text nodes; for nodes with the 'element-node' type, we use a special behavior + if (domUtils.isElementNode(startNode)) + _typeTextInElementNode(startNode, text); + else + _typeTextInChildTextNode(element, _excludeInvisibleSymbolsFromSelection(currentSelection), text); } - currentSelection = _excludeInvisibleSymbolsFromSelection(currentSelection); - startNode = currentSelection.startPos.node; - - var startOffset = currentSelection.startPos.offset; - var endOffset = currentSelection.endPos.offset; - var nodeValue = startNode.nodeValue; - var selectPosition = { node: startNode, offset: startOffset + text.length }; - - startNode.nodeValue = nodeValue.substring(0, startOffset) + text + - nodeValue.substring(endOffset, nodeValue.length); - - textSelection.selectByNodesAndOffsets(selectPosition, selectPosition); - afterContentChanged(); } @@ -156,6 +183,10 @@ function _typeTextToTextEditable (element, text) { var startSelection = textSelection.getSelectionStart(element); var endSelection = textSelection.getSelectionEnd(element); var isInputTypeNumber = domUtils.isInputElement(element) && element.type === 'number'; + var needProcessInput = simulateTextInput(element, text); + + if (!needProcessInput) + return; // NOTE: the 'maxlength' attribute doesn't work in all browsers. IE still doesn't support input with the 'number' type var elementMaxLength = !browserUtils.isIE && isInputTypeNumber ? null : parseInt(element.maxLength, 10); diff --git a/test/client/fixtures/automation/content-editable/api-actions-content-editable-test/index-test.js b/test/client/fixtures/automation/content-editable/api-actions-content-editable-test/index-test.js index 42a25d3ab26..6bed0f723d1 100644 --- a/test/client/fixtures/automation/content-editable/api-actions-content-editable-test/index-test.js +++ b/test/client/fixtures/automation/content-editable/api-actions-content-editable-test/index-test.js @@ -439,6 +439,9 @@ $(document).ready(function () { var fixedText = 'Test' + String.fromCharCode(160) + 'me' + String.fromCharCode(160) + 'all!'; var inputEventRaisedCount = 0; + // NOTE IE11 does not raise input event on contenteditable element + var expectedInputEventRaisedCount = !browserUtils.isIE11 ? 12 : 0; + $el = $('#2'); function onInput () { @@ -454,7 +457,7 @@ $(document).ready(function () { .then(function () { checkSelection($el, $el[0].childNodes[2], 4 + text.length, $el[0].childNodes[2], 4 + text.length); equal($.trim($el[0].childNodes[2].nodeValue), 'with' + fixedText + ' br'); - equal(inputEventRaisedCount, 12); + equal(inputEventRaisedCount, expectedInputEventRaisedCount); $el.unbind('input', onInput); startNext(); @@ -465,6 +468,9 @@ $(document).ready(function () { var text = 'Test'; var inputEventRaisedCount = 0; + // NOTE IE11 does not raise input event on contenteditable element + var expectedInputEventRaisedCount = !browserUtils.isIE11 ? 4 : 0; + $el = $('#8'); function onInput () { @@ -479,7 +485,7 @@ $(document).ready(function () { .run() .then(function () { equal($.trim($el[0].textContent), text); - equal(inputEventRaisedCount, 4); + equal(inputEventRaisedCount, expectedInputEventRaisedCount); $el.unbind('input', onInput); startNext(); diff --git a/test/functional/fixtures/regression/gh-1054/test.js b/test/functional/fixtures/regression/gh-1054/test.js index 7f65adcb5e6..e1f5fae4af1 100644 --- a/test/functional/fixtures/regression/gh-1054/test.js +++ b/test/functional/fixtures/regression/gh-1054/test.js @@ -4,8 +4,9 @@ describe('[Regression](GH-1054)', function () { return runTests('testcafe-fixtures/index.test.js', 'Type text in the input'); }); + // NOTE: IE11 does not raise Input event on contenteditable element it('Typing in the content editable element with "replace" option', function () { - return runTests('testcafe-fixtures/index.test.js', 'Type text in the content editable element'); + return runTests('testcafe-fixtures/index.test.js', 'Type text in the content editable element', { skip: [ 'ie' ] }); }); }); }); diff --git a/test/functional/fixtures/regression/gh-1956/pages/index.html b/test/functional/fixtures/regression/gh-1956/pages/index.html new file mode 100644 index 00000000000..2af849c902f --- /dev/null +++ b/test/functional/fixtures/regression/gh-1956/pages/index.html @@ -0,0 +1,105 @@ + +Edit test + + + +

Prevent Input event on TextInput when type to input element

+
+        Chrome/Edge. Typing is prevented and Input event is not raised
+        IE11/Firefox. Typing is not prevented. Input event is raised
+    
+ +

Prevent Input event and typing on simple ContentEditable div

+
+        Chrome/Edge. Typing is prevented. Input event is not raised
+        IE11/Firefox. Typing is not prevented.
+        Input event is raised in firefox but is not raised in IE11 - it's a IE11 bug
+    
+
+

Prevent Input event on TextInput event when type to element node

+
+        Not for IE11 because preventDefault will not prevent typing
+        Not for Firefox because Firefox does not support TextInput event
+    
+


+

Modify text node of ContentEditable div on TextInput event and prevent Input event

+
+        Not for IE11 because is's not possible to prevent typing in IE11
+        Not for Firefox because Firefox does not support TextInput event
+    
+

A

+

Type to ContentEditable div when selected node was replaced on TextInput event

+
+        Not for IE11 because this test emulates behavior from https://github.com/DevExpress/testcafe/issues/1956.
+        This behavior is different in IE11
+        Not for Firefox because Firefox does not support TextInput event
+    
+

B

+ + \ No newline at end of file diff --git a/test/functional/fixtures/regression/gh-1956/test.js b/test/functional/fixtures/regression/gh-1956/test.js new file mode 100644 index 00000000000..66325503ece --- /dev/null +++ b/test/functional/fixtures/regression/gh-1956/test.js @@ -0,0 +1,63 @@ +var expect = require('chai').expect; + +var browsersWithLimitations = [ 'ie', 'safari', 'firefox', 'firefox-osx', 'ipad', 'iphone' ]; + +describe('Should support TextInput event[Regression](GH-1956)', function () { + it('Prevent Input event on TextInput when type to input element', function () { + return runTests('testcafe-fixtures/index.js', + 'Prevent Input event on TextInput when type to input element', + { skip: browsersWithLimitations }); + }); + + it('Prevent Input event on TextInput when type to input element IE11/Firefox', function () { + return runTests('testcafe-fixtures/index.js', + 'Prevent Input event on TextInput when type to input element IE11/Firefox', + { only: [ 'ie', 'firefox', 'firefox-osx' ], shouldFail: true }) + .catch(function (errs) { + var errors = [ errs['ie'], errs['firefox'] ].filter(err => err); + + errors.forEach(err => { + expect(err[0]).contains('Input event has raised'); + }); + }); + }); + + it('Prevent Input event on TextInput when type to ContentEditable div', function () { + return runTests('testcafe-fixtures/index.js', + 'Prevent Input event on TextInput when type to ContentEditable div', + { skip: browsersWithLimitations }); + }); + + it('Prevent Input event on TextInput when type to ContentEditable div IE11', function () { + return runTests('testcafe-fixtures/index.js', + 'Prevent Input event on TextInput when type to ContentEditable div IE11/Firefox', + { only: [ 'ie' ] }); + }); + + it('Prevent Input event on TextInput when type to ContentEditable div Firefox', function () { + return runTests('testcafe-fixtures/index.js', + 'Prevent Input event on TextInput when type to ContentEditable div IE11/Firefox', + { only: [ 'firefox', 'firefox-osx' ], shouldFail: true }) + .catch(function (errs) { + expect(errs[0]).contains('Input event has raised'); + }); + }); + + it('Modify text node of ContentEditable div on TextInput event and prevent Input event', function () { + return runTests('testcafe-fixtures/index.js', + 'Modify text node of ContentEditable div on TextInput event and prevent Input event', + { skip: browsersWithLimitations }); + }); + + it('Type to ContentEditable div when selected node was replaced on TextInput event', function () { + return runTests('testcafe-fixtures/index.js', + 'Type to ContentEditable div when selected node was replaced on TextInput event', + { skip: browsersWithLimitations }); + }); + + it('Prevent Input event on TextInput when type to element node', function () { + return runTests('testcafe-fixtures/index.js', + 'Prevent Input event on TextInput when type to element node', + { skip: browsersWithLimitations }); + }); +}); diff --git a/test/functional/fixtures/regression/gh-1956/testcafe-fixtures/index.js b/test/functional/fixtures/regression/gh-1956/testcafe-fixtures/index.js new file mode 100644 index 00000000000..87acf1a0488 --- /dev/null +++ b/test/functional/fixtures/regression/gh-1956/testcafe-fixtures/index.js @@ -0,0 +1,64 @@ +import { Selector } from 'testcafe'; + +fixture('GH-1956 - Should support TextInput event') + .page `http://localhost:3000/fixtures/regression/gh-1956/pages/index.html`; + +const simpleInput = Selector('#simpleInput'); +const simpleContentEditable = Selector('#simpleContentEditable'); +const contentEditableWithElementNode = Selector('#contentEditableWithElementNode'); +const contentEditableWithModify = Selector('#contentEditableWithModify'); +const contentEditableWithReplace = Selector('#contentEditableWithReplace'); + +// NOTE: Chrome/Edge. Typing is prevented and Input event is not raised +test('Prevent Input event on TextInput when type to input element', async t => { + await t + .typeText(simpleInput, 'Hello') + .expect(simpleInput.value).eql(''); +}); + +// NOTE: IE11/Firefox. Typing is not prevented. Input event is raised +test('Prevent Input event on TextInput when type to input element IE11/Firefox', async t => { + await t + .typeText(simpleInput, 'Hello') + .expect(simpleInput.value).eql('Hello'); +}); + +// NOTE: Chrome/Edge. Typing is prevented. Input event is not raised +test('Prevent Input event on TextInput when type to ContentEditable div', async t => { + await t + .typeText(simpleContentEditable, 'Hello') + .expect(simpleContentEditable.textContent).eql(''); +}); + +// NOTE: IE11/Firefox. Typing is not prevented. +// Input event is raised in firefox but is not raised in IE11 - it's a IE11 bug +test('Prevent Input event on TextInput when type to ContentEditable div IE11/Firefox', async t => { + await t + .typeText(simpleContentEditable, 'Hello') + .expect(simpleContentEditable.textContent).eql('Hello'); +}); + +// NOTE: Not for IE11 because preventDefault will not prevent typing +// Not for Firefox because Firefox does not support TextInput event +test('Prevent Input event on TextInput when type to element node', async t => { + await t + .typeText(contentEditableWithElementNode, 'Hello') + .expect(contentEditableWithElementNode.textContent).eql(''); +}); + +// NOTE: Not for IE11 because is's not possible to prevent typing in IE11 +// Not for Firefox because Firefox does not support TextInput event +test('Modify text node of ContentEditable div on TextInput event and prevent Input event', async t => { + await t + .typeText(contentEditableWithModify, 'Hello') + .expect(contentEditableWithModify.textContent).eql('AHello'); +}); + +// NOTE: Not for IE11 because this test emulates behavior from https://github.com/DevExpress/testcafe/issues/1956. +// This behavior is different in IE11 +// Not for Firefox because Firefox does not support TextInput event +test('Type to ContentEditable div when selected node was replaced on TextInput event', async t => { + await t + .typeText(contentEditableWithReplace, 'Hello') + .expect(contentEditableWithReplace.textContent).eql('HelloX'); +}); From 62eaff2ac195ebf3a58fa3e0b6b688d3edb18cce Mon Sep 17 00:00:00 2001 From: "alexey.kamaev" Date: Wed, 25 Apr 2018 10:02:41 +0300 Subject: [PATCH 2/5] fix textInput dispatch in safari --- .../automation/playback/type/type-text.js | 25 ++++++++++++++++--- .../fixtures/regression/gh-1956/test.js | 2 +- .../gh-1956/testcafe-fixtures/index.js | 4 +-- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/client/automation/playback/type/type-text.js b/src/client/automation/playback/type/type-text.js index 67712f611fe..2da6a3555fc 100644 --- a/src/client/automation/playback/type/type-text.js +++ b/src/client/automation/playback/type/type-text.js @@ -104,16 +104,33 @@ function _excludeInvisibleSymbolsFromSelection (selection) { return selection; } -// NOTE: typing can be prevented in Chrome/Edge but can not be prevented in IE11 or Firefox +// NOTE: Typing can be prevented in Chrome/Edge but can not be prevented in IE11 or Firefox // Firefox does not support TextInput event -// Safari support TextInput event but adds e.data to node value. So let's ignore it +// Safari supports the TextInput event but has a bug: e.data is added to the node value. +// So in Safari we need to call preventDefault in the last textInput handler but not prevent the Input event + +let forceInputInSafari; + function simulateTextInput (element, text) { - const isTextInputIgnoredByBrowser = [ browserUtils.isFirefox, browserUtils.isSafari ].some(browser => browser); - const isInputEventRequired = isTextInputIgnoredByBrowser || eventSimulator.textInput(element, text); + forceInputInSafari = false; + + if (browserUtils.isSafari) + document.addEventListener('textInput', onSafariTextInput); + + const isInputEventRequired = browserUtils.isFirefox || eventSimulator.textInput(element, text) || forceInputInSafari; + + if (browserUtils.isSafari) + document.removeEventListener('textInput', onSafariTextInput); return isInputEventRequired || browserUtils.isIE11; } +function onSafariTextInput (e) { + forceInputInSafari = !e.defaultPrevented; + + e.preventDefault(); +} + function _typeTextToContentEditable (element, text) { var currentSelection = _getSelectionInElement(element); var startNode = currentSelection.startPos.node; diff --git a/test/functional/fixtures/regression/gh-1956/test.js b/test/functional/fixtures/regression/gh-1956/test.js index 66325503ece..97616caa660 100644 --- a/test/functional/fixtures/regression/gh-1956/test.js +++ b/test/functional/fixtures/regression/gh-1956/test.js @@ -1,6 +1,6 @@ var expect = require('chai').expect; -var browsersWithLimitations = [ 'ie', 'safari', 'firefox', 'firefox-osx', 'ipad', 'iphone' ]; +var browsersWithLimitations = [ 'ie', 'firefox', 'firefox-osx' ]; describe('Should support TextInput event[Regression](GH-1956)', function () { it('Prevent Input event on TextInput when type to input element', function () { diff --git a/test/functional/fixtures/regression/gh-1956/testcafe-fixtures/index.js b/test/functional/fixtures/regression/gh-1956/testcafe-fixtures/index.js index 87acf1a0488..3fad6c6d841 100644 --- a/test/functional/fixtures/regression/gh-1956/testcafe-fixtures/index.js +++ b/test/functional/fixtures/regression/gh-1956/testcafe-fixtures/index.js @@ -9,7 +9,7 @@ const contentEditableWithElementNode = Selector('#contentEditableWithElementNode const contentEditableWithModify = Selector('#contentEditableWithModify'); const contentEditableWithReplace = Selector('#contentEditableWithReplace'); -// NOTE: Chrome/Edge. Typing is prevented and Input event is not raised +// NOTE: Chrome/Edge/Safari. Typing is prevented and Input event is not raised test('Prevent Input event on TextInput when type to input element', async t => { await t .typeText(simpleInput, 'Hello') @@ -23,7 +23,7 @@ test('Prevent Input event on TextInput when type to input element IE11/Firefox', .expect(simpleInput.value).eql('Hello'); }); -// NOTE: Chrome/Edge. Typing is prevented. Input event is not raised +// NOTE: Chrome/Edge/Safari. Typing is prevented. Input event is not raised test('Prevent Input event on TextInput when type to ContentEditable div', async t => { await t .typeText(simpleContentEditable, 'Hello') From b09447013f5c1e9f58fa8d0a7df790d10607fead Mon Sep 17 00:00:00 2001 From: "alexey.kamaev" Date: Thu, 26 Apr 2018 16:06:10 +0300 Subject: [PATCH 3/5] fix textInput dispatch in safari --- .../automation/playback/type/type-text.js | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/client/automation/playback/type/type-text.js b/src/client/automation/playback/type/type-text.js index 2da6a3555fc..cd779857b5e 100644 --- a/src/client/automation/playback/type/type-text.js +++ b/src/client/automation/playback/type/type-text.js @@ -3,6 +3,7 @@ import testCafeCore from '../../deps/testcafe-core'; import nextTick from '../../utils/next-tick'; var browserUtils = hammerhead.utils.browser; +var eventSandbox = hammerhead.sandbox.event; var eventSimulator = hammerhead.eventSandbox.eventSimulator; var listeners = hammerhead.eventSandbox.listeners; @@ -112,23 +113,30 @@ function _excludeInvisibleSymbolsFromSelection (selection) { let forceInputInSafari; function simulateTextInput (element, text) { - forceInputInSafari = false; - - if (browserUtils.isSafari) - document.addEventListener('textInput', onSafariTextInput); + if (browserUtils.isSafari) { + listeners.addInternalEventListener(window, ['textInput'], onSafariTextInput); + eventSandbox.on(eventSandbox.EVENT_PREVENTED_EVENT, onSafariPreventTextInput); + } const isInputEventRequired = browserUtils.isFirefox || eventSimulator.textInput(element, text) || forceInputInSafari; - if (browserUtils.isSafari) - document.removeEventListener('textInput', onSafariTextInput); + if (browserUtils.isSafari) { + listeners.removeInternalEventListener(window, ['textInput'], onSafariTextInput); + eventSandbox.off(eventSandbox.EVENT_PREVENTED_EVENT, onSafariPreventTextInput); + } return isInputEventRequired || browserUtils.isIE11; } function onSafariTextInput (e) { - forceInputInSafari = !e.defaultPrevented; - e.preventDefault(); + + forceInputInSafari = true; +} + +function onSafariPreventTextInput (e) { + if (e.type === 'textInput') + forceInputInSafari = false; } function _typeTextToContentEditable (element, text) { From 18279800388d259bf22f197c2310b5c666e02965 Mon Sep 17 00:00:00 2001 From: "alexey.kamaev" Date: Tue, 8 May 2018 11:59:37 +0300 Subject: [PATCH 4/5] fix review remarks --- .../automation/playback/type/type-text.js | 32 +++--- .../index-test.js | 2 +- .../fixtures/regression/gh-1054/test.js | 3 +- .../gh-1054/testcafe-fixtures/index.test.js | 8 +- .../regression/gh-1956/pages/index.html | 97 +++++++++---------- .../gh-1956/testcafe-fixtures/index.js | 8 +- 6 files changed, 75 insertions(+), 75 deletions(-) diff --git a/src/client/automation/playback/type/type-text.js b/src/client/automation/playback/type/type-text.js index cd779857b5e..4da58ca14bf 100644 --- a/src/client/automation/playback/type/type-text.js +++ b/src/client/automation/playback/type/type-text.js @@ -106,13 +106,24 @@ function _excludeInvisibleSymbolsFromSelection (selection) { } // NOTE: Typing can be prevented in Chrome/Edge but can not be prevented in IE11 or Firefox -// Firefox does not support TextInput event -// Safari supports the TextInput event but has a bug: e.data is added to the node value. -// So in Safari we need to call preventDefault in the last textInput handler but not prevent the Input event - -let forceInputInSafari; +// Firefox does not support TextInput event +// Safari supports the TextInput event but has a bug: e.data is added to the node value. +// So in Safari we need to call preventDefault in the last textInput handler but not prevent the Input event function simulateTextInput (element, text) { + let forceInputInSafari; + + function onSafariTextInput (e) { + e.preventDefault(); + + forceInputInSafari = true; + } + + function onSafariPreventTextInput (e) { + if (e.type === 'textInput') + forceInputInSafari = false; + } + if (browserUtils.isSafari) { listeners.addInternalEventListener(window, ['textInput'], onSafariTextInput); eventSandbox.on(eventSandbox.EVENT_PREVENTED_EVENT, onSafariPreventTextInput); @@ -128,17 +139,6 @@ function simulateTextInput (element, text) { return isInputEventRequired || browserUtils.isIE11; } -function onSafariTextInput (e) { - e.preventDefault(); - - forceInputInSafari = true; -} - -function onSafariPreventTextInput (e) { - if (e.type === 'textInput') - forceInputInSafari = false; -} - function _typeTextToContentEditable (element, text) { var currentSelection = _getSelectionInElement(element); var startNode = currentSelection.startPos.node; diff --git a/test/client/fixtures/automation/content-editable/api-actions-content-editable-test/index-test.js b/test/client/fixtures/automation/content-editable/api-actions-content-editable-test/index-test.js index 6bed0f723d1..6592c5f01dd 100644 --- a/test/client/fixtures/automation/content-editable/api-actions-content-editable-test/index-test.js +++ b/test/client/fixtures/automation/content-editable/api-actions-content-editable-test/index-test.js @@ -440,7 +440,7 @@ $(document).ready(function () { var inputEventRaisedCount = 0; // NOTE IE11 does not raise input event on contenteditable element - var expectedInputEventRaisedCount = !browserUtils.isIE11 ? 12 : 0; + var expectedInputEventRaisedCount = browserUtils.isIE11 ? 0 : 12; $el = $('#2'); diff --git a/test/functional/fixtures/regression/gh-1054/test.js b/test/functional/fixtures/regression/gh-1054/test.js index e1f5fae4af1..7f65adcb5e6 100644 --- a/test/functional/fixtures/regression/gh-1054/test.js +++ b/test/functional/fixtures/regression/gh-1054/test.js @@ -4,9 +4,8 @@ describe('[Regression](GH-1054)', function () { return runTests('testcafe-fixtures/index.test.js', 'Type text in the input'); }); - // NOTE: IE11 does not raise Input event on contenteditable element it('Typing in the content editable element with "replace" option', function () { - return runTests('testcafe-fixtures/index.test.js', 'Type text in the content editable element', { skip: [ 'ie' ] }); + return runTests('testcafe-fixtures/index.test.js', 'Type text in the content editable element'); }); }); }); diff --git a/test/functional/fixtures/regression/gh-1054/testcafe-fixtures/index.test.js b/test/functional/fixtures/regression/gh-1054/testcafe-fixtures/index.test.js index 1500059d8a0..dc7d4c16384 100644 --- a/test/functional/fixtures/regression/gh-1054/testcafe-fixtures/index.test.js +++ b/test/functional/fixtures/regression/gh-1054/testcafe-fixtures/index.test.js @@ -1,10 +1,12 @@ import { ClientFunction, Selector } from 'testcafe'; +import bowser from 'bowser'; fixture `Check the target element value when the first input event raised` .page('http://localhost:3000/fixtures/regression/gh-1054/pages/index.html'); const getFirstValue = ClientFunction(() => window.storedValue); +const getUserAgent = ClientFunction(() => navigator.userAgent); test('Type text in the input', async t => { await t @@ -19,5 +21,9 @@ test('Type text in the content editable element', async t => { .typeText('div', 'text', { replace: true }) .expect(Selector('div').textContent).eql('text'); - await t.expect(await getFirstValue()).eql('t'); + var userAgent = await getUserAgent(); + var isIE = bowser._detect(userAgent).msie; + + if (!isIE) + await t.expect(await getFirstValue()).eql('t'); }); diff --git a/test/functional/fixtures/regression/gh-1956/pages/index.html b/test/functional/fixtures/regression/gh-1956/pages/index.html index 2af849c902f..f903cbbd489 100644 --- a/test/functional/fixtures/regression/gh-1956/pages/index.html +++ b/test/functional/fixtures/regression/gh-1956/pages/index.html @@ -9,14 +9,51 @@ min-height: 10px; } + +

Prevent Input event on TextInput when type to input element

+
+        Chrome/Edge. Typing is prevented and Input event is not raised
+        IE11/Firefox. Typing is not prevented. Input event is raised
+    
+ +

Prevent Input event and typing on simple ContentEditable div

+
+        Chrome/Edge. Typing is prevented. Input event is not raised
+        IE11/Firefox. Typing is not prevented.
+        Input event is raised in firefox but is not raised in IE11 - it's a IE11 bug
+    
+
+

Prevent Input event on TextInput event when type to element node

+
+        Not for IE11 because preventDefault will not prevent typing
+        Not for Firefox because Firefox does not support TextInput event
+    
+


+

Modify text node of ContentEditable div on TextInput event and prevent Input event

+
+        Not for IE11 because is's not possible to prevent typing in IE11
+        Not for Firefox because Firefox does not support TextInput event
+    
+

A

+

Type to ContentEditable div when selected node was replaced on TextInput event

+
+        Not for IE11 because this test emulates behavior from https://github.com/DevExpress/testcafe/issues/1956.
+        This behavior is different in IE11
+        Not for Firefox because Firefox does not support TextInput event
+    
+

B

+ - -

Prevent Input event on TextInput when type to input element

-
-        Chrome/Edge. Typing is prevented and Input event is not raised
-        IE11/Firefox. Typing is not prevented. Input event is raised
-    
- -

Prevent Input event and typing on simple ContentEditable div

-
-        Chrome/Edge. Typing is prevented. Input event is not raised
-        IE11/Firefox. Typing is not prevented.
-        Input event is raised in firefox but is not raised in IE11 - it's a IE11 bug
-    
-
-

Prevent Input event on TextInput event when type to element node

-
-        Not for IE11 because preventDefault will not prevent typing
-        Not for Firefox because Firefox does not support TextInput event
-    
-


-

Modify text node of ContentEditable div on TextInput event and prevent Input event

-
-        Not for IE11 because is's not possible to prevent typing in IE11
-        Not for Firefox because Firefox does not support TextInput event
-    
-

A

-

Type to ContentEditable div when selected node was replaced on TextInput event

-
-        Not for IE11 because this test emulates behavior from https://github.com/DevExpress/testcafe/issues/1956.
-        This behavior is different in IE11
-        Not for Firefox because Firefox does not support TextInput event
-    
-

B

- \ No newline at end of file diff --git a/test/functional/fixtures/regression/gh-1956/testcafe-fixtures/index.js b/test/functional/fixtures/regression/gh-1956/testcafe-fixtures/index.js index 3fad6c6d841..32d86c7f6ef 100644 --- a/test/functional/fixtures/regression/gh-1956/testcafe-fixtures/index.js +++ b/test/functional/fixtures/regression/gh-1956/testcafe-fixtures/index.js @@ -39,7 +39,7 @@ test('Prevent Input event on TextInput when type to ContentEditable div IE11/Fir }); // NOTE: Not for IE11 because preventDefault will not prevent typing -// Not for Firefox because Firefox does not support TextInput event +// Not for Firefox because Firefox does not support TextInput event test('Prevent Input event on TextInput when type to element node', async t => { await t .typeText(contentEditableWithElementNode, 'Hello') @@ -47,7 +47,7 @@ test('Prevent Input event on TextInput when type to element node', async t => { }); // NOTE: Not for IE11 because is's not possible to prevent typing in IE11 -// Not for Firefox because Firefox does not support TextInput event +// Not for Firefox because Firefox does not support TextInput event test('Modify text node of ContentEditable div on TextInput event and prevent Input event', async t => { await t .typeText(contentEditableWithModify, 'Hello') @@ -55,8 +55,8 @@ test('Modify text node of ContentEditable div on TextInput event and prevent Inp }); // NOTE: Not for IE11 because this test emulates behavior from https://github.com/DevExpress/testcafe/issues/1956. -// This behavior is different in IE11 -// Not for Firefox because Firefox does not support TextInput event +// This behavior is different in IE11 +// Not for Firefox because Firefox does not support TextInput event test('Type to ContentEditable div when selected node was replaced on TextInput event', async t => { await t .typeText(contentEditableWithReplace, 'Hello') From 7186e62ea070d7e922e41f93977533c8f4a027c5 Mon Sep 17 00:00:00 2001 From: "alexey.kamaev" Date: Tue, 8 May 2018 17:20:35 +0300 Subject: [PATCH 5/5] fix user agent module --- .../regression/gh-1054/testcafe-fixtures/index.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/functional/fixtures/regression/gh-1054/testcafe-fixtures/index.test.js b/test/functional/fixtures/regression/gh-1054/testcafe-fixtures/index.test.js index dc7d4c16384..8e78ce69072 100644 --- a/test/functional/fixtures/regression/gh-1054/testcafe-fixtures/index.test.js +++ b/test/functional/fixtures/regression/gh-1054/testcafe-fixtures/index.test.js @@ -1,5 +1,5 @@ import { ClientFunction, Selector } from 'testcafe'; -import bowser from 'bowser'; +import userAgent from 'useragent'; fixture `Check the target element value when the first input event raised` .page('http://localhost:3000/fixtures/regression/gh-1054/pages/index.html'); @@ -21,8 +21,8 @@ test('Type text in the content editable element', async t => { .typeText('div', 'text', { replace: true }) .expect(Selector('div').textContent).eql('text'); - var userAgent = await getUserAgent(); - var isIE = bowser._detect(userAgent).msie; + var userAgentStr = await getUserAgent(); + var isIE = userAgent.is(userAgentStr).ie; if (!isIE) await t.expect(await getFirstValue()).eql('t');