Webdriver addon
webdriver_addon ¶
module with webdriver class extensions
Webdriver extensions include: - speed-up for finding elements using parsel - access to shadow dom (with translation of xpath to css) - helper closing pop-ups - wait functions
T = TypeVar('T', bound='utils_seleniumxp._RemoteWebDriver') module-attribute ¶
EventFiringWebDriverExtendedMixedin(webdriver: _WebDriver, eventlistener: AbstractEventListener) ¶
EventFiringWebDriverExtendedMixedin - mixin class for eventfiring webdriver
Source code in src/utils_seleniumxp/eventfiring_addon.py
closepopup(locator_click: utils_seleniumxp.SeleniumLocator, wait_click: float, check_click: bool = False, locator_iframe: utils_seleniumxp.SeleniumLocator | None = None, wait_iframe: float = 1, locator_shadowdomhost: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator] | None = None) -> bool ¶
Source code in src/utils_seleniumxp/webdriver_addon.py
def closepopup(
self,
locator_click: utils_seleniumxp.SeleniumLocator,
wait_click: float,
check_click: bool = False,
locator_iframe: utils_seleniumxp.SeleniumLocator | None = None,
wait_iframe: float = 1,
locator_shadowdomhost: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator] | None = None
) -> bool:
return closepopup_eventfiring(self, locator_click, wait_click, check_click, locator_iframe, wait_iframe, locator_shadowdomhost)
closepopup_queueadd(locator_click: utils_seleniumxp.SeleniumLocator, wait_click: float, check_click: bool = False, locator_iframe: utils_seleniumxp.SeleniumLocator | None = None, wait_iframe: float = 1, locator_shadowdomhost: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator] | None = None) -> bool ¶
Source code in src/utils_seleniumxp/webdriver_addon.py
def closepopup_queueadd(
self, locator_click:
utils_seleniumxp.SeleniumLocator,
wait_click: float,
check_click: bool = False,
locator_iframe: utils_seleniumxp.SeleniumLocator | None = None,
wait_iframe: float = 1,
locator_shadowdomhost: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator] | None = None
) -> bool:
return closepopup_queueadd_eventfiring(self, locator_click, wait_click, check_click, locator_iframe, wait_iframe, locator_shadowdomhost)
closepopup_queueprocessing(firstonly: bool = True) -> bool ¶
WebDriverMixedin(cls_webdriver: type[T]) -> type[T] ¶
WebDriverMixedin - factory function for custom class with fixed 3rd party mixins and own mixin
The factory function mechanism is required to use alternative base classes like undetected_chromedriver.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls_webdriver | type[_RemoteWebDriver] | base class | required |
Returns:
| Type | Description |
|---|---|
type[T] | type[utils_seleniumxp._RemoteWebDriver]: custom webdriver class with mixin |
Source code in src/utils_seleniumxp/webdriver_addon.py
def WebDriverMixedin(cls_webdriver: type[T]) -> type[T]:
"""
WebDriverMixedin - factory function for custom class with fixed 3rd party mixins and own mixin
The factory function mechanism is required to use alternative base classes like
undetected_chromedriver.
Args:
cls_webdriver (type[utils_seleniumxp._RemoteWebDriver]): base class
Returns:
type[utils_seleniumxp._RemoteWebDriver]: custom webdriver class with mixin
"""
class WebDriverClassCustom(_WebDriverMixin, _RequestsSessionMixin, cls_webdriver): # type: ignore[valid-type, misc]
pass
return cast(type[T], WebDriverClassCustom)
WebDriverMixedinOnly3rdParty(cls_webdriver: type[T]) -> type[T] ¶
WebDriverMixedinOnly3rdParty - factory function for custom class with fixed 3rd party mixins
The factory function mechanism is required to use alternative base classes like undetected_chromedriver.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls_webdriver | type[_RemoteWebDriver] | base class | required |
Returns:
| Type | Description |
|---|---|
type[T] | type[utils_seleniumxp._RemoteWebDriver]: custom webdriver class with mixin |
Source code in src/utils_seleniumxp/webdriver_addon.py
def WebDriverMixedinOnly3rdParty(cls_webdriver: type[T]) -> type[T]:
"""
WebDriverMixedinOnly3rdParty - factory function for custom class with fixed 3rd party mixins
The factory function mechanism is required to use alternative base classes like
undetected_chromedriver.
Args:
cls_webdriver (type[utils_seleniumxp._RemoteWebDriver]): base class
Returns:
type[utils_seleniumxp._RemoteWebDriver]: custom webdriver class with mixin
"""
class WebDriverClassCustom(_RequestsSessionMixin, cls_webdriver): # type: ignore[valid-type, misc]
pass
return cast(type[T], WebDriverClassCustom)
clear_wol(webdriver: utils_seleniumxp._RemoteWebDriver) -> bool ¶
clear_wol - clear log of window.open logger
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
Returns:
| Name | Type | Description |
|---|---|---|
bool | bool | execution status |
Source code in src/utils_seleniumxp/webdriver_addon.py
closepopup(webdriver: utils_seleniumxp._RemoteWebDriver, locator_click: utils_seleniumxp.SeleniumLocator, wait_click: float = 0.1, check_click: bool = False, locator_iframe: utils_seleniumxp.SeleniumLocator | None = None, wait_iframe: float = 1, locator_shadowdomhost: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator] | None = None) -> bool ¶
closepopup - close popups with use of parsel
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
locator_click | SeleniumLocator | locator for webelement to lcick for closing | required |
wait_click | float | wait after click. DEfaults to 0.1. | 0.1 |
check_click | bool | check after click if popup closed. Defaults to False. | False |
locator_iframe | SeleniumLocator | locator for iframe containing click object. Defaults to None. | None |
wait_iframe | float | wait to switch to iframe. Defaults to 1. | 1 |
locator_shadowdomhost | Union[SeleniumLocator, list[SeleniumLocator]] | locator list to shadowDOM host. Defaults to None. | None |
Returns:
| Name | Type | Description |
|---|---|---|
bool | bool | flag if a matching popup was found and closed |
Source code in src/utils_seleniumxp/webdriver_addon.py
def closepopup(
webdriver: utils_seleniumxp._RemoteWebDriver,
locator_click: utils_seleniumxp.SeleniumLocator,
wait_click: float = 0.1,
check_click: bool = False,
locator_iframe: utils_seleniumxp.SeleniumLocator | None = None,
wait_iframe: float = 1,
locator_shadowdomhost: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator] | None = None
) -> bool:
"""
closepopup - close popups with use of parsel
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
locator_click (utils_seleniumxp.SeleniumLocator): locator for webelement to lcick for closing
wait_click (float, optional): wait after click. DEfaults to 0.1.
check_click (bool, optional): check after click if popup closed. Defaults to False.
locator_iframe (utils_seleniumxp.SeleniumLocator, optional): locator for iframe containing click object. Defaults to None.
wait_iframe (float, optional): wait to switch to iframe. Defaults to 1.
locator_shadowdomhost (Union[utils_seleniumxp.SeleniumLocator, list[utils_seleniumxp.SeleniumLocator]], optional): locator list to shadowDOM host. Defaults to None.
Returns:
bool: flag if a matching popup was found and closed
"""
closepopup_queueadd(webdriver, locator_click, wait_click, check_click, locator_iframe, wait_iframe, locator_shadowdomhost)
return closepopup_queueprocessing(webdriver)
closepopup_eventfiring(webdriver: utils_seleniumxp.eventfiring_addon.EventFiringWebDriverExtended, locator_click: utils_seleniumxp.SeleniumLocator, wait_click: float, check_click: bool = False, locator_iframe: utils_seleniumxp.SeleniumLocator | None = None, wait_iframe: float = 1, locator_shadowdomhost: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator] | None = None) -> bool ¶
closepopup_eventfiring - closepopup for eventfiring webdriver, required to avoid endless recurion loop)
Source code in src/utils_seleniumxp/webdriver_addon.py
def closepopup_eventfiring(
webdriver: utils_seleniumxp.eventfiring_addon.EventFiringWebDriverExtended,
locator_click: utils_seleniumxp.SeleniumLocator,
wait_click: float,
check_click: bool = False,
locator_iframe: utils_seleniumxp.SeleniumLocator | None = None,
wait_iframe: float = 1,
locator_shadowdomhost: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator] | None = None
) -> bool:
"""
closepopup_eventfiring - closepopup for eventfiring webdriver, required to avoid endless recurion loop)
"""
return webdriver._dispatch("closepopuphandler", ("simpleclose", webdriver._driver), "_closepopup", (locator_click, wait_click, check_click, locator_iframe, wait_iframe, locator_shadowdomhost), b_recursive=True)
closepopup_queueadd(webdriver: utils_seleniumxp._RemoteWebDriver, locator_click: utils_seleniumxp.SeleniumLocator, wait_click: float = 0.1, check_click: bool = False, locator_iframe: utils_seleniumxp.SeleniumLocator | None = None, wait_iframe: float = 1, locator_shadowdomhost: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator] | None = None) -> None ¶
closepopup_queueadd - add entry to closepopop processing queue
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
locator_click | SeleniumLocator | locator for webelement to lcick for closing | required |
wait_click | float | wait after click. DEfaults to 0.1. | 0.1 |
check_click | bool | check after click if popup closed. Defaults to False. | False |
locator_iframe | SeleniumLocator | locator for iframe containing click object. Defaults to None. | None |
wait_iframe | float | wait to switch to iframe. Defaults to 1. | 1 |
locator_shadowdomhost | Union[SeleniumLocator, list[SeleniumLocator]] | locator list to shadowDOM host. Defaults to None. | None |
Source code in src/utils_seleniumxp/webdriver_addon.py
def closepopup_queueadd(
webdriver: utils_seleniumxp._RemoteWebDriver,
locator_click: utils_seleniumxp.SeleniumLocator,
wait_click: float = 0.1,
check_click: bool = False,
locator_iframe: utils_seleniumxp.SeleniumLocator | None = None,
wait_iframe: float = 1,
locator_shadowdomhost: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator] | None = None
) -> None:
"""
closepopup_queueadd - add entry to closepopop processing queue
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
locator_click (utils_seleniumxp.SeleniumLocator): locator for webelement to lcick for closing
wait_click (float, optional): wait after click. DEfaults to 0.1.
check_click (bool, optional): check after click if popup closed. Defaults to False.
locator_iframe (utils_seleniumxp.SeleniumLocator, optional): locator for iframe containing click object. Defaults to None.
wait_iframe (float, optional): wait to switch to iframe. Defaults to 1.
locator_shadowdomhost (Union[utils_seleniumxp.SeleniumLocator, list[utils_seleniumxp.SeleniumLocator]], optional): locator list to shadowDOM host. Defaults to None.
"""
# check if webdriver has queue attribute already
if hasattr(webdriver, 'closepopup_queue'):
pass
else:
closepopup_queue = collections.deque() # type: ignore[var-annotated]
setattr(webdriver, 'closepopup_queue', closepopup_queue)
# add to queue
queueentry = {
"locator_click": locator_click,
"wait_click": wait_click,
"check_click": check_click,
"locator_iframe": locator_iframe,
"wait_iframe": wait_iframe,
"locator_shadowdomhost": locator_shadowdomhost
}
webdriver.closepopup_queue.append(queueentry)
closepopup_queueadd_eventfiring(webdriver: utils_seleniumxp.eventfiring_addon.EventFiringWebDriverExtended, locator_click: utils_seleniumxp.SeleniumLocator, wait_click: float, check_click: bool = False, locator_iframe: utils_seleniumxp.SeleniumLocator | None = None, wait_iframe: float = 1, locator_shadowdomhost: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator] | None = None) -> bool ¶
closepopup_queueadd_eventfiring - closepopup_queueadd for eventfiring webdriver, required to avoid endless recurion loop)
Source code in src/utils_seleniumxp/webdriver_addon.py
def closepopup_queueadd_eventfiring(
webdriver: utils_seleniumxp.eventfiring_addon.EventFiringWebDriverExtended,
locator_click: utils_seleniumxp.SeleniumLocator,
wait_click: float,
check_click: bool = False,
locator_iframe: utils_seleniumxp.SeleniumLocator | None = None,
wait_iframe: float = 1,
locator_shadowdomhost: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator] | None = None
) -> bool:
"""
closepopup_queueadd_eventfiring - closepopup_queueadd for eventfiring webdriver, required to avoid endless recurion loop)
"""
return webdriver._dispatch(None, (), "_closepopup_queueadd", (locator_click, wait_click, check_click, locator_iframe, wait_iframe, locator_shadowdomhost), b_recursive=True)
closepopup_queueprocessing(webdriver: utils_seleniumxp._RemoteWebDriver, firstonly: bool = True) -> bool ¶
closepopup_queueprocessing - process closepopup queue
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
firstonly | bool | process first found target webelement only. Defaults to True. | True |
Returns:
| Name | Type | Description |
|---|---|---|
bool | bool | flag if a matching popup was found and closed |
Source code in src/utils_seleniumxp/webdriver_addon.py
def closepopup_queueprocessing(webdriver: utils_seleniumxp._RemoteWebDriver, firstonly: bool = True) -> bool:
"""
closepopup_queueprocessing - process closepopup queue
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
firstonly (bool, optional): process first found target webelement only. Defaults to True.
Returns:
bool: flag if a matching popup was found and closed
"""
# set return default
closedpopup: bool = False
if hasattr(webdriver, 'closepopup_queue'):
if len(webdriver.closepopup_queue) > 0:
webdriver.wait4AJAX()
parsedhtml = utils_seleniumxp.locatorutils.parselSelectorExtension(text=webdriver.page_source)
while len(webdriver.closepopup_queue) > 0:
webdriver.wait4AJAX()
queueentry = webdriver.closepopup_queue.popleft()
locator_click: utils_seleniumxp.SeleniumLocator = queueentry["locator_click"]
wait_click: float = queueentry["wait_click"]
check_click: bool = queueentry["check_click"]
locator_iframe: utils_seleniumxp.SeleniumLocator | None = queueentry["locator_iframe"]
wait_iframe: float = queueentry["wait_iframe"]
locator_shadowdomhost: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator] | None = queueentry["locator_shadowdomhost"]
if not firstonly or not closedpopup:
# convert locator within shadowDOM to CSS
if locator_shadowdomhost is not None:
if locator_click.by == utils_seleniumxp.By.XPATH:
locator_click = utils_seleniumxp.SeleniumLocator(utils_seleniumxp.By.CSS_SELECTOR, cssify.cssify(locator_click.value))
elif locator_click.by != utils_seleniumxp.By.CSS_SELECTOR:
utils_seleniumxp.ErrorUtilsSelenium("Only CSS selector allowed together with element in shadowDOM.")
# initialize parsedhtml at beginning of loop
parsedhtml = utils_seleniumxp.locatorutils.parselSelectorExtension(text=webdriver.page_source)
# go to frame of popup (if any)
if locator_iframe is not None:
if utils_seleniumxp.locatorutils.check_locator(locator_iframe, [utils_seleniumxp.By.XPATH, utils_seleniumxp.By.CSS_SELECTOR]):
frames = parsedhtml.css_or_xpath(locator_iframe).getall()
# re-parse once, sometimes timing problem -> caused by switch-to error
if len(frames) == 0:
parsedhtml = utils_seleniumxp.locatorutils.parselSelectorExtension(text=webdriver.page_source)
frames = parsedhtml.css_or_xpath(locator_iframe).getall()
else:
frames = webdriver.find_elements(*locator_iframe)
if len(frames) == 0:
if hasattr(webdriver, "closepopup_logger"):
webdriver.closepopup_logger.info(f"FRAME not found\t{webdriver.current_url}\t({locator_click})\t({locator_iframe})\t({locator_shadowdomhost})")
continue
elif len(frames) == 1:
utils_seleniumxp.WebDriverWait(webdriver, wait_iframe).until(utils_seleniumxp.ExpectedConditions.frame_to_be_available_and_switch_to_it(locator_iframe)) # type: ignore[arg-type]
# shadowDOM cannot be evaluated via parsel / lxml but first node always not in shadowDOM
if (utils_seleniumxp.locatorutils.check_locator(locator_click, [utils_seleniumxp.By.XPATH, utils_seleniumxp.By.CSS_SELECTOR]) or
utils_seleniumxp.locatorutils.check_locatorlist(locator_shadowdomhost, [utils_seleniumxp.By.XPATH, utils_seleniumxp.By.CSS_SELECTOR])
):
parsedhtml = utils_seleniumxp.locatorutils.parselSelectorExtension(text=webdriver.page_source)
elif len(frames) > 1:
if hasattr(webdriver, "closepopup_logger"):
webdriver.closepopup_logger.info(f"FRAME not unique\t{webdriver.current_url}\t({locator_click})\t({locator_iframe})\t({locator_shadowdomhost})")
continue
# find close popup (considering also shadowDOM webelements)
if locator_shadowdomhost is not None:
# if utils_seleniumxp.locatorutils.check_locatorlist(locator_shadowdomhost, [utils_seleniumxp.By.XPATH, utils_seleniumxp.By.CSS_SELECTOR]):
# shadowhosts = parsedhtml.css_or_xpath(locator_shadowdomhost).getall()
# # re-parse once, sometimes timing problem (probably caused by opening shadowDOM and loading?)
# if len(shadowhosts) == 0:
# parsedhtml = utils_seleniumxp.locatorutils.parselSelectorExtension(text=webdriver.page_source)
# shadowhosts = parsedhtml.css_or_xpath(locator_shadowdomhost).getall()
# else:
# shadowhosts = webdriver.find_elements(*locator_shadowdomhost)
# webelts = []
# if len(shadowhosts) == 0:
# if hasattr(webdriver, "closepopup_logger"):
# webdriver.closepopup_logger.info(f"ShadowDOM host not found\t{webdriver.current_url}\t({locator_click})\t({locator_iframe})\t({locator_shadowdomhost})")
# continue
# elif len(shadowhosts) == 1:
# # shadowhost = webdriver.find_element(*locator_shadowdomhost)
# # shadowroot = webdriver.execute_script("return arguments[0].shadowRoot", shadowhost)
# shadowroot = webdriver.find_root_shadowdom_simple(*locator_shadowdomhost)
# if shadowroot is not None:
# webelts = shadowroot.find_elements(*locator_click)
# else:
# if hasattr(webdriver, "closepopup_logger"):
# webdriver.closepopup_logger.info(f"ShadowDOM host not unique\t{webdriver.current_url}\t({locator_click})\t({locator_iframe})\t({locator_shadowdomhost})")
# continue
shadowroot = webdriver.find_root_shadowdom(locator_shadowdomhost, webdriver.closepopup_logger.info, raise_exception=False)
if shadowroot is not None:
webelts = shadowroot.find_elements(*locator_click)
else:
webdriver.closepopup_logger.info(f"ShadowDOM root not found \t{webdriver.current_url}\t({locator_click})\t({locator_iframe})\t({locator_shadowdomhost})")
else:
if utils_seleniumxp.locatorutils.check_locator(locator_click, {utils_seleniumxp.By.XPATH, utils_seleniumxp.By.CSS_SELECTOR}):
webelts = parsedhtml.css_or_xpath(locator_click).getall()
webelts = webdriver.find_elements(*locator_click) if len(webelts) > 0 else []
else:
webelts = webdriver.find_elements(*locator_click)
# close popup
if len(webelts) > 0:
closedpopup_thisrun = False
for webelt in webelts:
try:
# if webelt.is_displayed() and not webelt.is_overlapped(): # type: ignore[union-attr]
if webelt.is_displayed():
countwindows = len(webdriver.window_handles)
keepwindows = webdriver.window_handles
webelt.click()
if wait_click > 0:
time.sleep(wait_click)
if len(webdriver.window_handles) > countwindows:
closewindows(webdriver, keepwindows)
closedpopup = True
closedpopup_thisrun = True
if hasattr(webdriver, "closepopup_logger"):
webdriver.closepopup_logger.info(f"found target\t{webdriver.current_url}\t({locator_click})\t({locator_iframe})\t({locator_shadowdomhost})")
break
except utils_seleniumxp.WebDriverExceptions.StaleElementReferenceException:
pass # simple rerun
except utils_seleniumxp.WebDriverExceptions.ElementClickInterceptedException:
pass # simple rerun
except:
raise
if check_click and closedpopup_thisrun:
if locator_shadowdomhost is not None:
webelts = shadowroot.find_elements(*locator_click)
else:
if utils_seleniumxp.locatorutils.check_locator(locator_click, {utils_seleniumxp.By.XPATH, utils_seleniumxp.By.CSS_SELECTOR}):
webelts = parsedhtml.css_or_xpath(locator_click).getall()
webelts = webdriver.find_elements(*locator_click) if len(webelts) > 0 else []
else:
webelts = webdriver.find_elements(*locator_click)
for webelt in webelts:
if webelt.is_displayed():
err_msg = "Popup could not be closed."
raise utils_seleniumxp.ErrorUtilsSelenium(err_msg)
else:
if hasattr(webdriver, "closepopup_logger"):
webdriver.closepopup_logger.info(f"not found\t{webdriver.current_url}\t({locator_click})\t({locator_iframe})\t({locator_shadowdomhost})")
# switch back from frame if necessary
if locator_iframe is not None:
if len(frames) != 0:
webdriver.switch_to.default_content()
else:
if hasattr(webdriver, "closepopup_logger"):
webdriver.closepopup_logger.info(f"not checked\t{webdriver.current_url}\t({locator_click})\t({locator_iframe})\t({locator_shadowdomhost})")
return closedpopup
closepopup_queueprocessing_eventfiring(webdriver: utils_seleniumxp.eventfiring_addon.EventFiringWebDriverExtended, firstonly: bool = True) -> bool ¶
closepopup_queueprocessing_eventfiring - closepopup_queueprocessing for eventfiring webdriver, required to avoid endless recurion loop)
Source code in src/utils_seleniumxp/webdriver_addon.py
def closepopup_queueprocessing_eventfiring(
webdriver: utils_seleniumxp.eventfiring_addon.EventFiringWebDriverExtended,
firstonly: bool = True
) -> bool:
"""
closepopup_queueprocessing_eventfiring - closepopup_queueprocessing for eventfiring webdriver, required to avoid endless recurion loop)
"""
return webdriver._dispatch("closepopuphandler", ("queueprocessing", webdriver._driver), "_closepopup_queueprocessing", (firstonly,), b_recursive=True)
closewindows(webdriver: utils_seleniumxp._RemoteWebDriver, keepwindows: list) -> None ¶
closewindows - close windows except those in 'keeplist'
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
keepwindows | list | list with windows to keep | required |
Source code in src/utils_seleniumxp/webdriver_addon.py
def closewindows(webdriver: utils_seleniumxp._RemoteWebDriver, keepwindows: list) -> None:
"""
closewindows - close windows except those in 'keeplist'
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
keepwindows (list): list with windows to keep
"""
keepcount: int = len(keepwindows)
if keepcount == 0:
return
while len(webdriver.window_handles) > keepcount:
for handle in reversed(webdriver.window_handles):
if handle not in keepwindows:
webdriver.switch_to.window(handle)
webdriver.close()
break
disable_wol(webdriver: utils_seleniumxp._RemoteWebDriver) -> bool ¶
disable_wol - disable window.open logger
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
Returns:
| Name | Type | Description |
|---|---|---|
bool | bool | execution status |
Source code in src/utils_seleniumxp/webdriver_addon.py
enable_wol(webdriver: utils_seleniumxp._RemoteWebDriver) -> bool ¶
enable_wol - enable window.open logger
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
Returns:
| Name | Type | Description |
|---|---|---|
bool | bool | execution status |
Source code in src/utils_seleniumxp/webdriver_addon.py
find_element_shadowdom(webdriver: utils_seleniumxp._RemoteWebDriver, locator_list: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator], shadowroot: utils_seleniumxp._ShadowRoot | utils_seleniumxp._WebElement | None = None) -> utils_seleniumxp._WebElement | None ¶
find_element_shadowdom - find element in shadowDOM with support for nested shadowDOM
Note: every item in the locator list must be a locator to a host of another shadowDOM root.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
locator_list | list[SeleniumLocator] | locator list | required |
shadowroot | Union[utils_seleniumxp._ShadowRoot, utils_seleniumxp._WebElement]] | shadowDOM root. Defaults to None. | None |
Returns:
| Type | Description |
|---|---|
_WebElement | None | Optional[utils_seleniumxp._WebElement]: webelement in shadowDOM if found |
Source code in src/utils_seleniumxp/webdriver_addon.py
def find_element_shadowdom(
webdriver: utils_seleniumxp._RemoteWebDriver,
locator_list: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator],
shadowroot: utils_seleniumxp._ShadowRoot | utils_seleniumxp._WebElement | None = None
) -> utils_seleniumxp._WebElement | None:
"""
find_element_shadowdom - find element in shadowDOM with support for nested shadowDOM
Note: every item in the locator list must be a locator to a host of another shadowDOM root.
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
locator_list (list[utils_seleniumxp.SeleniumLocator]): locator list
shadowroot (Union[utils_seleniumxp._ShadowRoot, utils_seleniumxp._WebElement]], optional): shadowDOM root. Defaults to None.
Returns:
Optional[utils_seleniumxp._WebElement]: webelement in shadowDOM if found
"""
webelts = find_elements_shadowdom(webdriver, locator_list, shadowroot)
if webelts is not None and webelts != []:
if len(webelts) == 1:
return webelts[0]
else:
err_msg = "Multiple elements for descriptor in shadowDOM"
raise utils_seleniumxp.ErrorUtilsSelenium(err_msg)
else:
return None
find_element_shadowdom_simple(webdriver: utils_seleniumxp._RemoteWebDriver, by: utils_seleniumxp.By, value: str, shadowroot: utils_seleniumxp._ShadowRoot | utils_seleniumxp._WebElement) -> utils_seleniumxp._WebElement | None ¶
find_element_shadowdom_simple - find element in shadowDOM
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
by | By | locator type | required |
value | str | locator value | required |
shadowroot | Union[_ShadowRoot, _WebElement] | shadowDOM root | required |
Returns:
| Type | Description |
|---|---|
_WebElement | None | Optional[utils_seleniumxp._WebElement]: webelement in shadowDOM if found |
Source code in src/utils_seleniumxp/webdriver_addon.py
def find_element_shadowdom_simple(
webdriver: utils_seleniumxp._RemoteWebDriver,
by: utils_seleniumxp.By,
value: str,
shadowroot: utils_seleniumxp._ShadowRoot | utils_seleniumxp._WebElement
) -> utils_seleniumxp._WebElement | None:
"""
find_element_shadowdom_simple - find element in shadowDOM
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
by (utils_seleniumxp.By): locator type
value (str): locator value
shadowroot (Union[utils_seleniumxp._ShadowRoot, utils_seleniumxp._WebElement]): shadowDOM root
Returns:
Optional[utils_seleniumxp._WebElement]: webelement in shadowDOM if found
"""
return find_element_shadowdom(webdriver, [utils_seleniumxp.SeleniumLocator(by, value)], shadowroot)
find_elements_optimized(webdriver: utils_seleniumxp._RemoteWebDriver, by: utils_seleniumxp.By, value: str, use_parsel: bool = True) -> list[utils_seleniumxp._WebElement] ¶
find_elements_optimized - optimized find_elements using parsel
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
by | By | locator type | required |
value | str | locator value | required |
use_parsel | bool | flag to use parsel. Defaults to True. | True |
Returns:
| Type | Description |
|---|---|
list[_WebElement] | list[utils_seleniumxp._WebElement]: list of webelements matching locator |
Source code in src/utils_seleniumxp/webdriver_addon.py
def find_elements_optimized(
webdriver: utils_seleniumxp._RemoteWebDriver,
by: utils_seleniumxp.By,
value: str,
use_parsel: bool = True
) -> list[utils_seleniumxp._WebElement]:
"""
find_elements_optimized - optimized find_elements using parsel
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
by (utils_seleniumxp.By): locator type
value (str): locator value
use_parsel (bool, optional): flag to use parsel. Defaults to True.
Returns:
list[utils_seleniumxp._WebElement]: list of webelements matching locator
"""
if use_parsel and by in {utils_seleniumxp.By.XPATH, utils_seleniumxp.By.CSS_SELECTOR}:
if webdriver.is_present(by, value, use_parsel):
return webdriver.find_elements(by, value)
else:
return []
else:
return webdriver.find_elements(by, value)
find_elements_shadowdom(webdriver: utils_seleniumxp._RemoteWebDriver, locator_list: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator], shadowroot: utils_seleniumxp._ShadowRoot | utils_seleniumxp._WebElement | None = None) -> list[utils_seleniumxp._WebElement] | None ¶
find_elements_shadowdom - find elements in shadowDOM with support for nested shadowDOM and root element as optional parameter
Note: every item in the locator list must be a locator to a host of another shadowDOM root. The routine also accepts the shadowhost element and derives the shadowroot automatically.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
locator_list | list[SeleniumLocator] | locator list | required |
shadowroot | Union[utils_seleniumxp._ShadowRoot, utils_seleniumxp._WebElement]] | shadowDOM root. Defaults to None. | None |
Returns:
| Type | Description |
|---|---|
list[_WebElement] | None | Optional[list[utils_seleniumxp._WebElement]]: list of webelements in shadowDOM if found |
Source code in src/utils_seleniumxp/webdriver_addon.py
def find_elements_shadowdom(
webdriver: utils_seleniumxp._RemoteWebDriver,
locator_list: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator],
shadowroot: utils_seleniumxp._ShadowRoot | utils_seleniumxp._WebElement | None = None
) -> list[utils_seleniumxp._WebElement] | None:
"""
find_elements_shadowdom - find elements in shadowDOM with support for nested shadowDOM and root element as optional parameter
Note: every item in the locator list must be a locator to a host of another shadowDOM root.
The routine also accepts the shadowhost element and derives the shadowroot automatically.
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
locator_list (list[utils_seleniumxp.SeleniumLocator]): locator list
shadowroot (Union[utils_seleniumxp._ShadowRoot, utils_seleniumxp._WebElement]], optional): shadowDOM root. Defaults to None.
Returns:
Optional[list[utils_seleniumxp._WebElement]]: list of webelements in shadowDOM if found
"""
if not isinstance(locator_list, list):
locator_list = [locator_list]
if len(locator_list) > 1 or shadowroot is not None:
queryselector = ""
for i in range(0, len(locator_list) - 1):
queryselector = queryselector + ".querySelector('" + _prepare_selector(locator_list[i]) + "').shadowRoot"
queryselector = queryselector + ".querySelectorAll('" + _prepare_selector(locator_list[-1]) + "')"
if shadowroot is not None:
if shadowroot.__class__.__name__ != "ShadowRoot":
# overcome issue that shadowDOM host but not root is provided
# try to treat shadowroot as host to derive correct root
try:
shadowroot = webdriver.execute_script("return arguments[0].shadowRoot", shadowroot)
except Exception:
shadowroot = None
if shadowroot is None:
err_msg = "Provided webelement is neither a ShadowRoot nor a ShadowHost."
raise utils_seleniumxp.ErrorUtilsSelenium(err_msg)
return None
# overcome issue with id attribute, discovered missing in JSON return when accessing shadow root in May 2025
if not hasattr(shadowroot, "id"):
shadowroot.id = shadowroot._id # type: ignore[misc]
try:
return webdriver.execute_script(f"return arguments[0]{queryselector}", shadowroot)
except Exception:
return None
else:
try:
return webdriver.execute_script(f"return document{queryselector}")
except Exception:
return None
else:
err_msg = "No sufficient selector information provided to access element in shadowDOM."
raise utils_seleniumxp.ErrorUtilsSelenium(err_msg)
find_elements_shadowdom_simple(webdriver: utils_seleniumxp._RemoteWebDriver, by: utils_seleniumxp.By, value: str, shadowroot: utils_seleniumxp._ShadowRoot | utils_seleniumxp._WebElement) -> list[utils_seleniumxp._WebElement] | None ¶
find_elements_shadowdom_simple - find elements in shadowDOM
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
by | By | locator type | required |
value | str | locator value | required |
shadowroot | Union[_ShadowRoot, _WebElement] | shadowDOM root | required |
Returns:
| Type | Description |
|---|---|
list[_WebElement] | None | Optional[utils_seleniumxp._WebElement]: list of webelements in shadowDOM if found |
Source code in src/utils_seleniumxp/webdriver_addon.py
def find_elements_shadowdom_simple(
webdriver: utils_seleniumxp._RemoteWebDriver,
by: utils_seleniumxp.By,
value: str,
shadowroot: utils_seleniumxp._ShadowRoot | utils_seleniumxp._WebElement
) -> list[utils_seleniumxp._WebElement] | None:
"""
find_elements_shadowdom_simple - find elements in shadowDOM
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
by (utils_seleniumxp.By): locator type
value (str): locator value
shadowroot (Union[utils_seleniumxp._ShadowRoot, utils_seleniumxp._WebElement]): shadowDOM root
Returns:
Optional[utils_seleniumxp._WebElement]: list of webelements in shadowDOM if found
"""
return find_elements_shadowdom(webdriver, [utils_seleniumxp.SeleniumLocator(by, value)], shadowroot)
find_root_shadowdom(webdriver: utils_seleniumxp._RemoteWebDriver, locator_list: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator], loggercall: Callable | None = None, raise_exception: bool = False, debug: bool = False) -> utils_seleniumxp._ShadowRoot | None ¶
find_root_shadowdom - find shadowDOM root with support for nested shadowDOM
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | browser | required |
locator_list | SeleniumLocator | list[SeleniumLocator] | (Union[utils_seleniumxp.SeleniumLocator, list[utils_seleniumxp.SeleniumLocator]], optional): locator list to shadowDOM host. Defaults to None. | required |
loggercall | Callable | None | (Callable, optional) = log function for error. Defaults to None. | None |
raise_exception | bool | (bool): flag to raise exception inc ase of any error in shadowDOM evaluation. Defaults to False. | False |
debug | bool | flag for debug mode to process every nesting level in shadowDOM separately. Defaults to False. | False |
Returns:
| Type | Description |
|---|---|
_ShadowRoot | None | Optional[utils_seleniumxp._WebElement]: shadowDOM root if found |
Source code in src/utils_seleniumxp/webdriver_addon.py
def find_root_shadowdom(
webdriver: utils_seleniumxp._RemoteWebDriver,
locator_list: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator],
loggercall: Callable | None = None,
raise_exception: bool = False,
debug: bool = False
) -> utils_seleniumxp._ShadowRoot | None:
"""
find_root_shadowdom - find shadowDOM root with support for nested shadowDOM
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): browser
locator_list: (Union[utils_seleniumxp.SeleniumLocator, list[utils_seleniumxp.SeleniumLocator]], optional): locator list to shadowDOM host. Defaults to None.
loggercall: (Callable, optional) = log function for error. Defaults to None.
raise_exception: (bool): flag to raise exception inc ase of any error in shadowDOM evaluation. Defaults to False.
debug (bool): flag for debug mode to process every nesting level in shadowDOM separately. Defaults to False.
Returns:
Optional[utils_seleniumxp._WebElement]: shadowDOM root if found
"""
def _execute_find_shadowroot(
webdriver: utils_seleniumxp._RemoteWebDriver,
script: str,
scriptparam: object,
err_msg: str,
loggercall: Callable | None = None,
raise_exception: bool = False
) -> utils_seleniumxp._ShadowRoot | None:
try:
shadowroot = webdriver.execute_script(script, scriptparam)
except Exception:
shadowroot = None
if shadowroot is None:
if loggercall is not None:
loggercall(err_msg)
if raise_exception:
raise utils_seleniumxp.ErrorUtilsSelenium(err_msg)
return shadowroot
if not isinstance(locator_list, list):
locator_list = [locator_list]
if len(locator_list) >= 1:
# evaluate first locator - use optimized check for presence
shadowroot = None
shadowhost = locator_list[0]
if webdriver.is_present(*shadowhost):
shadowroot = _execute_find_shadowroot(
webdriver,
"return arguments[0].shadowRoot",
webdriver.find_element(*shadowhost),
f"Locator {shadowhost} is not a valid unique locator to a shadowDOM host.",
loggercall,
raise_exception
)
if shadowroot is not None:
# evaluate rest of locator list
queryselector = ""
for i in range(1, len(locator_list)):
if debug:
shadowroot = _execute_find_shadowroot(
webdriver,
f"return arguments[0].querySelector('{_prepare_selector(locator_list[i])}').shadowRoot",
shadowroot,
f"Locator {locator_list[i]} is not a valid unique locator to a shadowDOM host.",
loggercall,
raise_exception
)
else:
queryselector = queryselector + ".querySelector('" + _prepare_selector(locator_list[i]) + "').shadowRoot"
if not debug:
shadowroot = _execute_find_shadowroot(
webdriver,
f"return arguments[0]{queryselector}",
shadowroot,
f"Locatorlist {locator_list} contains invalid/not unique locator to a shadowDOM host.",
loggercall,
raise_exception
)
return shadowroot
err_msg = f"Locatorlist {locator_list} is empty."
if loggercall is not None:
loggercall(err_msg)
if raise_exception:
raise utils_seleniumxp.ErrorUtilsSelenium(err_msg)
return None
find_root_shadowdom_simple(webdriver: utils_seleniumxp._RemoteWebDriver, by: utils_seleniumxp.By, value: str) -> utils_seleniumxp._ShadowRoot | None ¶
find_root_shadowdom_simple - find shadowDOM root
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | browser | required |
by | By | locator type of element hosting shadowDOM root | required |
value | str | locator value of element hosting shadowDOM root | required |
Returns:
| Type | Description |
|---|---|
_ShadowRoot | None | Optional[utils_seleniumxp._WebElement]: shadowDOM root if found |
Source code in src/utils_seleniumxp/webdriver_addon.py
def find_root_shadowdom_simple(
webdriver: utils_seleniumxp._RemoteWebDriver,
by: utils_seleniumxp.By,
value: str
) -> utils_seleniumxp._ShadowRoot | None:
"""
find_root_shadowdom_simple - find shadowDOM root
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): browser
by (utils_seleniumxp.By): locator type of element hosting shadowDOM root
value (str): locator value of element hosting shadowDOM root
Returns:
Optional[utils_seleniumxp._WebElement]: shadowDOM root if found
"""
shadowroot = None
if webdriver.is_present(by, value):
shadowhost = webdriver.find_element(by, value)
try:
# shadowroot = webdriver.execute_script("return arguments[0].shadowRoot", shadowhost)
shadowroot = shadowhost.shadow_root
except Exception:
shadowroot = None
return shadowroot
get_user_agent(webdriver: utils_seleniumxp._RemoteWebDriver) -> str ¶
get_user_agent - get user agent via javascript
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
Returns:
| Name | Type | Description |
|---|---|---|
str | str | user agent string |
Source code in src/utils_seleniumxp/webdriver_addon.py
handle_alert(webdriver: utils_seleniumxp._RemoteWebDriver, alerttext: str, accept: bool = False) -> bool ¶
handle_alert - handle alert
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
alerttext | str | alert text | required |
accept | bool | accept yes or no. Defaults to False. | False |
Returns:
| Name | Type | Description |
|---|---|---|
bool | bool | flag if alert was processed successfully or not |
Source code in src/utils_seleniumxp/webdriver_addon.py
def handle_alert(webdriver: utils_seleniumxp._RemoteWebDriver, alerttext: str, accept: bool = False) -> bool:
"""
handle_alert - handle alert
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
alerttext (str): alert text
accept (bool, optional): accept yes or no. Defaults to False.
Returns:
bool: flag if alert was processed successfully or not
"""
if utils_seleniumxp.ExpectedConditions.alert_is_present(): # type: ignore[truthy-function]
try:
alert = webdriver._switch_to.alert
alertmatch = (not alerttext or fnmatch.fnmatch(alert.text, "*" + alerttext + "*"))
if alertmatch:
if accept:
alert.accept()
else:
alert.dismiss()
return True
else:
return False
except utils_seleniumxp.WebDriverExceptions.NoAlertPresentException:
return False
else:
return False
hover_over_element(webdriver: utils_seleniumxp._RemoteWebDriver, by: utils_seleniumxp.By, value: str, by_host: utils_seleniumxp.By | None = None, value_host: str | None = None) -> None ¶
hover_over_element - action chain to hover over element
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
by | By | locator type | required |
value | str | locator value | required |
by_host | By | locator type of shadowhost. Defaults to None. | None |
value_host | str | locator value of shadowhost. Defaults to None. | None |
Source code in src/utils_seleniumxp/webdriver_addon.py
def hover_over_element(
webdriver: utils_seleniumxp._RemoteWebDriver,
by: utils_seleniumxp.By,
value: str,
by_host: utils_seleniumxp.By | None = None,
value_host: str | None = None
) -> None:
"""
hover_over_element - action chain to hover over element
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
by (utils_seleniumxp.By): locator type
value (str): locator value
by_host (utils_seleniumxp.By, optional): locator type of shadowhost. Defaults to None.
value_host (str, optional): locator value of shadowhost. Defaults to None.
"""
if value_host is None:
if webdriver.is_present(by, value):
webelement = webdriver.find_element(by, value)
else:
shadowroot = webdriver.find_root_shadowdom_simple(by_host, value_host)
webelement = webdriver.find_element_shadowdom_simple(by, value, shadowroot)
utils_seleniumxp.WebDriver.ActionChains(webdriver).move_to_element(webelement).perform()
is_element_present(webdriver: utils_seleniumxp._RemoteWebDriver, by: utils_seleniumxp.By, value: str, use_parsel: bool = True) -> bool ¶
is_element_present - check if webelement is present (alternative caller vor _is_present)
Source code in src/utils_seleniumxp/webdriver_addon.py
is_present(webdriver: utils_seleniumxp._RemoteWebDriver, by: utils_seleniumxp.By, value: str, use_parsel: bool = True) -> bool ¶
is_present - check if webelement is present
If element is not present, the standard routine is pretty time-consuming compared to parsel using C implemented lxml library. The overhead caused by the library is comparably slow. However, parsel can only be used for XPATH and CSS.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
by | By | locator type | required |
value | str | locator value | required |
use_parsel | bool | flag to use parsel. Defaults to True. | True |
Returns:
| Name | Type | Description |
|---|---|---|
bool | bool | flag if element is present or not |
Source code in src/utils_seleniumxp/webdriver_addon.py
def is_present(
webdriver: utils_seleniumxp._RemoteWebDriver,
by: utils_seleniumxp.By,
value: str,
use_parsel: bool = True
) -> bool:
"""
is_present - check if webelement is present
If element is not present, the standard routine is pretty time-consuming compared to parsel
using C implemented lxml library. The overhead caused by the library is comparably slow.
However, parsel can only be used for XPATH and CSS.
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
by (utils_seleniumxp.By): locator type
value (str): locator value
use_parsel (bool, optional): flag to use parsel. Defaults to True.
Returns:
bool: flag if element is present or not
"""
if use_parsel and by in {utils_seleniumxp.By.XPATH, utils_seleniumxp.By.CSS_SELECTOR}:
parsedhtml = utils_seleniumxp.locatorutils.parselSelectorExtension(text=webdriver.page_source)
return len(parsedhtml.css_or_xpath(utils_seleniumxp.SeleniumLocator(by, value)).getall()) > 0
else:
# alternative variant -> as slow as try-variant if not present (even slightly slower in case element is present)
# but potentially more errors if descriptor is not unique
# return len(webdriver.find_elements(by, value)) > 0
try:
webdriver.find_element(by, value)
except Exception:
return False
else:
return True
is_present_shadowdom(webdriver: utils_seleniumxp._RemoteWebDriver, locator_list: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator], shadowroot: utils_seleniumxp._ShadowRoot | utils_seleniumxp._WebElement | None = None) -> bool ¶
is_present_shadowdom - check if element is present in shadowDOM
Note: every item in the locator list must be a locator to a host of another shadowDOM root.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
locator_list | list[SeleniumLocator] | locator list | required |
shadowroot | Union[utils_seleniumxp._ShadowRoot, utils_seleniumxp._WebElement]] | shadowDOM root. Defaults to None. | None |
Returns:
| Name | Type | Description |
|---|---|---|
bool | bool | flag if element is present or not |
Source code in src/utils_seleniumxp/webdriver_addon.py
def is_present_shadowdom(
webdriver: utils_seleniumxp._RemoteWebDriver,
locator_list: utils_seleniumxp.SeleniumLocator | list[utils_seleniumxp.SeleniumLocator],
shadowroot: utils_seleniumxp._ShadowRoot | utils_seleniumxp._WebElement | None = None
) -> bool:
"""
is_present_shadowdom - check if element is present in shadowDOM
Note: every item in the locator list must be a locator to a host of another shadowDOM root.
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
locator_list (list[utils_seleniumxp.SeleniumLocator]): locator list
shadowroot (Union[utils_seleniumxp._ShadowRoot, utils_seleniumxp._WebElement]], optional): shadowDOM root. Defaults to None.
Returns:
bool: flag if element is present or not
"""
webelts = find_elements_shadowdom(webdriver, locator_list, shadowroot)
return webelts is not None and webelts != []
last_logentry_wol(webdriver: utils_seleniumxp._RemoteWebDriver) -> dict ¶
last_logentry_wol - retrieve log entry from log of window.open logger
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
Returns:
| Name | Type | Description |
|---|---|---|
dict | dict | log entry |
Source code in src/utils_seleniumxp/webdriver_addon.py
def last_logentry_wol(webdriver: utils_seleniumxp._RemoteWebDriver) -> dict:
"""
last_logentry_wol - retrieve log entry from log of window.open logger
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
Returns:
dict: log entry
"""
return webdriver.execute_script("return window.WindowOpenLogger('last');")
log_wol(webdriver: utils_seleniumxp._RemoteWebDriver) -> list[dict] ¶
log_wol - retrieve complete log of window.open logger
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
Returns:
| Type | Description |
|---|---|
list[dict] | list[dict]: list of log entries |
Source code in src/utils_seleniumxp/webdriver_addon.py
def log_wol(webdriver: utils_seleniumxp._RemoteWebDriver) -> list[dict]:
"""
log_wol - retrieve complete log of window.open logger
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
Returns:
list[dict]: list of log entries
"""
return webdriver.execute_script("return window.WindowOpenLogger('log');")
status_wol(webdriver: utils_seleniumxp._RemoteWebDriver) -> dict ¶
status_wol - status of window.open logger
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
Returns:
| Name | Type | Description |
|---|---|---|
dict | dict | status information |
Source code in src/utils_seleniumxp/webdriver_addon.py
wait4AJAX(webdriver: utils_seleniumxp._RemoteWebDriver, timeout: int = 10, min_wait: float = 0.5) -> bool ¶
wait4AJAX - wait routine checking jQuery.active via JavaScript and document.readyState
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
timeout | int | timeout | 10 |
min_wait | float | minimum wait time. Defaults to 0.5. | 0.5 |
Returns:
| Name | Type | Description |
|---|---|---|
bool | bool | flag if timeout reached |
Source code in src/utils_seleniumxp/webdriver_addon.py
def wait4AJAX(webdriver: utils_seleniumxp._RemoteWebDriver, timeout: int = 10, min_wait: float = 0.5) -> bool:
"""
wait4AJAX - wait routine checking jQuery.active via JavaScript and document.readyState
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
timeout (int): timeout
min_wait (float, optional): minimum wait time. Defaults to 0.5.
Returns:
bool: flag if timeout reached
"""
starttime = time.time()
timeoutscript = False
try:
utils_seleniumxp.WebDriverWait(webdriver, 1).until(lambda webdriver: webdriver.execute_script('return jQuery.active') == 0)
except (utils_seleniumxp.WebDriverExceptions.JavascriptException, utils_seleniumxp.WebDriverExceptions.TimeoutException):
pass
else:
try:
utils_seleniumxp.WebDriverWait(webdriver, timeout).until(lambda webdriver: webdriver.execute_script('return jQuery.active') == 0)
except utils_seleniumxp.WebDriverExceptions.TimeoutException:
timeoutscript = True
timeoutdocrs = False
try:
utils_seleniumxp.WebDriverWait(webdriver, timeout).until(lambda webdriver: webdriver.execute_script('return document.readyState') == 'complete')
except utils_seleniumxp.WebDriverExceptions.TimeoutException:
timeoutdocrs = True
while (time.time() < starttime + min_wait):
time.sleep(0.1)
return timeoutscript or timeoutdocrs
wait4HTMLstable(webdriver: utils_seleniumxp._RemoteWebDriver, wait: float = 0.1, max_wait: float = 0.5) -> bool ¶
wait4HTMLstable - wait routine checking stability page source
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
wait | float | wait between re-checks. Defaults to 0.1. | 0.1 |
max_wait | float | timeout. Defaults to 0.5. | 0.5 |
Returns:
| Name | Type | Description |
|---|---|---|
bool | bool | flag if page source is stable |
Source code in src/utils_seleniumxp/webdriver_addon.py
def wait4HTMLstable(webdriver: utils_seleniumxp._RemoteWebDriver, wait: float = 0.1, max_wait: float = 0.5) -> bool:
"""
wait4HTMLstable - wait routine checking stability page source
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
wait (float, optional): wait between re-checks. Defaults to 0.1.
max_wait (float, optional): timeout. Defaults to 0.5.
Returns:
bool: flag if page source is stable
"""
wait4AJAX(webdriver)
HTMLprev = ""
starttime = time.time()
while (HTMLprev != webdriver.page_source and (time.time() < starttime + max_wait)):
HTMLprev = webdriver.page_source
time.sleep(wait)
return HTMLprev == webdriver.page_source
wait_for_page_load(webdriver: utils_seleniumxp._RemoteWebDriver, timeout=10) -> Generator ¶
wait_for_page_load - wait routine with contextmanager from ObeyTheTestingGoat
method checks for the staleness of the old page (i.e., that the new page has loaded) prior to moving forward with further actions. Therefore, it only works in situations where the URL changes between page loads.
Usage: with self.wait_for_page_load(): click a button or do whatever do the next thing that was failing before using this
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
timeout | int | timeout. Defaults to 10. | 10 |
Return
(Generator): contextmanager generator
Source code in src/utils_seleniumxp/webdriver_addon.py
@contextlib.contextmanager
def wait_for_page_load(webdriver: utils_seleniumxp._RemoteWebDriver, timeout=10) -> Generator:
"""
wait_for_page_load - wait routine with contextmanager from ObeyTheTestingGoat
method checks for the staleness of the old page (i.e., that the new page has loaded)
prior to moving forward with further actions. Therefore, it only works in situations
where the URL changes between page loads.
Usage:
with self.wait_for_page_load():
click a button or do whatever
do the next thing that was failing before using this
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
timeout (int, optional): timeout. Defaults to 10.
Return:
(Generator): contextmanager generator
"""
old_page = webdriver.find_element(utils_seleniumxp.By.TAG_NAME, 'html')
yield
utils_seleniumxp.WebDriverWait(webdriver, timeout).until(utils_seleniumxp.ExpectedConditions.staleness_of(old_page))
window_open_logger(webdriver: utils_seleniumxp._RemoteWebDriver) -> None ¶
window_open_logger - inject javascript for window.open logger
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
webdriver | _RemoteWebDriver | webdriver | required |
Source code in src/utils_seleniumxp/webdriver_addon.py
def window_open_logger(webdriver: utils_seleniumxp._RemoteWebDriver) -> None:
"""
window_open_logger - inject javascript for window.open logger
Args:
webdriver (utils_seleniumxp._RemoteWebDriver): webdriver
"""
script_wol = """
window.WindowOpenLogger = function(action) {
// internal init
window.__openLog ||= [];
switch (action) {
case 'enable':
if (window.__openLoggerEnabled) return true;
// save org function once
const originalOpen = window.open;
// proxy instead of override
window.open = new Proxy(originalOpen, {
apply(target, thisArg, args) {
const [url, targetName, features] = args;
const entry = {
timestamp: new Date().toISOString(),
url,
target: targetName,
features
};
window.__openLog.push(entry);
console.log('window.open:', url);
return Reflect.apply(target, thisArg, args);
}
});
window.__originalWindowOpen = originalOpen;
window.__openLoggerEnabled = true;
return true;
case 'disable':
if (!window.__openLoggerEnabled) return true;
if (window.__originalWindowOpen) {
window.open = window.__originalWindowOpen;
}
window.__openLoggerEnabled = false;
return true;
case 'last':
return (window.__openLog || []).length ? window.__openLog[window.__openLog.length - 1] : null;
case 'log':
return window.__openLog || [];
case 'clear':
window.__openLog = [];
return true;
case 'status':
return {
enabled: !!window.__openLoggerEnabled,
entries: (window.__openLog || []).length
};
default:
throw new Error('Valid actions: enable, disable, last, log, clear, status');
}
}
"""
webdriver.wait4HTMLstable()
webdriver.execute_script(script_wol)