Skip to content

Commit 9756ead

Browse files
committed
FIX: Make sure we can still navigate after closing the last tab.
FIX: Control+C now works with Firefox as well and overcomes the window.getSelection bug.
1 parent 298605c commit 9756ead

File tree

1 file changed

+53
-5
lines changed

1 file changed

+53
-5
lines changed

botcity/web/bot.py

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)