diff options
author | nirnimesh@chromium.org <nirnimesh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-10 18:42:41 +0000 |
---|---|---|
committer | nirnimesh@chromium.org <nirnimesh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-10 18:42:41 +0000 |
commit | b2c39e9d909e9f9c59d738f51ccac700edaf30ad (patch) | |
tree | 9e86ccdf0288a3edbf0328fa8127f893d47aa2a8 /chrome | |
parent | 251c93e2a820da9d291f20ac2154140c2d382798 (diff) | |
download | chromium_src-b2c39e9d909e9f9c59d738f51ccac700edaf30ad.zip chromium_src-b2c39e9d909e9f9c59d738f51ccac700edaf30ad.tar.gz chromium_src-b2c39e9d909e9f9c59d738f51ccac700edaf30ad.tar.bz2 |
Revert 117005 - Added page objects for various content settings pages and generalized tests for specefic exceptions pages.
Broke all pyauto bots.
BUG=102892
TEST=none
Review URL: http://codereview.chromium.org/8477041
TBR=dyu@chromium.org
Review URL: http://codereview.chromium.org/9167018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@117059 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/test/data/geolocation/geolocation_on_load.html | 17 | ||||
-rw-r--r-- | chrome/test/functional/PYAUTO_TESTS | 9 | ||||
-rwxr-xr-x | chrome/test/functional/prefs.py | 189 | ||||
-rw-r--r-- | chrome/test/functional/webdriver_pages/settings.py | 281 |
4 files changed, 71 insertions, 425 deletions
diff --git a/chrome/test/data/geolocation/geolocation_on_load.html b/chrome/test/data/geolocation/geolocation_on_load.html index 69b0bb5..f646a34a0 100644 --- a/chrome/test/data/geolocation/geolocation_on_load.html +++ b/chrome/test/data/geolocation/geolocation_on_load.html @@ -5,9 +5,9 @@ <title>Show Geolocation on page load</title> <script> -function triggerGeo(onSuccess, onError) { +function triggerGeo() { if (navigator.geolocation) { - navigator.geolocation.getCurrentPosition(onSuccess, onError); + navigator.geolocation.getCurrentPosition(showPosition, onError); } else { document.getElementById('lat').innerHTML = 'Error: navigator.geolocation is false'; @@ -15,15 +15,6 @@ function triggerGeo(onSuccess, onError) { } } - -function triggerGeoWithCallback(callback){ - triggerGeo(function (position){ - callback("allow"); - }, function(positionError){ - callback("block"); - }); -} - function showPosition(position) { var lat = position.coords.latitude; var lng = position.coords.longitude; @@ -31,7 +22,7 @@ function showPosition(position) { document.getElementById('lng').innerHTML = lng; } -function showError(positionError) { +function onError(positionError) { document.getElementById('lat').innerHTML = positionError.message; document.getElementById('lng').innerHTML = ''; @@ -40,7 +31,7 @@ function showError(positionError) { </script> </head> -<body onload="triggerGeo(showPosition, showError)"> +<body onload="triggerGeo()"> <b id=lat>-1</b>, <b id=lng>-1</b> </body> diff --git a/chrome/test/functional/PYAUTO_TESTS b/chrome/test/functional/PYAUTO_TESTS index f8f37b3..c12cc98 100644 --- a/chrome/test/functional/PYAUTO_TESTS +++ b/chrome/test/functional/PYAUTO_TESTS @@ -117,7 +117,6 @@ '-nacl_sdk.NaClSDKTest.testVerifyNaClPlugin', # crbug.com/105560 '-notifications', - '-prefs.PrefsTest.testAllowSelectedGeoTracking', ], 'win': [ @@ -355,14 +354,6 @@ '-notifications.NotificationsTest.testOriginPrefsNotSavedInIncognito', # crbug.com/103379 '-policy.PolicyTest.testDisable3DAPIs', - # Chrome driver does not work in Chrome OS. - '-prefs.PrefsTest.testDenySelectedGeoTracking', - '-prefs.PrefsTest.testCancelSelectedGeoTracking', - '-prefs.PrefsTest.testBlockAllGeoTracking', - '-prefs.PrefsTest.testAllowAllGeoTracking', - '-prefs.PrefsTest.testAddNewException', - '-prefs.PrefsTest.testChangeExceptionBehavior', - '-prefs.PrefsTest.testDeleteException', ], }, diff --git a/chrome/test/functional/prefs.py b/chrome/test/functional/prefs.py index 65d3ab8..738758d 100755 --- a/chrome/test/functional/prefs.py +++ b/chrome/test/functional/prefs.py @@ -6,20 +6,16 @@ import logging import os import shutil -import time +import sys import pyauto_functional # Must be imported before pyauto import pyauto -from webdriver_pages import settings -from webdriver_pages.settings import Behaviors, ContentTypes +import test_utils + class PrefsTest(pyauto.PyUITest): """TestCase for Preferences.""" - def setUp(self): - pyauto.PyUITest.setUp(self) - self.driver = self.NewWebDriver() - def Debug(self): """Test method for experimentation. @@ -31,21 +27,35 @@ class PrefsTest(pyauto.PyUITest): def testSessionRestore(self): """Test session restore preference.""" + + pref_url = 'chrome://settings/browser' url1 = 'http://www.google.com/' url2 = 'http://news.google.com/' + + self.NavigateToURL(pref_url) + # Set pref to restore session on startup. + driver = self.NewWebDriver() + restore_elem = driver.find_element_by_xpath( + '//input[@metric="Options_Startup_LastSession"]') + restore_elem.click() + self.assertTrue(restore_elem.is_selected()) + self.RestartBrowser(clear_profile=False) self.NavigateToURL(url1) self.AppendTab(pyauto.GURL(url2)) num_tabs = self.GetTabCount() - # Set pref to restore session on startup. - self.SetPrefs(pyauto.kRestoreOnStartup, 1) - logging.debug('Setting %s to 1' % pyauto.kRestoreOnStartup) self.RestartBrowser(clear_profile=False) + # Verify tabs are properly restored. self.assertEqual(self.GetPrefsInfo().Prefs(pyauto.kRestoreOnStartup), 1) self.assertEqual(num_tabs, self.GetTabCount()) self.ActivateTab(0) self.assertEqual(url1, self.GetActiveTabURL().spec()) self.ActivateTab(1) self.assertEqual(url2, self.GetActiveTabURL().spec()) + # Verify session restore option is still selected. + self.NavigateToURL(pref_url, 0, 0) + driver = self.NewWebDriver() + self.assertTrue(driver.find_element_by_xpath( + '//input[@metric="Options_Startup_LastSession"]').is_selected()) def testNavigationStateOnSessionRestore(self): """Verify navigation state is preserved on session restore.""" @@ -148,6 +158,10 @@ class PrefsTest(pyauto.PyUITest): Checks for the geolocation infobar. """ + # Fails on Win7 Chromium bot only. crbug.com/89000 + if (self.IsWin7() and + self.GetBrowserInfo()['properties']['branding'] == 'Chromium'): + return url = self.GetFileURLForPath(os.path.join( # triggers geolocation self.DataDir(), 'geolocation', 'geolocation_on_load.html')) self.assertEqual(3, # default state @@ -163,160 +177,6 @@ class PrefsTest(pyauto.PyUITest): self.assertTrue(self.WaitForInfobarCount(0)) self.assertFalse(self.GetBrowserInfo()['windows'][0]['tabs'][0]['infobars']) - def _SetContentSettingsDefaultBehavior(self, content_type, option): - """Set the Content Settings default behavior. - - Args: - content_type: The string content type to manage. - option: The string option allow, deny or ask. - """ - page = settings.ContentSettingsPage.FromNavigation(self.driver) - page.SetContentTypeOption(content_type, option) - - def _VerifyContentException(self, content_type, hostname_pattern, behavior): - """Find hostname pattern and behavior on content Exceptions page. - - Args: - content_type: The string content type to manage. - hostname_pattern: The URL or pattern associated with the behavior. - behavior: The exception to allow or block the hostname. - """ - page = settings.ManageExceptionsPage.FromNavigation( - self.driver, content_type) - self.assertTrue(page.GetExceptions().has_key(hostname_pattern), - msg=('No displayed host name matches pattern "%s"' - % hostname_pattern)) - self.assertEqual(behavior, page.GetExceptions()[hostname_pattern], - msg=('Displayed behavior "%s" does not match behavior "%s"' - % (page.GetExceptions()[hostname_pattern], behavior))) - - def _VerifyDismissInfobar(self, content_type): - """Verify only Ask line entry is shown when Infobar is dismissed. - - Args: - content_type: The string content type to manage. - """ - page = settings.ManageExceptionsPage.FromNavigation( - self.driver, content_type) - self.assertEqual(0, len(page.GetExceptions())) - - def _GetGeolocationTestPageURL(self): - """Get the HTML test page for geolocation.""" - return self.GetFileURLForDataPath('geolocation', 'geolocation_on_load.html') - - def _GetGeolocationTestPageHttpURL(self): - """Get HTML test page for geolocation served by the local http server.""" - return self.GetHttpURLForDataPath('geolocation', 'geolocation_on_load.html') - - def testBlockAllGeoTracking(self): - """Verify web page is blocked when blocking tracking of all sites.""" - self._SetContentSettingsDefaultBehavior( - ContentTypes.GEOLOCATION, Behaviors.BLOCK) - self.NavigateToURL(self._GetGeolocationTestPageHttpURL()) - self.assertFalse(self.GetBrowserInfo()['windows'][0]['tabs'][0]['infobars']) - self.driver.set_script_timeout(10) - # Call the js function, which returns whether geolocation is blocked. - behavior = self.driver.execute_async_script( - 'triggerGeoWithCallback(arguments[arguments.length - 1]);') - self.assertEqual( - behavior, Behaviors.BLOCK, - msg='Blocking tracking of all sites was not set') - - def testAllowAllGeoTracking(self): - """Verify that infobar does not appear when allowing all sites to track.""" - self._SetContentSettingsDefaultBehavior( - ContentTypes.GEOLOCATION, Behaviors.ALLOW) # Allow all sites to track. - self.NavigateToURL(self._GetGeolocationTestPageHttpURL()) - self.assertFalse(self.GetBrowserInfo()['windows'][0]['tabs'][0]['infobars']) - self.driver.set_script_timeout(10) - # Call the js function, which returns whether geolocation is blocked. - behavior = self.driver.execute_async_script( - 'triggerGeoWithCallback(arguments[arguments.length - 1]);') - self.assertEqual( - behavior, Behaviors.ALLOW, - msg='Allowing tracking of all sites was not set') - - def testAllowSelectedGeoTracking(self): - """Verify location prefs to allow selected sites to track location.""" - self._SetContentSettingsDefaultBehavior( - ContentTypes.GEOLOCATION, Behaviors.ASK) - self.NavigateToURL(self._GetGeolocationTestPageHttpURL()) - self.assertTrue(self.WaitForInfobarCount(1)) - self.assertTrue(self.GetBrowserInfo()['windows'][0]['tabs'][0]['infobars']) - self.PerformActionOnInfobar('accept', infobar_index=0) - # Allow selected hosts. - self._VerifyContentException( - ContentTypes.GEOLOCATION, - # Get the hostname pattern (e.g. http://127.0.0.1:57622). - '/'.join(self.GetHttpURLForDataPath('').split('/')[0:3]), - Behaviors.ALLOW) - - def testDenySelectedGeoTracking(self): - """Verify location prefs to deny selected sites to track location.""" - self._SetContentSettingsDefaultBehavior( - ContentTypes.GEOLOCATION, Behaviors.ASK) - self.NavigateToURL(self._GetGeolocationTestPageHttpURL()) - self.assertTrue(self.WaitForInfobarCount(1)) - self.assertTrue(self.GetBrowserInfo()['windows'][0]['tabs'][0]['infobars']) - self.PerformActionOnInfobar('cancel', infobar_index=0) - # Block selected hosts. - self._VerifyContentException( - ContentTypes.GEOLOCATION, - # Get the hostname pattern (e.g. http://127.0.0.1:57622). - '/'.join(self.GetHttpURLForDataPath('').split('/')[0:3]), - Behaviors.BLOCK) - - def testCancelSelectedGeoTracking(self): - """Verify infobar canceled for sites to track location.""" - self._SetContentSettingsDefaultBehavior( - ContentTypes.GEOLOCATION, Behaviors.ASK) - self.NavigateToURL(self._GetGeolocationTestPageURL()) - self.assertTrue(self.WaitForInfobarCount(1)) - self.assertTrue(self.GetBrowserInfo()['windows'][0]['tabs'][0]['infobars']) - self.PerformActionOnInfobar('dismiss', infobar_index=0) - self._VerifyDismissInfobar(ContentTypes.GEOLOCATION) - - def testAddNewException(self): - """Verify new exception added for hostname pattern and behavior.""" - content_type = ContentTypes.PLUGINS - page = settings.ManageExceptionsPage.FromNavigation( - self.driver, content_type) - - pattern, behavior = ('bing.com', Behaviors.BLOCK) - page.AddNewException(pattern, behavior) - self.assertEqual(page.GetExceptions()[pattern], Behaviors.BLOCK, - msg='The behavior "%s" was not added for pattern "%s"' - % (behavior, pattern)) - - def testChangeExceptionBehavior(self): - """Verify behavior for hostname pattern is changed.""" - content_type = ContentTypes.PLUGINS - page = settings.ManageExceptionsPage.FromNavigation( - self.driver, content_type) - - pattern, behavior = ('bing.com', Behaviors.BLOCK) - page.AddNewException(pattern, behavior) - new_behavior = Behaviors.ALLOW - page.SetBehaviorForPattern(pattern, new_behavior) - self.assertEqual(page.GetExceptions()[pattern], Behaviors.ALLOW, - msg='The behavior for "%s" did not change: "%s"' - % (pattern, behavior)) - - def testDeleteException(self): - """Verify exception deleted for hostname pattern and behavior.""" - content_type = ContentTypes.PLUGINS - page = settings.ManageExceptionsPage.FromNavigation( - self.driver, content_type) - - pattern, behavior = ('bing.com', Behaviors.BLOCK) - page.AddNewException(pattern, behavior) - self.assertEqual(page.GetExceptions()[pattern], Behaviors.BLOCK, - msg='The behavior "%s" was not added for pattern "%s"' - % (behavior, pattern)) - page.DeleteException(pattern) - self.assertEqual(page.GetExceptions().get(pattern, KeyError), KeyError, - msg='Pattern "%s" was not deleted' % pattern) - def testUnderTheHoodPref(self): """Verify the security preferences for Under the Hood. The setting is enabled by default.""" @@ -333,6 +193,7 @@ class PrefsTest(pyauto.PyUITest): def testJavaScriptEnableDisable(self): """Verify enabling disabling javascript prefs work """ + self.assertTrue( self.GetPrefsInfo().Prefs(pyauto.kWebKitGlobalJavascriptEnabled)) url = self.GetFileURLForDataPath( diff --git a/chrome/test/functional/webdriver_pages/settings.py b/chrome/test/functional/webdriver_pages/settings.py index 3b78f4d..e733bf6 100644 --- a/chrome/test/functional/webdriver_pages/settings.py +++ b/chrome/test/functional/webdriver_pages/settings.py @@ -8,49 +8,6 @@ import selenium.common.exceptions from selenium.webdriver.common.action_chains import ActionChains -def _FocusField(driver, list_elem, field_elem): - """Focuses a field in a dynamic list. - - Note, the item containing the field should not be focused already. - - Typing into a field is tricky because the js automatically focuses and - selects the text field after 50ms after it first receives focus. This - method focuses the field and waits for the timeout to occur. - For more info, see inline_editable_list.js and search for setTimeout. - See crbug.com/97369. - - Args: - list_elem: An element in the HTML list. - field_elem: An element in the HTML text field. - - Raises: - RuntimeError: If a timeout occurs when waiting for the focus event. - """ - # To wait properly for the focus, we focus the last text field, and then - # add a focus listener to it, so that we return when the element is focused - # again after the timeout. We have to focus a different element in between - # these steps, otherwise the focus event will not fire since the element - # already has focus. - # Ideally this should be fixed in the page. - - correct_focus_script = """ - (function(listElem, itemElem, callback) { - if (document.activeElement == itemElem) { - callback(); - return; - } - itemElem.focus(); - listElem.focus(); - itemElem.addEventListener("focus", callback); - }).apply(null, arguments); - """ - driver.set_script_timeout(5) - try: - driver.execute_async_script(correct_focus_script, list_elem, field_elem) - except selenium.common.exceptions.TimeoutException: - raise RuntimeError('Unable to focus list item ' + field_elem) - - class DynamicList(object): """A web element that holds a dynamic list of items. @@ -94,41 +51,11 @@ class DynamicList(object): """The item to be added must have the same number of fields as an item in the HTML list. Given item '%s' should have %s fields.""" % ( item, len(fields)) - _FocusField(self.driver, self.elem, fields[0]) + self._FocusField(fields[0]) for field, value in zip(fields, values)[1:-1]: field.send_keys(value + '\t') fields[-1].send_keys(values[-1] + '\n') - def Remove(self, item): - """Removes all item occurrences from the list. - - Args: - item: The item to remove from the list. - """ - # There's no close button for the last field. - fields = self._GetPlaceholderElem().find_elements_by_tag_name('input') - if len(fields) > 1: - assert type(item) == types.ListType, \ - """The item must be a list for a HTML list that has multi-field - items. '%s' should be in a list.""" % item - values = item - else: - values = [item] - - assert len(fields) == len(values), \ - """The item to be added must have the same number of fields as an item - in the HTML list. Given item '%s' should have %d fields.""" % ( - item, len(fields)) - - item_list = self.GetCommittedItems() - close_button_list = self.elem.find_elements_by_class_name( - 'close-button')[:-1] - for i in range(len(item_list)): - if item_list[i] == item: - # Highlight the item, so the close button shows up, then click it. - ActionChains(self.driver).move_to_element( - close_button_list[i]).click().perform() - def RemoveAll(self): """Removes all items from the list.""" # There's no close button for the last field. @@ -155,6 +82,47 @@ class DynamicList(object): """Returns the number of items in the list, excluding the placeholder.""" return len(self._GetCommittedItemElems()) + def _FocusField(self, field): + """Focuses a field in the list. + + Note, the item containing the field should not be focused already. + + Typing into a field is tricky because the js automatically focuses and + selects the text field after 50ms after it first receives focus. This + method focuses the field and waits for the timeout to occur. + For more info, see inline_editable_list.js and search for setTimeout. + See crbug.com/97369. + + Args: + field: HTML text field to focus. + + Raises: + RuntimeError: A timeout occurred when waiting for the focus event. + """ + # To wait properly for the focus, we focus the last text field, and then + # add a focus listener to it, so that we return when the element is focused + # again after the timeout. We have to focus a different element in between + # these steps, otherwise the focus event will not fire since the element + # already has focus. + # Ideally this should be fixed in the page. + + correct_focus_script = """ + (function(listElem, itemElem, callback) { + if (document.activeElement == itemElem) { + callback(); + return; + } + itemElem.focus(); + listElem.focus(); + itemElem.addEventListener("focus", callback); + }).apply(null, arguments); + """ + self.driver.set_script_timeout(5) + try: + self.driver.execute_async_script(correct_focus_script, self.elem, field) + except selenium.common.exceptions.TimeoutException: + raise RuntimeError('Unable to focus list item' + value) + def _GetCommittedItemElems(self): return self._GetItemElems()[:-1] @@ -257,168 +225,3 @@ class AutofillEditAddressDialog(object): list = DynamicList( self.driver, self.dialog_elem.find_element_by_id('phone-list')) return list.GetCommittedItems() - - -class ContentTypes(object): - COOKIES = 'cookies' - IMAGES = 'images' - JAVASCRIPT = 'javascript' - HANDLERS = 'handlers' - PLUGINS = 'plugins' - POPUPS = 'popups' - GEOLOCATION = 'location' - NOTIFICATIONS = 'notifications' - - -class Behaviors(object): - ALLOW = 'allow' - SESSION_ONLY = 'session_only' - ASK = 'ask' - BLOCK = 'block' - - -class ContentSettingsPage(object): - """The overlay for managing exceptions on the Content Settings page.""" - - _URL = 'chrome://settings/content' - - @staticmethod - def FromNavigation(driver): - """Creates an instance of the dialog by navigating directly to it.""" - driver.get(ContentSettingsPage._URL) - return ContentSettingsPage(driver) - - def __init__(self, driver): - assert self._URL == driver.current_url - self.page_elem = driver.find_element_by_id( - 'content-settings-page') - - def SetContentTypeOption(self, content_type, option): - """Set the option for the specified content type. - - Args: - content_type: The content type to manage. - option: The option to allow, deny or ask. - """ - self.page_elem.find_element_by_xpath( - './/*[@name="%s"][@value="%s"]' % (content_type, option)).click() - - -class ManageExceptionsPage(object): - """The overlay for the content exceptions page.""" - - @staticmethod - def FromNavigation(driver, content_type): - """Creates an instance of the dialog by navigating directly to it. - - Args: - driver: The remote WebDriver instance to manage some content type. - content_type: The content type to manage. - """ - content_url = 'chrome://settings/contentExceptions#%s' % content_type - driver.get(content_url) - return ManageExceptionsPage(driver, content_type) - - def __init__(self, driver, content_type): - content_url = 'chrome://settings/contentExceptions#%s' % content_type - assert content_url == driver.current_url - self._list_elem = driver.find_element_by_xpath( - './/*[@id="content-settings-exceptions-area"]' \ - '//*[@contenttype="%s"]//list[@role="listbox"]' \ - '[@class="settings-list"]' % content_type) - self._driver = driver - self._content_type = content_type - - def _GetExceptionList(self): - return DynamicList(self._driver, self._list_elem) - - def _GetPatternList(self): - pattern_list = [p.text for p in - self._list_elem.find_elements_by_xpath( - './/*[contains(@class, "exception-pattern")]' - '//*[@class="static-text"]')] - return pattern_list - - def AddNewException(self, pattern, behavior): - """Add a new pattern and behavior to the Exceptions page. - - Args: - pattern: Hostname pattern string. - behavior: Setting for the hostname pattern (Allow, Block, Session Only). - - Raises: - AssertionError when an exception cannot be added on the content page. - """ - # Select behavior first. - try: - self._list_elem.find_element_by_xpath( - './/*[@class="exception-setting"]' - '[not(@displaymode)]//option[@value="%s"]' - % behavior).click() - except selenium.common.exceptions.NoSuchElementException: - raise AssertionError( - 'Adding new exception not allowed in "%s" content page' - % self._content_type) - # Set pattern now. - self._GetExceptionList().Add(pattern) - - def DeleteException(self, pattern): - """Delete the exception for the selected hostname pattern. - - Args: - pattern: Hostname pattern string. - """ - self._GetExceptionList().Remove(pattern) - - def GetExceptions(self): - """Returns a dictionary of {pattern: behavior}. - - Example: {'file:///*': 'block'} - """ - pattern_list = self._GetPatternList() - behavior_list = self._list_elem.find_elements_by_xpath( - './/*[@role="listitem"][@class="deletable-item"]' \ - '//*[@class="exception-setting"][@displaymode="static"]') - assert len(pattern_list) == len(behavior_list), \ - 'Number of patterns does not match the behaviors.' - return dict(zip(pattern_list, [b.text.lower() for b in behavior_list])) - - def GetBehaviorForPattern(self, pattern): - """Returns the behavior for a given pattern on the Exceptions page. - - Args: - pattern: Hostname pattern string. - """ - assert self.GetExceptions().has_key(pattern), \ - 'No displayed host name matches pattern "%s"' % pattern - return self.GetExceptions()[pattern] - - def SetBehaviorForPattern(self, pattern, behavior): - """Set the behavior for the selected pattern on the Exceptions page. - - Args: - pattern: Hostname pattern string. - behavior: Setting for the hostname pattern (Allow, Block, Session Only). - - Raises: - AssertionError when the behavior cannot be changed on the content page. - """ - pattern_list = self._GetPatternList() - listitem_list = self._list_elem.find_elements_by_xpath( - './/*[@role="listitem"][@class="deletable-item"]') - pattern_listitem_dict = dict(zip(pattern_list, listitem_list)) - # Set focus to appropriate listitem. - listitem_elem = pattern_listitem_dict[pattern] - listitem_elem.click() - # Set behavior. - try: - listitem_elem.find_element_by_xpath( - './/option[@value="%s"]' % behavior).click() - except selenium.common.exceptions.ElementNotVisibleException: - raise AssertionError( - 'Changing the behavior is invalid for pattern ' - '"%s" in "%s" content page' % (behavior, self._content_type)) - # Send enter key. - pattern_elem = listitem_elem.find_element_by_tag_name('input') - _FocusField(self._driver, self._list_elem, pattern_elem) - pattern_elem.send_keys('\n') |