diff --git a/examples/cdp_mode/ReadMe.md b/examples/cdp_mode/ReadMe.md index f92d79da44e..5815ba409b5 100644 --- a/examples/cdp_mode/ReadMe.md +++ b/examples/cdp_mode/ReadMe.md @@ -313,6 +313,7 @@ sb.cdp.add_handler(event, handler) sb.cdp.find_element(selector) sb.cdp.find(selector) sb.cdp.locator(selector) +sb.cdp.find_element_by_text(text, tag_name=None) sb.cdp.find_all(selector) sb.cdp.find_elements_by_text(text, tag_name=None) sb.cdp.select(selector) diff --git a/requirements.txt b/requirements.txt index 22e6a73191f..8f3f8fed029 100755 --- a/requirements.txt +++ b/requirements.txt @@ -14,7 +14,7 @@ mycdp>=1.1.0 pynose>=1.5.3 platformdirs>=4.3.6 typing-extensions>=4.12.2 -sbvirtualdisplay>=1.3.0 +sbvirtualdisplay>=1.3.1 six>=1.17.0 parse>=1.20.2 parse-type>=0.6.4 diff --git a/seleniumbase/__version__.py b/seleniumbase/__version__.py index f9c1f6b1cea..0247a0dbf13 100755 --- a/seleniumbase/__version__.py +++ b/seleniumbase/__version__.py @@ -1,2 +1,2 @@ # seleniumbase package -__version__ = "4.33.8" +__version__ = "4.33.9" diff --git a/seleniumbase/core/browser_launcher.py b/seleniumbase/core/browser_launcher.py index 2cd96268a04..c2d9ae5b140 100644 --- a/seleniumbase/core/browser_launcher.py +++ b/seleniumbase/core/browser_launcher.py @@ -600,6 +600,7 @@ def uc_open_with_cdp_mode(driver, url=None): cdp.find_element = CDPM.find_element cdp.find = CDPM.find_element cdp.locator = CDPM.find_element + cdp.find_element_by_text = CDPM.find_element_by_text cdp.find_all = CDPM.find_all cdp.find_elements_by_text = CDPM.find_elements_by_text cdp.select = CDPM.select diff --git a/seleniumbase/core/sb_cdp.py b/seleniumbase/core/sb_cdp.py index b266b5f882e..6d196672446 100644 --- a/seleniumbase/core/sb_cdp.py +++ b/seleniumbase/core/sb_cdp.py @@ -167,6 +167,57 @@ def find_element( self.__slow_mode_pause_if_set() return element + def find_element_by_text( + self, text, tag_name=None, timeout=settings.SMALL_TIMEOUT + ): + """Returns an element by matching text. + Optionally, provide a tag_name to narrow down the search to an + element with the given tag. (Eg: a, button, div, script, span)""" + self.__add_light_pause() + time_now = time.time() + self.assert_text(text, timeout=timeout) + spent = int(time.time() - time_now) + remaining = 1 + timeout - spent + if tag_name: + self.assert_element(tag_name, timeout=remaining) + elements = self.loop.run_until_complete( + self.page.find_elements_by_text(text=text) + ) + if tag_name: + tag_name = tag_name.lower().strip() + for element in elements: + if element and not tag_name: + element = self.__add_sync_methods(element) + return self.__add_sync_methods(element) + elif ( + element + and tag_name in element.tag_name.lower() + and text.strip() in element.text + ): + element = self.__add_sync_methods(element) + return self.__add_sync_methods(element) + elif ( + element.parent + and tag_name in element.parent.tag_name.lower() + and text.strip() in element.parent.text + ): + element = self.__add_sync_methods(element.parent) + return self.__add_sync_methods(element) + elif ( + element.parent.parent + and tag_name in element.parent.parent.tag_name.lower() + and text.strip() in element.parent.parent.text + ): + element = self.__add_sync_methods(element.parent.parent) + return self.__add_sync_methods(element) + plural = "s" + if timeout == 1: + plural = "" + raise Exception( + "Text {%s} with tag {%s} was not found after %s second%s!" + % (text, tag_name, timeout, plural) + ) + def find_all(self, selector, timeout=settings.SMALL_TIMEOUT): self.__add_light_pause() selector = self.__convert_to_css_if_xpath(selector) @@ -177,26 +228,48 @@ def find_all(self, selector, timeout=settings.SMALL_TIMEOUT): for element in elements: element = self.__add_sync_methods(element) updated_elements.append(element) - self.__slow_mode_pause_if_set() return updated_elements def find_elements_by_text(self, text, tag_name=None): """Returns a list of elements by matching text. - Optionally, provide a tag_name to narrow down the search - to only elements with the given tag. (Eg: a, div, script, span)""" + Optionally, provide a tag_name to narrow down the search to only + elements with the given tag. (Eg: a, button, div, script, span)""" self.__add_light_pause() elements = self.loop.run_until_complete( self.page.find_elements_by_text(text=text) ) updated_elements = [] + if tag_name: + tag_name = tag_name.lower().strip() for element in elements: - if ( - not tag_name - or tag_name.lower().strip() in element.tag_name.lower().strip() + if element and not tag_name: + element = self.__add_sync_methods(element) + if element not in updated_elements: + updated_elements.append(element) + elif ( + element + and tag_name in element.tag_name.lower() + and text.strip() in element.text ): element = self.__add_sync_methods(element) - updated_elements.append(element) - self.__slow_mode_pause_if_set() + if element not in updated_elements: + updated_elements.append(element) + elif ( + element.parent + and tag_name in element.parent.tag_name.lower() + and text.strip() in element.parent.text + ): + element = self.__add_sync_methods(element.parent) + if element not in updated_elements: + updated_elements.append(element) + elif ( + element.parent.parent + and tag_name in element.parent.parent.tag_name.lower() + and text.strip() in element.parent.parent.text + ): + element = self.__add_sync_methods(element.parent.parent) + if element not in updated_elements: + updated_elements.append(element) return updated_elements def select(self, selector, timeout=settings.SMALL_TIMEOUT): @@ -244,7 +317,6 @@ def select_all(self, selector, timeout=settings.SMALL_TIMEOUT): for element in elements: element = self.__add_sync_methods(element) updated_elements.append(element) - self.__slow_mode_pause_if_set() return updated_elements def find_elements(self, selector, timeout=settings.SMALL_TIMEOUT): diff --git a/setup.py b/setup.py index 371dbc08124..9ae77f4b8fb 100755 --- a/setup.py +++ b/setup.py @@ -163,7 +163,7 @@ "pynose>=1.5.3", 'platformdirs>=4.3.6', 'typing-extensions>=4.12.2', - "sbvirtualdisplay>=1.3.0", + "sbvirtualdisplay>=1.3.1", "six>=1.17.0", 'parse>=1.20.2', 'parse-type>=0.6.4',