From d537b40f432b1764aff6326cf42b1771a58b7d63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Fale=C5=A1n=C3=ADk?= Date: Wed, 24 May 2017 17:33:00 +0200 Subject: [PATCH 1/4] Speedup by checking the page only when necessary; Logging update. --- src/widgetastic/browser.py | 102 ++++++++++++++++++++++++++++--------- src/widgetastic/log.py | 32 ++++++++---- src/widgetastic/utils.py | 32 ++++++++++++ testing/conftest.py | 12 ++++- 4 files changed, 143 insertions(+), 35 deletions(-) diff --git a/src/widgetastic/browser.py b/src/widgetastic/browser.py index e1985bc8..95e7b321 100644 --- a/src/widgetastic/browser.py +++ b/src/widgetastic/browser.py @@ -21,7 +21,8 @@ from .exceptions import ( NoSuchElementException, UnexpectedAlertPresentException, MoveTargetOutOfBoundsException, StaleElementReferenceException, NoAlertPresentException, LocatorNotImplemented) -from .log import create_widget_logger, null_logger +from .log import create_widget_logger, logged, null_logger +from .utils import repeat_once_on_exceptions from .xpath import normalize_space from .utils import crop_string_middle @@ -269,6 +270,7 @@ def elements( return result + @repeat_once_on_exceptions(NoSuchElementException, check_safe=True) def element(self, locator, *args, **kwargs): """Returns one :py:class:`selenium.webdriver.remote.webelement.WebElement` @@ -280,6 +282,8 @@ def element(self, locator, *args, **kwargs): Raises: :py:class:`selenium.common.exceptions.NoSuchElementException` """ + if 'check_safe' not in kwargs: + kwargs['check_safe'] = False try: vcheck = self._locator_force_visibility_check(locator) if vcheck is not None: @@ -294,7 +298,7 @@ def element(self, locator, *args, **kwargs): else: return elements[0] except IndexError: - raise NoSuchElementException('Could not find an element {}'.format(repr(locator))) + raise NoSuchElementException('Could not find an element {!r}'.format(locator)) def perform_click(self): """Clicks the left mouse button at the current mouse position.""" @@ -304,12 +308,12 @@ def perform_double_click(self): """Double-clicks the left mouse button at the current mouse position.""" ActionChains(self.selenium).double_click().perform() + @logged(log_args=True, only_after=True, debug_only=True, log_full_exception=False) def click(self, locator, *args, **kwargs): """Clicks at a specific element using two separate events (mouse move, mouse click). Args: See :py:meth:`elements` """ - self.logger.debug('click: %r', locator) ignore_ajax = kwargs.pop('ignore_ajax', False) el = self.move_to_element(locator, *args, **kwargs) self.plugin.before_click(el) @@ -325,6 +329,7 @@ def click(self, locator, *args, **kwargs): except (StaleElementReferenceException, UnexpectedAlertPresentException): pass + @logged(log_args=True, only_after=True, debug_only=True, log_full_exception=False) def double_click(self, locator, *args, **kwargs): """Double-clicks at a specific element using two separate events (mouse move, mouse click). @@ -346,12 +351,12 @@ def double_click(self, locator, *args, **kwargs): except (StaleElementReferenceException, UnexpectedAlertPresentException): pass + @logged(log_args=True, only_after=True, debug_only=True, log_full_exception=False) def raw_click(self, locator, *args, **kwargs): """Clicks at a specific element using the direct event. Args: See :py:meth:`elements` """ - self.logger.debug('raw_click: %r', locator) ignore_ajax = kwargs.pop('ignore_ajax', False) el = self.element(locator, *args, **kwargs) self.plugin.before_click(el) @@ -394,6 +399,10 @@ def is_displayed(self, locator, *args, **kwargs): # Just in case return False + @logged(log_args=True, only_after=True, debug_only=True, log_full_exception=False) + @repeat_once_on_exceptions( + StaleElementReferenceException, MoveTargetOutOfBoundsException, + check_safe=True) def move_to_element(self, locator, *args, **kwargs): """Moves the mouse cursor to the middle of the element represented by the locator. @@ -402,23 +411,31 @@ def move_to_element(self, locator, *args, **kwargs): Args: See :py:meth:`elements` + Keywords: + workaround: Default True, tells whether it can or can not perform the JS workaround. + Returns: :py:class:`selenium.webdriver.remote.webelement.WebElement` """ - self.logger.debug('move_to_element: %r', locator) + if 'check_safe' not in kwargs: + kwargs['check_safe'] = False + workaround = kwargs.pop('workaround', True) el = self.element(locator, *args, **kwargs) if el.tag_name == "option": # Instead of option, let's move on its parent