@@ -151,6 +151,8 @@ def stop_browser(self):
151151 """
152152 Stops the Chrome browser and clean up the User Data Directory.
153153 """
154+ if not self ._driver :
155+ return
154156 self ._driver .quit ()
155157 self ._driver = None
156158
@@ -603,16 +605,24 @@ def page_source(self):
603605 except InvalidSessionIdException :
604606 return None
605607
606- def navigate_to (self , url ):
608+ def navigate_to (self , url , is_retry = False ):
607609 """
608610 Opens the browser on the given URL.
609611
610612 Args:
611613 url (str): The URL to be visited.
614+ is_retry (bool): Whether or not this is a retry attempt.
612615 """
616+ self ._x = 0
617+ self ._y = 0
613618 if not self ._driver :
614619 self .start_browser ()
615- self ._driver .get (url )
620+ try :
621+ self ._driver .get (url )
622+ except InvalidSessionIdException :
623+ if not is_retry :
624+ self .stop_browser ()
625+ self .navigate_to (url , is_retry = True )
616626
617627 def browse (self , url ):
618628 """
@@ -750,10 +760,12 @@ def mouse_move(self, x, y):
750760 y (int): The Y coordinate
751761
752762 """
753- ActionChains (self ._driver ).move_by_offset (- self ._x , - self ._y ).perform ()
763+ # ActionChains(self._driver).move_by_offset(-self._x, -self._y).perform()
764+ mx = x - self ._x
765+ my = y - self ._y
754766 self ._x = x
755767 self ._y = y
756- ActionChains (self ._driver ).move_by_offset (x , y ).perform ()
768+ ActionChains (self ._driver ).move_by_offset (mx , my ).perform ()
757769
758770 def click_at (self , x , y , * , clicks = 1 , interval_between_clicks = 0 , button = 'left' ):
759771 """
@@ -859,6 +871,28 @@ def triple_click_relative(self, x, y, interval_between_clicks=0, wait_after=conf
859871 """
860872 self .click_relative (x , y , wait_after = wait_after , click = 3 , interval_between_clicks = interval_between_clicks )
861873
874+ def mouse_down (self , wait_after = config .DEFAULT_SLEEP_AFTER_ACTION , * , button = 'left' ):
875+ """
876+ Holds down the requested mouse button.
877+
878+ Args:
879+ wait_after (int, optional): Interval to wait after clicking on the element.
880+ button (str, optional): One of 'left', 'right', 'middle'. Defaults to 'left'
881+ """
882+ ActionChains (self ._driver ).click_and_hold ().perform ()
883+ self .sleep (wait_after )
884+
885+ def mouse_up (self , wait_after = config .DEFAULT_SLEEP_AFTER_ACTION , * , button = 'left' ):
886+ """
887+ Releases the requested mouse button.
888+
889+ Args:
890+ wait_after (int, optional): Interval to wait after clicking on the element.
891+ button (str, optional): One of 'left', 'right', 'middle'. Defaults to 'left'
892+ """
893+ ActionChains (self ._driver ).release ().perform ()
894+ self .sleep (wait_after )
895+
862896 def scroll_down (self , clicks ):
863897 """
864898 Scroll Down n clicks
@@ -1072,6 +1106,7 @@ def key_home(self, wait=0):
10721106 wait (int, optional): Wait interval (ms) after task
10731107
10741108 """
1109+ # TODO: Investigate why with Firefox the key isn't working properly
10751110 action = ActionChains (self ._driver )
10761111 action .key_down (Keys .HOME )
10771112 action .key_up (Keys .HOME )
@@ -1102,6 +1137,7 @@ def page_up(self, wait=0):
11021137 wait (int, optional): Wait interval (ms) after task
11031138
11041139 """
1140+ # TODO: Investigate why with Firefox the key isn't working properly
11051141 action = ActionChains (self ._driver )
11061142 action .key_down (Keys .PAGE_UP )
11071143 action .key_up (Keys .PAGE_UP )
@@ -1117,6 +1153,7 @@ def page_down(self, wait=0):
11171153 wait (int, optional): Wait interval (ms) after task
11181154
11191155 """
1156+ # TODO: Investigate why with Firefox the key isn't working properly
11201157 action = ActionChains (self ._driver )
11211158 action .key_down (Keys .PAGE_DOWN )
11221159 action .key_up (Keys .PAGE_DOWN )
@@ -1223,7 +1260,18 @@ def control_c(self, wait=0):
12231260 wait (int, optional): Wait interval (ms) after task
12241261
12251262 """
1226- self ._clipboard = self .execute_javascript ("return window.getSelection().toString();" )
1263+ # Firefox can't do window.getSelection() and return a proper value when the selected text
1264+ # is in an input of similar. While Firefox doesn't get its shit together we apply this
1265+ # ugly alternative so control+c works for "all" browsers tested so far.
1266+ cmd = """
1267+ try {
1268+ return document.activeElement.value.substring(document.activeElement.selectionStart,document.activeElement.selectionEnd);
1269+ } catch(error) {
1270+ return window.getSelection().toString();
1271+ }
1272+ """
1273+
1274+ self ._clipboard = self .execute_javascript (cmd )
12271275 delay = max (0 , wait or config .DEFAULT_SLEEP_AFTER_ACTION )
12281276 self .sleep (delay )
12291277
0 commit comments