diff --git a/stere/fields/element_builder.py b/stere/fields/element_builder.py index 72e84568..2f5803ec 100644 --- a/stere/fields/element_builder.py +++ b/stere/fields/element_builder.py @@ -36,11 +36,11 @@ def __init__(self, strategy, locator, parent_locator=None): # when .find() is called. self.root = None - def find(self): + def find(self, wait_time=None): """Use _find_all() or _find_all_in_parent() to find an element.""" if self.root is None and self.parent_locator is None: - return self._find_all() + return self._find_all(wait_time=wait_time) if self.root: self.parent_locator = self.root.find() - return self._find_all_in_parent() + return self._find_all_in_parent(wait_time=wait_time) diff --git a/stere/strategy/splinter.py b/stere/strategy/splinter.py index 53ca99fa..d4adbd92 100644 --- a/stere/strategy/splinter.py +++ b/stere/strategy/splinter.py @@ -19,16 +19,21 @@ def is_clickable(self, wait_time: typing.Optional[int] = None) -> bool: ) def is_not_clickable(self, wait_time: typing.Optional[int] = None) -> bool: - """Check if an element is present in the DOM and clickable. + """Check if an element is not clickable in the DOM. Arguments: wait_time (int): The number of seconds to wait. If not specified, Stere.retry_time will be used. """ - return _retry( - lambda: not self.find() or (self.find() and not self.find()._element.is_enabled()), # NOQA: E501 - wait_time, - ) + def search(): + result = self.find(wait_time=0) + if not result: + return True + if result and not result._element.is_enabled(): + return True + return False + + return _retry(search, wait_time) def is_present(self, wait_time: typing.Optional[int] = None) -> bool: """Check if an element is present in the DOM. @@ -50,7 +55,7 @@ def is_not_present(self, wait_time: typing.Optional[int] = None) -> bool: Stere.retry_time will be used. """ return _retry( - lambda: not self.find(), + lambda: not self.find(wait_time=0), wait_time, ) @@ -67,26 +72,31 @@ def is_visible(self, wait_time: typing.Optional[int] = None) -> bool: ) def is_not_visible(self, wait_time: typing.Optional[int] = None) -> bool: - """Check if an element is present in the DOM but not visible. + """Check if an element is not visible in the DOM. Arguments: wait_time (int): The number of seconds to wait. If not specified, Stere.retry_time will be used. """ - return _retry( - lambda: not self.find() or (self.find() and not self.find().visible), # NOQA: E501 - wait_time, - ) + def search(): + result = self.find(wait_time=0) + if not result: + return True + if result and not result.visible: + return True + return False + + return _retry(search, wait_time) - def _find_all(self): + def _find_all(self, wait_time=None): """Find from page root.""" func = getattr(self.browser, f'find_by_{self.strategy}') - return func(self.locator) + return func(self.locator, wait_time=wait_time) - def _find_all_in_parent(self): + def _find_all_in_parent(self, wait_time=None): """Find from inside a parent element.""" func = getattr(self.parent_locator, f'find_by_{self.strategy}') - return func(self.locator) + return func(self.locator, wait_time=wait_time) @strategy('css') @@ -127,15 +137,17 @@ class FindByValue(SplinterBase): class FindByAttribute(SplinterBase): """Strategy to find an element by an arbitrary attribute.""" - def _find_all(self): + def _find_all(self, wait_time=None): """Find from page root.""" return self.browser.find_by_xpath( - f'//*[@{self._attribute}="{self.locator}"]') + f'//*[@{self._attribute}="{self.locator}"]', wait_time=wait_time, + ) - def _find_all_in_parent(self): + def _find_all_in_parent(self, wait_time=None): """Find from inside parent element.""" return self.parent_locator.find_by_xpath( - f'.//*[@{self._attribute}="{self.locator}"]') + f'.//*[@{self._attribute}="{self.locator}"]', wait_time=wait_time, + ) def add_data_star_strategy(data_star_attribute):