diff --git a/selen_kaa/element/se_elements_array.py b/selen_kaa/element/se_elements_array.py index d5fa829..39275ad 100644 --- a/selen_kaa/element/se_elements_array.py +++ b/selen_kaa/element/se_elements_array.py @@ -1,11 +1,10 @@ from selenium.webdriver.remote.webdriver import WebDriver from selenium.webdriver.support.wait import WebDriverWait +from selenium.common.exceptions import TimeoutException +from selenium.webdriver.support.expected_conditions import presence_of_all_elements_located from selen_kaa.utils.se_utils import get_selector_type -from selenium.webdriver.support.expected_conditions import presence_of_all_elements_located from selen_kaa.utils import custom_types -from selen_kaa.element.se_web_element import SeWebElement - TimeoutType = custom_types.TimeoutType @@ -23,15 +22,32 @@ def __init__(self, webdriver: WebDriver, css_selector: str, timeout: TimeoutType self._css_selector = css_selector self._timeout = timeout self._elements_array = [] + self._element_type = None + + @property + def element_type(self): + if self._element_type is None: + raise AttributeError("Type of element in SeElementsArray is None. " + "Probably, you forgot to assign an element_type.") + return self._element_type + + @element_type.setter + def element_type(self, web_element_type): + self._element_type = web_element_type @property def _lazy_array(self): - if not self._elements_array: - elements_ = WebDriverWait(self._webdriver, self._timeout).until( - presence_of_all_elements_located((get_selector_type(self._css_selector), self._css_selector)) - ) + if len(self._elements_array) < 1: + try: + elements_ = WebDriverWait(self._webdriver, self._timeout).until( + presence_of_all_elements_located((get_selector_type(self._css_selector), self._css_selector)) + ) + except TimeoutException: + # return empty array if no element is present on the page + return [] + for elem in elements_: - wrapped_elem = SeWebElement(self._webdriver, self._css_selector, self._timeout) + wrapped_elem = self._element_type(self._webdriver, self._css_selector, self._timeout) wrapped_elem.web_element = elem self._elements_array.append(wrapped_elem) @@ -48,6 +64,7 @@ def hooked(*args, **kwargs): if result == self._lazy_array: return self return result + return hooked return orig_attr except AttributeError as exc: diff --git a/selen_kaa/waits.py b/selen_kaa/waits.py index cb5f641..01d15f5 100644 --- a/selen_kaa/waits.py +++ b/selen_kaa/waits.py @@ -9,7 +9,6 @@ from selen_kaa.errors import TIMEOUT_BASE_ERR_MSG from selen_kaa.utils import se_utils -from selen_kaa.element.se_element_interface import SeElementInterface from selen_kaa.utils import custom_types from selen_kaa.utils.custom_funcs import single_dispatch @@ -33,7 +32,6 @@ def element_be_in_dom(self, selector: str, timeout: TimeoutType = DEFAULT_TIMEOU @single_dispatch def element_to_be_visible(self, target: ElementType, timeout: TimeoutType = DEFAULT_TIMEOUT): - self._check_target_type(target) def wrapped_visible(): target.get_web_element_by_timeout(timeout) @@ -56,7 +54,6 @@ def element_to_be_invisible(self, target: ElementType, timeout: TimeoutType = DE Difference from `element_not_present`: returns True if element is not visible, but it's still present in DOM. """ - self._check_target_type(target) def wrapped_webelement_disappears(): try: @@ -85,7 +82,6 @@ def element_not_present(self, target: ElementType, timeout: TimeoutType = DEFAUL """True if there is no NoSuchElementException or StaleElementReferenceException. Element should be neither visible, nor enabled, nor be present in DOM. """ - self._check_target_type(target) def no_wrapped_webelement_in_dom(): try: @@ -114,7 +110,6 @@ def element_to_contain_text(self, target: ElementType, text: str, timeout: Timeo """Wait for text attribute of the web element to contain expected text. True for `in` comparision, e.g. "test" in "some test here". """ - self._check_target_type(target) def has_text_in_target(): target.get_web_element_by_timeout(timeout) @@ -147,7 +142,6 @@ def element_to_have_exact_text(self, target: ElementType, text: str, timeout: Ti """Wait for the web element to have exact text True for exact comparision of expected text with actual text attribute of web element. """ - self._check_target_type(target) def has_exact_text_in_target(): target.get_web_element_by_timeout(timeout) @@ -180,7 +174,6 @@ def element_have_similar_text(self, target: ElementType, text: str, timeout: Tim This method is different from `wait_element_to_contain_text`, as it ignores whitespaces, newtabs, cases for similarity comparision. """ - self._check_target_type(target) target.get_web_element_by_timeout(timeout) element = target return self._element_have_similar_text_helper(element, text, timeout) @@ -219,7 +212,6 @@ def __element_have_similar_text_we(self, target: WebElement, text: str, timeout= @single_dispatch def element_to_get_class(self, target: ElementType, expected_class: str, timeout: TimeoutType = DEFAULT_TIMEOUT): """Wait until web element gets expected class.""" - self._check_target_type(target) target.get_web_element_by_timeout(timeout) element = target return self._wait_element_to_get_class(element, expected_class, timeout) @@ -288,7 +280,6 @@ def element_to_include_child_element(self, target: ElementType, child_css_selector, timeout: TimeoutType = DEFAULT_TIMEOUT): """Wait for a web element to have another web element as a child element.""" - self._check_target_type(target) target.get_web_element_by_timeout(timeout) webelement_ = target return self._wait_child_element(webelement_, child_css_selector, timeout) @@ -407,9 +398,3 @@ def wait_fluently(condition: Callable, timeout: TimeoutType, err_msg: str): if time.time() - start_time >= timeout: raise TimeoutException(err_msg) time.sleep(0.3) - - @staticmethod - def _check_target_type(target): - if not isinstance(target, SeElementInterface): - raise TypeError(f"Error type: {type(target)}. " - f"Target shall be an instance of string, WebElement or WebElementWrapper.") diff --git a/selen_kaa/webdriver.py b/selen_kaa/webdriver.py index b5add45..03a5a18 100644 --- a/selen_kaa/webdriver.py +++ b/selen_kaa/webdriver.py @@ -69,4 +69,6 @@ def init_all_web_elements(self, selector: str, timeout: TimeoutType = None) -> S timeout_ = DEFAULT_TIMEOUT if timeout or timeout == 0: timeout_ = timeout - return SeElementsArray(self.webdriver, selector, timeout_) + arr = SeElementsArray(self.webdriver, selector, timeout_) + arr.element_type = SeWebElement + return arr diff --git a/setup.py b/setup.py index 5156537..1b15ef0 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ def get_requirements(): setup( name="selen-kaa", - version="0.0.3.1.0", + version="0.1.0", author="Viktor Grygorchuk", author_email="vvgrygorchuk@gmail.com", keywords=['Selenium', 'Test Automation'], @@ -21,7 +21,7 @@ def get_requirements(): long_description=long_description, long_description_content_type="text/markdown", url="https://github.com/VicGrygorchyk/selen_kaa.git", - download_url="https://github.com/VicGrygorchyk/selen_kaa/archive/0.0.3.1.0.tar.gz", + download_url="https://github.com/VicGrygorchyk/selen_kaa/archive/0.1.0.tar.gz", packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "test*"]), install_requires=get_requirements(), classifiers=[ diff --git a/tests/se_test/test_wrapped_arr.py b/tests/se_test/test_wrapped_arr.py index 4723337..a1ba713 100644 --- a/tests/se_test/test_wrapped_arr.py +++ b/tests/se_test/test_wrapped_arr.py @@ -1,5 +1,7 @@ from selen_kaa.element.se_elements_array import SeElementsArray from selen_kaa.element.se_web_element import SeWebElement + +from tests.webapp.driver_wrapper import WebElementWrapper from tests.webapp.pages.index_page import THE_SAME_CLASS @@ -10,8 +12,11 @@ def test_init_elements_works(app): def test_arr_is_lazy(app): - """Verify the init doesn't crash before the element is visible.""" + """Verify the array is empty before the element is visible. + The array is populated after elements became visible. + """ thesame_element = app.web_driver.init_all_web_elements(THE_SAME_CLASS) + assert not thesame_element app.goto_index_page() # only here element is rendered assert len(thesame_element) == 7 @@ -20,6 +25,8 @@ def test_arr_is_lazy(app): def test_can_override_webelements_type(app): index_page = app.goto_index_page() assert isinstance(index_page.the_same_text, SeElementsArray) + assert type(index_page.the_same_text[0]) is WebElementWrapper + assert isinstance(index_page.the_same_text[0], SeWebElement) def test_elem_in_arr(app): diff --git a/tests/webapp/driver_wrapper.py b/tests/webapp/driver_wrapper.py index ea58221..aa9464e 100644 --- a/tests/webapp/driver_wrapper.py +++ b/tests/webapp/driver_wrapper.py @@ -53,3 +53,8 @@ def get_screenshot_as_png(self): def init_web_element(self, selector: str, timeout: TimeoutType = 1): return WebElementWrapper(self.webdriver, selector, timeout) + + def init_all_web_elements(self, selector: str, timeout: TimeoutType = None): + arr = super().init_all_web_elements(selector, timeout) + arr.element_type = WebElementWrapper + return arr