From c82ce3535e101ed2c4e93d9913584b1ea36fa570 Mon Sep 17 00:00:00 2001 From: Alvaro Laserna Date: Fri, 10 Oct 2025 10:43:29 +0300 Subject: [PATCH] add exists method --- tests/selenium_tests.py | 2 +- testui/elements/testui_collection.py | 33 ++++++++++++ testui/elements/testui_element.py | 80 ++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 1 deletion(-) diff --git a/tests/selenium_tests.py b/tests/selenium_tests.py index 449bb21..fedb2ba 100644 --- a/tests/selenium_tests.py +++ b/tests/selenium_tests.py @@ -44,7 +44,7 @@ def test_template_matching(self, selenium_driver: TestUIDriver): .swipe(start_x=50, start_y=50, end_x=100, end_y=100) selenium_driver.navigate_to( "https://www.testdevlab.com/" - ).e('css', '#email').send_keys('some@email.com') + ).e('css', '#email').wait_until_exists(10).send_keys('some@email.com') selenium_driver.raise_errors() @pytest.mark.signup diff --git a/testui/elements/testui_collection.py b/testui/elements/testui_collection.py index bd2a074..efa6ddc 100644 --- a/testui/elements/testui_collection.py +++ b/testui/elements/testui_collection.py @@ -65,6 +65,39 @@ def wait_until_all_visible(self, seconds=10.0, log=True): f"been found after {time.time() - start}s: \n {compose_error}" ) + def wait_until_all_exist(self, seconds=10.0, log=True): + """ + Wait until all elements in collection are visible + :param seconds: timeout + :param log: log to console + """ + start = time.time() + threads = [] + for arg in self.args: + threads.append( + threading.Thread( + target=arg.wait_until_exists, args=(seconds, log) + ) + ) + for thread in threads: + thread.start() + for thread in threads: + thread.join() + if time.time() < start + seconds: + logger.log( + f"{self.args[0].device_name}: Collection of elements has been " + f"found after {time.time() - start}s" + ) + else: + compose_error = "" + error: str + for error in self.__errors: + compose_error = compose_error + f"{error} \n" + self.__show_error( + f"{self.args[0].device_name}: Collection of elements has not " + f"been found after {time.time() - start}s: \n {compose_error}" + ) + def find_visible(self, seconds=10, return_el_number=False): """ Find first visible element in collection diff --git a/testui/elements/testui_element.py b/testui/elements/testui_element.py index 0fbef4a..9da3ce5 100644 --- a/testui/elements/testui_element.py +++ b/testui/elements/testui_element.py @@ -270,6 +270,49 @@ def is_visible(self, log=True, **kwargs) -> bool: return is_visible + def exist(self, log=True, **kwargs) -> bool: + """ + Check if element exists + :param log: Boolean + :return: Boolean + """ + is_not = False + + # Allows passing "is_not" as a kwarg to not overwrite self.__is_not. + # This is not meant to be used by the user. + if "is_not" in kwargs: + is_not = kwargs["is_not"] + else: + is_not = self.__is_not + self.__is_not = False + + exists = False + try: + exists = self.get_element() + + if log: + if exists: + self.__put_log( + f'{self.device_name}: element "{self.locator_type}: ' + f'{self.locator}" exists' + ) + else: + self.__put_log( + f'{self.device_name}: element "{self.locator_type}: ' + f'{self.locator}" does not exist' + ) + except Exception: + if log: + self.__put_log( + f'{self.device_name}: element "{self.locator_type}: ' + f'{self.locator}" does not exists' + ) + + if is_not: + return not exists + + return exists + def is_visible_in(self, seconds) -> bool: """ Check if element is visible in a certain amount of time @@ -344,6 +387,43 @@ def wait_until_visible(self, seconds=10.0, log=True): if is_not: err_text = "was" + self.__show_error( + f"{self.device_name}: Element {err_text} found visible with the following " + f'locator: "{self.locator_type}: {self.locator}" ' + f"after {time.time() - start}s" + ) + + return self + + def wait_until_exists(self, seconds=10.0, log=True): + """ + Wait until element is visible + :param seconds: seconds + :param log: Boolean + """ + start = time.time() + + is_not = self.__is_not + self.__is_not = False + + is_visible = self.exist(log=False, is_not=is_not) + while time.time() < start + seconds and not is_visible: + time.sleep(0.2) + is_visible = self.exist(log=False, is_not=is_not) + + if is_visible: + if log: + self.__put_log( + f'{self.device_name}: Element "{self.locator_type}: ' + f'{self.locator}" was visible in {time.time() - start}s' + ) + + return self + + err_text = "was not" + if is_not: + err_text = "was" + self.__show_error( f"{self.device_name}: Element {err_text} found with the following " f'locator: "{self.locator_type}: {self.locator}" '