1717from PIL import Image
1818from selenium .common .exceptions import InvalidSessionIdException
1919from selenium .webdriver .common .action_chains import ActionChains
20+ from selenium .common .exceptions import StaleElementReferenceException
2021from selenium .webdriver .common .by import By
2122from selenium .webdriver .common .keys import Keys
2223from selenium .webdriver .remote .webelement import WebElement
@@ -61,14 +62,15 @@ def __init__(self, headless=False):
6162 self ._clipboard = ""
6263
6364 # Stub mouse coordinates
65+ self ._html_elem = None
6466 self ._x = 0
6567 self ._y = 0
6668
6769 # State for Key modifiers
6870 self ._shift_hold = False
6971
7072 self ._dimensions = (1600 , 900 )
71- self ._download_folder_path = os .path . join ( os . path . expanduser ( "~" ), "Desktop" )
73+ self ._download_folder_path = os .getcwd ( )
7274
7375 @property
7476 def driver (self ):
@@ -94,6 +96,7 @@ def driver_path(self, driver_path):
9496 driver_path (str): The full path to the proper webdriver path used for the selected browser.
9597 If set to None, the code will look into the PATH for the proper file when starting the browser.
9698 """
99+ driver_path = os .path .abspath (os .path .expanduser (os .path .expandvars (driver_path )))
97100 if driver_path and not os .path .isfile (driver_path ):
98101 raise ValueError ("Invalid driver_path. The file does not exist." )
99102 self ._driver_path = driver_path
@@ -943,14 +946,17 @@ def print_pdf(self, path=None, print_options=None):
943946 str: the saved file path
944947 """
945948 title = self .page_title () or "document"
946- default_path = os .path .expanduser (os .path .join ("~" , "Desktop" , f"{ title } .pdf" ))
949+ timeout = 60000
950+ if not self .page_title ():
951+ timeout = 1000
952+ default_path = os .path .expanduser (os .path .join (self .download_folder_path , f"{ title } .pdf" ))
947953
948954 if self .browser in [Browser .CHROME , Browser .EDGE ] and not self .headless :
949955 # Chrome still does not support headless webdriver print
950956 # but Firefox does.
951957 self .execute_javascript ("window.print();" )
952958 # We need to wait for the file to be available in this case.
953- self .wait_for_file (default_path )
959+ self .wait_for_file (default_path , timeout = timeout )
954960 return default_path
955961
956962 if print_options is None :
@@ -973,6 +979,7 @@ def print_pdf(self, path=None, print_options=None):
973979 def wait_for_downloads (self , timeout : int = 120000 ):
974980 """
975981 Wait for all downloads to be finished.
982+ Beware that this method replaces the current page with the downloads window.
976983
977984 Args:
978985 timeout (int, optional): Timeout in millis. Defaults to 120000.
@@ -994,7 +1001,7 @@ def find_elements(self, selector: str, by: By = By.CSS_SELECTOR) -> List[WebElem
9941001
9951002 **Example:**
9961003 ```python
997- from botcity.web.bot import By
1004+ from botcity.web import By
9981005 ...
9991006 # Find element by ID
10001007 all_cells = self.find_elements("//td", By.XPATH)
@@ -1017,7 +1024,7 @@ def find_element(self, selector: str, by: str = By.CSS_SELECTOR) -> WebElement:
10171024
10181025 **Example:**
10191026 ```python
1020- from botcity.web.bot import By
1027+ from botcity.web import By
10211028 ...
10221029 # Find element by ID
10231030 elem = self.find_element("my_elem", By.ID)
@@ -1106,7 +1113,20 @@ def mouse_move(self, x, y):
11061113 y (int): The Y coordinate
11071114
11081115 """
1109- # ActionChains(self._driver).move_by_offset(-self._x, -self._y).perform()
1116+ if self .browser == Browser .FIREFOX :
1117+ # Reset coordinates if the page has gone stale. Only required for Firefox
1118+ if self ._html_elem is None :
1119+ self ._html_elem = self ._driver .find_element_by_tag_name ('body' )
1120+ self ._x = 0
1121+ self ._y = 0
1122+ else :
1123+ try :
1124+ self ._html_elem .is_enabled ()
1125+ except StaleElementReferenceException :
1126+ self ._html_elem = self ._driver .find_element_by_tag_name ('body' )
1127+ self ._x = 0
1128+ self ._y = 0
1129+
11101130 mx = x - self ._x
11111131 my = y - self ._y
11121132 self ._x = x
@@ -1798,6 +1818,7 @@ def wait_for_file(self, path, timeout=60000):
17981818 status (bool): Whether or not the file was available before the timeout
17991819
18001820 """
1821+ path = os .path .abspath (os .path .expanduser (os .path .expandvars (path )))
18011822 start_time = time .time ()
18021823
18031824 while True :
0 commit comments