Commit bf62d746 authored by Julian Kung's avatar Julian Kung Committed by Commit Bot

[ChromeDriver] Element Send Keys: support content editable; fix text input type

The email input type being considered a text input caused bugs and crashes.
In this commit it is removed from textControlTypes and thus no longer
considered a text input.

Also added support for content editable
elements in compliance with the following W3C procedure:
"Set the text insertion caret after any child content."
Added test to run_py_test to test correct functionality.

R=crouleau@chromium.org, johnchen@chromium.org

Bug: chromedriver:2704
Change-Id: I95bb9ff2396aa0e6bdfa35dde33f338be83607b7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1658966
Commit-Queue: Julian Kung <juliankung@google.com>
Reviewed-by: default avatarJohn Chen <johnchen@chromium.org>
Reviewed-by: default avatarCaleb Rouleau <crouleau@chromium.org>
Cr-Commit-Position: refs/heads/master@{#669828}
parent a918b221
......@@ -32,8 +32,8 @@
#include "third_party/webdriver/atoms.h"
const int kFlickTouchEventsPerSecond = 30;
const std::set<std::string> textControlTypes = {"text", "search", "tel",
"url", "email", "password"};
const std::set<std::string> textControlTypes = {"text", "search", "tel", "url",
"password"};
namespace {
......@@ -92,8 +92,8 @@ Status SendKeysToElement(Session* session,
Status status = FocusToElement(session, web_view, element_id);
if (status.IsError())
return Status(kElementNotInteractable);
// Move cursor/caret to append the input keys if element's type is
// text-related
// Move cursor/caret to append the input
// keys if element's type is text-related
if (is_text) {
base::ListValue args;
args.Append(CreateElement(element_id));
......@@ -441,6 +441,46 @@ Status ExecuteSendKeysToElement(Session* session,
return web_view->SetFileInputFiles(session->GetCurrentFrameId(), *element,
paths, multiple);
} else {
std::unique_ptr<base::Value> get_content_editable;
base::ListValue args;
args.Append(CreateElement(element_id));
status = web_view->CallFunction(session->GetCurrentFrameId(),
"element => element.isContentEditable",
args, &get_content_editable);
if (status.IsError())
return status;
bool is_content_editable;
if (get_content_editable->GetAsBoolean(&is_content_editable) &&
is_content_editable) {
// If element is contentEditable, will move caret
// at end of element text. W3C mandates that the
// caret be moved "after any child content"
std::unique_ptr<base::Value> result;
status = web_view->CallFunction(
session->GetCurrentFrameId(),
"function(element) {"
"var range = document.createRange();"
"range.selectNodeContents(element);"
"range.collapse();"
"var sel = window.getSelection();"
"sel.removeAllRanges();"
"sel.addRange(range);"
"while (element.parentElement.isContentEditable) {"
" element = element.parentElement;"
" }"
"return element;"
"}",
args, &result);
if (status.IsError())
return status;
const base::DictionaryValue* element_dict;
std::string target_element_id;
if (!result->GetAsDictionary(&element_dict) ||
!element_dict->GetString(GetElementKey(), &target_element_id))
return Status(kUnknownError, "no element reference returned by script");
return SendKeysToElement(session, web_view, target_element_id, false,
key_list);
}
// If element_type is in textControlTypes, sendKeys should append
bool is_text = is_input && textControlTypes.find(element_type) !=
textControlTypes.end();
......
......@@ -1963,18 +1963,46 @@ class ChromeDriverW3cTest(ChromeDriverBaseTestWithWebServer):
self.assertEquals('0123456789+-*/ Hi, there!', value)
def testSendKeysToElementAppend(self):
self._driver.Load(self.GetHttpUrlForFile(
'/chromedriver/empty.html'))
textControlTypes = ["text", "search", "tel", "url", "password"]
for textType in textControlTypes:
element = self._driver.ExecuteScript(
'document.body.innerHTML = '
'\'<input type="{}" value="send_this_value">\';'
'var input = document.getElementsByTagName("input")[0];'
'input.focus();'
'input.setSelectionRange(0,0);'
'return input;'.format(textType))
element.SendKeys('hello')
value = self._driver.ExecuteScript('return arguments[0].value;',
element)
self.assertEquals('send_this_valuehello', value)
def testSendKeysToEditableElement(self):
self._driver.Load(self.GetHttpUrlForFile(
'/chromedriver/empty.html'))
element = self._driver.ExecuteScript(
'document.body.innerHTML = '
'\'<p contentEditable="true"> <i>hello-></i> '
'<b>send_this_value </b> </p>\';'
'var input = document.getElementsByTagName("i")[0];'
'input.focus();'
'return input;')
element.SendKeys('hello')
self.assertEquals(u'hello->hello', element.GetText())
self._driver.Load(self.GetHttpUrlForFile(
'/chromedriver/empty.html'))
element = self._driver.ExecuteScript(
'document.body.innerHTML = '
'\'<input type="text" value="send_this_value">\';'
'var input = document.getElementsByTagName("input")[0];'
'\'<p contentEditable="true"> <i>hello</i> '
'<b>-></b> </p>\';'
'var input = document.getElementsByTagName("p")[0];'
'input.focus();'
'input.setSelectionRange(0,0);'
'return input;')
element.SendKeys('hello')
value = self._driver.ExecuteScript('return arguments[0].value;', element)
self.assertEquals('send_this_valuehello', value)
self.assertEquals(u'hello ->hello', element.GetText())
def testUnexpectedAlertOpenExceptionMessage(self):
self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
......
......@@ -924,7 +924,6 @@ crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/stress
crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/bubbling.py>>test_spin_event_loop [ Failure ]
crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state[realmSetting2-denied] [ Failure ]
crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/content_editable.py>>test_sets_insertion_point_to_after_last_text_node [ Failure ]
crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_session/create_alwaysMatch.py>>test_valid[pageLoadStrategy-eager] [ Failure ]
crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_invalid_parameters[parameters7] [ Failure ]
......@@ -952,7 +951,6 @@ crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/set_window_rect/set.py>>
crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/scroll_into_view.py>>test_option_stays_outside_of_scrollable_viewport [ Failure ]
crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state[realmSetting1-granted] [ Failure ]
crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[META-expected11] [ Failure ]
crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/content_editable.py>>test_sets_insertion_point_to_end [ Failure ]
crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_invalid_parameters[parameters0] [ Failure ]
crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_accept_and_notify[capabilities0-alert] [ Failure ]
crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_special_keys.py>>test_codepoint_keys_behave_correctly[\u1100\u1161\u11a8] [ Failure ]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment