seleniumbase 4.43.2__py3-none-any.whl → 4.44.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
1
  # seleniumbase package
2
- __version__ = "4.43.2"
2
+ __version__ = "4.44.0"
@@ -28,6 +28,10 @@ from seleniumbase import decorators
28
28
  from seleniumbase import drivers # webdriver storage folder for SeleniumBase
29
29
  from seleniumbase.drivers import cft_drivers # chrome-for-testing
30
30
  from seleniumbase.drivers import chs_drivers # chrome-headless-shell
31
+ from seleniumbase.drivers import opera_drivers # still uses chromedriver
32
+ from seleniumbase.drivers import brave_drivers # still uses chromedriver
33
+ from seleniumbase.drivers import comet_drivers # still uses chromedriver
34
+ from seleniumbase.drivers import atlas_drivers # still uses chromedriver
31
35
  from seleniumbase import extensions # browser extensions storage folder
32
36
  from seleniumbase.config import settings
33
37
  from seleniumbase.core import detect_b_ver
@@ -44,6 +48,10 @@ urllib3.disable_warnings()
44
48
  DRIVER_DIR = os.path.dirname(os.path.realpath(drivers.__file__))
45
49
  DRIVER_DIR_CFT = os.path.dirname(os.path.realpath(cft_drivers.__file__))
46
50
  DRIVER_DIR_CHS = os.path.dirname(os.path.realpath(chs_drivers.__file__))
51
+ DRIVER_DIR_OPERA = os.path.dirname(os.path.realpath(opera_drivers.__file__))
52
+ DRIVER_DIR_BRAVE = os.path.dirname(os.path.realpath(brave_drivers.__file__))
53
+ DRIVER_DIR_COMET = os.path.dirname(os.path.realpath(comet_drivers.__file__))
54
+ DRIVER_DIR_ATLAS = os.path.dirname(os.path.realpath(atlas_drivers.__file__))
47
55
  # Make sure that the SeleniumBase DRIVER_DIR is at the top of the System PATH
48
56
  # (Changes to the System PATH with os.environ only last during the test run)
49
57
  if not os.environ["PATH"].startswith(DRIVER_DIR):
@@ -543,6 +551,19 @@ def uc_open_with_tab(driver, url):
543
551
 
544
552
  def uc_open_with_reconnect(driver, url, reconnect_time=None):
545
553
  """Open a url, disconnect chromedriver, wait, and reconnect."""
554
+ if (
555
+ hasattr(sb_config, "_cdp_browser")
556
+ and sb_config._cdp_browser in ["comet", "opera", "atlas"]
557
+ ):
558
+ if not __is_cdp_swap_needed(driver):
559
+ if not driver.current_url.startswith(
560
+ ("about", "data", "chrome")
561
+ ):
562
+ driver.get("about:blank")
563
+ uc_activate_cdp_mode(driver, url)
564
+ else:
565
+ driver.cdp.open(url)
566
+ return
546
567
  url = shared_utils.fix_url_as_needed(url)
547
568
  if __is_cdp_swap_needed(driver):
548
569
  driver.cdp.get(url)
@@ -877,6 +898,7 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs):
877
898
  cdp.assert_not_in = CDPM.assert_not_in
878
899
  cdp.scroll_into_view = CDPM.scroll_into_view
879
900
  cdp.scroll_to_y = CDPM.scroll_to_y
901
+ cdp.scroll_by_y = CDPM.scroll_by_y
880
902
  cdp.scroll_to_top = CDPM.scroll_to_top
881
903
  cdp.scroll_to_bottom = CDPM.scroll_to_bottom
882
904
  cdp.scroll_up = CDPM.scroll_up
@@ -1218,8 +1240,8 @@ def uc_gui_click_x_y(driver, x, y, timeframe=0.25):
1218
1240
  driver.cdp.minimize()
1219
1241
  driver.cdp.set_window_rect(win_x, win_y, width, height)
1220
1242
  if IS_WINDOWS:
1221
- x = x * width_ratio
1222
- y = y * width_ratio
1243
+ x = x * (width_ratio + 0.03)
1244
+ y = y * (width_ratio - 0.03)
1223
1245
  _uc_gui_click_x_y(driver, x, y, timeframe=timeframe, uc_lock=False)
1224
1246
  return
1225
1247
  with suppress(Exception):
@@ -1260,7 +1282,7 @@ def _uc_gui_click_captcha(
1260
1282
  ctype=None,
1261
1283
  ):
1262
1284
  cdp_mode_on_at_start = __is_cdp_swap_needed(driver)
1263
- if cdp_mode_on_at_start and (not ctype or ctype == "cf_t"):
1285
+ if cdp_mode_on_at_start:
1264
1286
  return driver.cdp.gui_click_captcha()
1265
1287
  _on_a_captcha_page = None
1266
1288
  if ctype == "cf_t":
@@ -1952,6 +1974,15 @@ def get_valid_binary_names_for_browser(browser):
1952
1974
  raise Exception("Invalid combination for OS browser binaries!")
1953
1975
 
1954
1976
 
1977
+ def _special_binary_exists(location, name):
1978
+ filename = str(location).split("/")[-1].split("\\")[-1]
1979
+ return (
1980
+ location
1981
+ and str(name).lower() in filename.lower()
1982
+ and os.path.exists(location)
1983
+ )
1984
+
1985
+
1955
1986
  def _repair_chromedriver(chrome_options, headless_options, mcv=None):
1956
1987
  if mcv:
1957
1988
  subprocess.check_call(
@@ -2960,6 +2991,18 @@ def get_driver(
2960
2991
  and sb_config.binary_location == "chs"
2961
2992
  ):
2962
2993
  driver_dir = DRIVER_DIR_CHS
2994
+ if _special_binary_exists(binary_location, "opera"):
2995
+ driver_dir = DRIVER_DIR_OPERA
2996
+ sb_config._cdp_browser = "opera"
2997
+ if _special_binary_exists(binary_location, "brave"):
2998
+ driver_dir = DRIVER_DIR_BRAVE
2999
+ sb_config._cdp_browser = "brave"
3000
+ if _special_binary_exists(binary_location, "comet"):
3001
+ driver_dir = DRIVER_DIR_COMET
3002
+ sb_config._cdp_browser = "comet"
3003
+ if _special_binary_exists(binary_location, "atlas"):
3004
+ driver_dir = DRIVER_DIR_ATLAS
3005
+ sb_config._cdp_browser = "atlas"
2963
3006
  if (
2964
3007
  hasattr(sb_config, "settings")
2965
3008
  and hasattr(sb_config.settings, "NEW_DRIVER_DIR")
@@ -2972,6 +3015,8 @@ def get_driver(
2972
3015
  browser_name = browser
2973
3016
  else:
2974
3017
  browser_name = "chrome" # The default if not specified
3018
+ if browser_name in constants.ChromiumSubs.chromium_subs:
3019
+ browser_name = "chrome"
2975
3020
  browser_name = browser_name.lower()
2976
3021
  if headless2 and browser_name == constants.Browser.FIREFOX:
2977
3022
  headless2 = False # Only for Chromium
@@ -3919,6 +3964,18 @@ def get_local_driver(
3919
3964
  ):
3920
3965
  special_chrome = True
3921
3966
  driver_dir = DRIVER_DIR_CHS
3967
+ if _special_binary_exists(binary_location, "opera"):
3968
+ special_chrome = True
3969
+ driver_dir = DRIVER_DIR_OPERA
3970
+ if _special_binary_exists(binary_location, "brave"):
3971
+ special_chrome = True
3972
+ driver_dir = DRIVER_DIR_BRAVE
3973
+ if _special_binary_exists(binary_location, "comet"):
3974
+ special_chrome = True
3975
+ driver_dir = DRIVER_DIR_COMET
3976
+ if _special_binary_exists(binary_location, "atlas"):
3977
+ special_chrome = True
3978
+ driver_dir = DRIVER_DIR_ATLAS
3922
3979
  if (
3923
3980
  hasattr(sb_config, "settings")
3924
3981
  and hasattr(sb_config.settings, "NEW_DRIVER_DIR")
@@ -4756,6 +4813,27 @@ def get_local_driver(
4756
4813
  )
4757
4814
  return extend_driver(driver)
4758
4815
  elif browser_name == constants.Browser.GOOGLE_CHROME:
4816
+ set_chromium = None
4817
+ if _special_binary_exists(binary_location, "opera"):
4818
+ set_chromium = "opera"
4819
+ local_chromedriver = DRIVER_DIR_OPERA + "/chromedriver"
4820
+ if IS_WINDOWS:
4821
+ local_chromedriver = DRIVER_DIR_OPERA + "/chromedriver.exe"
4822
+ if _special_binary_exists(binary_location, "brave"):
4823
+ set_chromium = "brave"
4824
+ local_chromedriver = DRIVER_DIR_BRAVE + "/chromedriver"
4825
+ if IS_WINDOWS:
4826
+ local_chromedriver = DRIVER_DIR_BRAVE + "/chromedriver.exe"
4827
+ if _special_binary_exists(binary_location, "comet"):
4828
+ set_chromium = "comet"
4829
+ local_chromedriver = DRIVER_DIR_COMET + "/chromedriver"
4830
+ if IS_WINDOWS:
4831
+ local_chromedriver = DRIVER_DIR_COMET + "/chromedriver.exe"
4832
+ if _special_binary_exists(binary_location, "atlas"):
4833
+ set_chromium = "atlas"
4834
+ local_chromedriver = DRIVER_DIR_ATLAS + "/chromedriver"
4835
+ if IS_WINDOWS:
4836
+ local_chromedriver = DRIVER_DIR_ATLAS + "/chromedriver.exe"
4759
4837
  try:
4760
4838
  chrome_options = _set_chrome_options(
4761
4839
  browser_name,
@@ -4877,6 +4955,12 @@ def get_local_driver(
4877
4955
  major_chrome_version = None
4878
4956
  if major_chrome_version:
4879
4957
  use_version = major_chrome_version
4958
+ if (
4959
+ set_chromium == "opera"
4960
+ and use_version.isnumeric()
4961
+ and int(use_version) < 130
4962
+ ):
4963
+ use_version = "130" # Special case
4880
4964
  ch_driver_version = None
4881
4965
  path_chromedriver = chromedriver_on_path()
4882
4966
  if os.path.exists(local_chromedriver):
@@ -4894,7 +4978,7 @@ def get_local_driver(
4894
4978
  ch_driver_version = output
4895
4979
  if driver_version == "keep":
4896
4980
  driver_version = ch_driver_version
4897
- elif path_chromedriver:
4981
+ elif path_chromedriver and not set_chromium:
4898
4982
  try:
4899
4983
  make_driver_executable_if_not(path_chromedriver)
4900
4984
  except Exception as e:
@@ -278,11 +278,12 @@ def opera_on_windows_path(browser_type=None):
278
278
  ),
279
279
  ):
280
280
  for subitem in (
281
+ "Programs/Opera",
281
282
  "Opera",
282
283
  "Opera/Application",
283
284
  ):
284
285
  try:
285
- candidates.append(os.sep.join((item, subitem, "launcher.exe")))
286
+ candidates.append(os.sep.join((item, subitem, "opera.exe")))
286
287
  except TypeError:
287
288
  pass
288
289
  for candidate in candidates:
@@ -336,6 +337,7 @@ def comet_on_windows_path(browser_type=None):
336
337
  ):
337
338
  for subitem in (
338
339
  "Comet/Application",
340
+ "Programs/Comet",
339
341
  ):
340
342
  try:
341
343
  candidates.append(os.sep.join((item, subitem, "Comet.exe")))
@@ -364,6 +366,7 @@ def atlas_on_windows_path(browser_type=None):
364
366
  ):
365
367
  for subitem in (
366
368
  "Atlas/Application",
369
+ "Programs/Atlas",
367
370
  ):
368
371
  try:
369
372
  candidates.append(os.sep.join((item, subitem, "Atlas.exe")))
@@ -1029,12 +1029,19 @@ class CDPMethods():
1029
1029
  return self.loop.run_until_complete(self.page.js_dumps(obj_name))
1030
1030
 
1031
1031
  def maximize(self):
1032
- if self.get_window()[1].window_state.value == "maximized":
1033
- return
1034
- elif self.get_window()[1].window_state.value == "minimized":
1035
- self.loop.run_until_complete(self.page.maximize())
1036
- time.sleep(0.044)
1037
- return self.loop.run_until_complete(self.page.maximize())
1032
+ try:
1033
+ if self.get_window()[1].window_state.value == "maximized":
1034
+ return
1035
+ elif self.get_window()[1].window_state.value == "minimized":
1036
+ self.loop.run_until_complete(self.page.maximize())
1037
+ time.sleep(0.044)
1038
+ return self.loop.run_until_complete(self.page.maximize())
1039
+ except Exception:
1040
+ with suppress(Exception):
1041
+ width = self.evaluate("screen.availWidth;")
1042
+ height = self.evaluate("screen.availHeight;")
1043
+ self.__set_window_rect(0, 0, width, height)
1044
+ return
1038
1045
 
1039
1046
  def minimize(self):
1040
1047
  if self.get_window()[1].window_state.value != "minimized":
@@ -1333,6 +1340,17 @@ class CDPMethods():
1333
1340
  x = window_rect["x"] + element_rect["x"]
1334
1341
  y = w_bottom_y - viewport_height + element_rect["y"]
1335
1342
  y_scroll_offset = window_rect["pageYOffset"]
1343
+ if (
1344
+ hasattr(sb_config, "_cdp_browser")
1345
+ and sb_config._cdp_browser == "opera"
1346
+ ):
1347
+ # Handle special case where Opera side panel shifts coordinates
1348
+ x_offset = window_rect["outerWidth"] - window_rect["innerWidth"]
1349
+ if x_offset > 56:
1350
+ x_offset = 56
1351
+ elif x_offset < 22:
1352
+ x_offset = 0
1353
+ x = x + x_offset
1336
1354
  y = y - y_scroll_offset
1337
1355
  x = x + window_rect["scrollX"]
1338
1356
  y = y + window_rect["scrollY"]
@@ -1674,11 +1692,6 @@ class CDPMethods():
1674
1692
  import pyautogui
1675
1693
  pyautogui = self.__get_configured_pyautogui(pyautogui)
1676
1694
  screen_width, screen_height = pyautogui.size()
1677
- if (
1678
- hasattr(sb_config, "_cdp_browser")
1679
- and sb_config._cdp_browser == "opera"
1680
- ):
1681
- x = x + 55
1682
1695
  if x < 0 or y < 0 or x > screen_width or y > screen_height:
1683
1696
  raise Exception(
1684
1697
  "PyAutoGUI cannot click on point (%s, %s)"
@@ -1719,20 +1732,20 @@ class CDPMethods():
1719
1732
  win_x = window_rect["x"]
1720
1733
  win_y = window_rect["y"]
1721
1734
  scr_width = pyautogui.size().width
1722
- self.maximize()
1723
- self.__add_light_pause()
1724
- win_width = self.get_window_size()["width"]
1735
+ win_width = self.evaluate("screen.availWidth;")
1725
1736
  width_ratio = round(float(scr_width) / float(win_width), 2)
1726
1737
  width_ratio += 0.01
1727
1738
  if width_ratio < 0.45 or width_ratio > 2.55:
1728
1739
  width_ratio = 1.01
1729
1740
  sb_config._saved_width_ratio = width_ratio
1730
- self.minimize()
1731
- self.__add_light_pause()
1732
- self.__set_window_rect(win_x, win_y, width, height)
1733
- self.__add_light_pause()
1734
- x = x * width_ratio
1735
- y = y * width_ratio
1741
+ with suppress(Exception):
1742
+ self.get_window() # If this fails, skip the rest
1743
+ self.minimize()
1744
+ self.__add_light_pause()
1745
+ self.__set_window_rect(win_x, win_y, width, height)
1746
+ self.__add_light_pause()
1747
+ x = x * (width_ratio + 0.03)
1748
+ y = y * (width_ratio - 0.03)
1736
1749
  self.bring_active_window_to_front()
1737
1750
  self.__gui_click_x_y(x, y, timeframe=timeframe, uc_lock=False)
1738
1751
 
@@ -1760,8 +1773,43 @@ class CDPMethods():
1760
1773
  return True
1761
1774
  return False
1762
1775
 
1776
+ def _on_a_g_recaptcha_page(self):
1777
+ time.sleep(0.042)
1778
+ source = self.get_page_source()
1779
+ if not source or len(source) < 400:
1780
+ time.sleep(0.22)
1781
+ source = self.get_page_source()
1782
+ if (
1783
+ 'id="recaptcha-token"' in source
1784
+ or 'title="reCAPTCHA"' in source
1785
+ ):
1786
+ return True
1787
+ return False
1788
+
1789
+ def __gui_click_recaptcha(self):
1790
+ selector = None
1791
+ if self.is_element_visible('iframe[title="reCAPTCHA"]'):
1792
+ selector = 'iframe[title="reCAPTCHA"]'
1793
+ else:
1794
+ return
1795
+ with suppress(Exception):
1796
+ time.sleep(0.08)
1797
+ element_rect = self.get_gui_element_rect(selector, timeout=1)
1798
+ e_x = element_rect["x"]
1799
+ e_y = element_rect["y"]
1800
+ x = e_x + 29
1801
+ y = e_y + 35
1802
+ sb_config._saved_cf_x_y = (x, y)
1803
+ time.sleep(0.08)
1804
+ self.gui_click_x_y(x, y)
1805
+
1763
1806
  def gui_click_captcha(self):
1764
- if not self._on_a_cf_turnstile_page():
1807
+ if self._on_a_cf_turnstile_page():
1808
+ pass
1809
+ elif self._on_a_g_recaptcha_page():
1810
+ self.__gui_click_recaptcha()
1811
+ return
1812
+ else:
1765
1813
  return
1766
1814
  selector = None
1767
1815
  if (
@@ -1926,7 +1974,7 @@ class CDPMethods():
1926
1974
  if not shared_utils.is_windows():
1927
1975
  y = e_y + 32
1928
1976
  else:
1929
- y = e_y + 22
1977
+ y = e_y + 28
1930
1978
  sb_config._saved_cf_x_y = (x, y)
1931
1979
  time.sleep(0.08)
1932
1980
  self.gui_click_x_y(x, y)
@@ -1936,12 +1984,6 @@ class CDPMethods():
1936
1984
  import pyautogui
1937
1985
  pyautogui = self.__get_configured_pyautogui(pyautogui)
1938
1986
  screen_width, screen_height = pyautogui.size()
1939
- if (
1940
- hasattr(sb_config, "_cdp_browser")
1941
- and sb_config._cdp_browser == "opera"
1942
- ):
1943
- x1 = x1 + 55
1944
- x2 = x2 + 55
1945
1987
  if x1 < 0 or y1 < 0 or x1 > screen_width or y1 > screen_height:
1946
1988
  raise Exception(
1947
1989
  "PyAutoGUI cannot drag-drop from point (%s, %s)"
@@ -1986,18 +2028,18 @@ class CDPMethods():
1986
2028
  win_x = window_rect["x"]
1987
2029
  win_y = window_rect["y"]
1988
2030
  scr_width = pyautogui.size().width
1989
- self.maximize()
1990
- self.__add_light_pause()
1991
- win_width = self.get_window_size()["width"]
2031
+ win_width = self.evaluate("screen.availWidth;")
1992
2032
  width_ratio = round(float(scr_width) / float(win_width), 2)
1993
2033
  width_ratio += 0.01
1994
2034
  if width_ratio < 0.45 or width_ratio > 2.55:
1995
2035
  width_ratio = 1.01
1996
2036
  sb_config._saved_width_ratio = width_ratio
1997
- self.minimize()
1998
- self.__add_light_pause()
1999
- self.__set_window_rect(win_x, win_y, width, height)
2000
- self.__add_light_pause()
2037
+ with suppress(Exception):
2038
+ self.get_window() # If this fails, skip the rest
2039
+ self.minimize()
2040
+ self.__add_light_pause()
2041
+ self.__set_window_rect(win_x, win_y, width, height)
2042
+ self.__add_light_pause()
2001
2043
  x1 = x1 * width_ratio
2002
2044
  y1 = y1 * (width_ratio - 0.02)
2003
2045
  x2 = x2 * width_ratio
@@ -2033,11 +2075,6 @@ class CDPMethods():
2033
2075
  import pyautogui
2034
2076
  pyautogui = self.__get_configured_pyautogui(pyautogui)
2035
2077
  screen_width, screen_height = pyautogui.size()
2036
- if (
2037
- hasattr(sb_config, "_cdp_browser")
2038
- and sb_config._cdp_browser == "opera"
2039
- ):
2040
- x = x + 55
2041
2078
  if x < 0 or y < 0 or x > screen_width or y > screen_height:
2042
2079
  raise Exception(
2043
2080
  "PyAutoGUI cannot hover on point (%s, %s)"
@@ -2084,15 +2121,14 @@ class CDPMethods():
2084
2121
  width_ratio = sb_config._saved_width_ratio
2085
2122
  else:
2086
2123
  scr_width = pyautogui.size().width
2087
- self.maximize()
2088
- self.__add_light_pause()
2089
- win_width = self.get_window_size()["width"]
2124
+ win_width = self.evaluate("screen.availWidth;")
2090
2125
  width_ratio = round(float(scr_width) / float(win_width), 2)
2091
2126
  width_ratio += 0.01
2092
2127
  if width_ratio < 0.45 or width_ratio > 2.55:
2093
2128
  width_ratio = 1.01
2094
2129
  sb_config._saved_width_ratio = width_ratio
2095
- self.__set_window_rect(win_x, win_y, width, height)
2130
+ with suppress(Exception):
2131
+ self.__set_window_rect(win_x, win_y, width, height)
2096
2132
  self.__add_light_pause()
2097
2133
  self.bring_active_window_to_front()
2098
2134
  elif (
@@ -2118,7 +2154,7 @@ class CDPMethods():
2118
2154
  if width > 0 and height > 0:
2119
2155
  x, y = self.get_gui_element_center(selector)
2120
2156
  self.bring_active_window_to_front()
2121
- self.__gui_hover_x_y(x, y, timeframe=timeframe)
2157
+ self.__gui_hover_x_y(x, y, timeframe=timeframe, uc_lock=False)
2122
2158
  self.__slow_mode_pause_if_set()
2123
2159
  self.loop.run_until_complete(self.page.wait())
2124
2160
 
@@ -2664,6 +2700,13 @@ class CDPMethods():
2664
2700
  self.loop.run_until_complete(self.page.evaluate(js_code))
2665
2701
  self.loop.run_until_complete(self.page.wait())
2666
2702
 
2703
+ def scroll_by_y(self, y):
2704
+ y = int(y)
2705
+ js_code = "window.scrollBy(0, %s);" % y
2706
+ with suppress(Exception):
2707
+ self.loop.run_until_complete(self.page.evaluate(js_code))
2708
+ self.loop.run_until_complete(self.page.wait())
2709
+
2667
2710
  def scroll_to_top(self):
2668
2711
  js_code = "window.scrollTo(0, 0);"
2669
2712
  with suppress(Exception):
@@ -2677,11 +2720,21 @@ class CDPMethods():
2677
2720
  self.loop.run_until_complete(self.page.wait())
2678
2721
 
2679
2722
  def scroll_up(self, amount=25):
2680
- self.loop.run_until_complete(self.page.scroll_up(amount))
2723
+ """Scrolls up as a percentage of the page."""
2724
+ try:
2725
+ self.loop.run_until_complete(self.page.scroll_up(amount))
2726
+ except Exception:
2727
+ amount = self.get_window_size()["height"] * amount / 100
2728
+ self.execute_script("window.scrollBy(0, -%s);" % amount)
2681
2729
  self.loop.run_until_complete(self.page.wait())
2682
2730
 
2683
2731
  def scroll_down(self, amount=25):
2684
- self.loop.run_until_complete(self.page.scroll_down(amount))
2732
+ """Scrolls down as a percentage of the page."""
2733
+ try:
2734
+ self.loop.run_until_complete(self.page.scroll_down(amount))
2735
+ except Exception:
2736
+ amount = self.get_window_size()["height"] * amount / 100
2737
+ self.execute_script("window.scrollBy(0, %s);" % amount)
2685
2738
  self.loop.run_until_complete(self.page.wait())
2686
2739
 
2687
2740
  def save_page_source(self, name, folder=None):
File without changes
File without changes
File without changes
File without changes
@@ -3577,9 +3577,18 @@ class BaseCase(unittest.TestCase):
3577
3577
  self.cdp.maximize()
3578
3578
  return
3579
3579
  self._check_browser()
3580
- self.driver.maximize_window()
3580
+ try:
3581
+ self.driver.maximize_window()
3582
+ except Exception:
3583
+ with suppress(Exception):
3584
+ width = self.execute_script("return screen.availWidth;")
3585
+ height = self.execute_script("return screen.availHeight;")
3586
+ self.set_window_rect(0, 0, width, height)
3581
3587
  self.__demo_mode_pause_if_active(tiny=True)
3582
3588
 
3589
+ def maximize(self):
3590
+ self.maximize_window()
3591
+
3583
3592
  def minimize_window(self):
3584
3593
  self.__check_scope()
3585
3594
  if self.__is_cdp_swap_needed():
@@ -3589,6 +3598,9 @@ class BaseCase(unittest.TestCase):
3589
3598
  self.driver.minimize_window()
3590
3599
  self.__demo_mode_pause_if_active(tiny=True)
3591
3600
 
3601
+ def minimize(self):
3602
+ self.minimize_window()
3603
+
3592
3604
  def reset_window_size(self):
3593
3605
  self.__check_scope()
3594
3606
  if self.__is_cdp_swap_needed():
@@ -4344,7 +4356,7 @@ class BaseCase(unittest.TestCase):
4344
4356
  if self.is_chromium():
4345
4357
  try:
4346
4358
  if self.maximize_option:
4347
- self.driver.maximize_window()
4359
+ self.maximize_window()
4348
4360
  self.wait_for_ready_state_complete()
4349
4361
  else:
4350
4362
  pass # Now handled in browser_launcher.py
@@ -4354,7 +4366,7 @@ class BaseCase(unittest.TestCase):
4354
4366
  elif self.browser == "firefox":
4355
4367
  try:
4356
4368
  if self.maximize_option:
4357
- self.driver.maximize_window()
4369
+ self.maximize_window()
4358
4370
  self.wait_for_ready_state_complete()
4359
4371
  else:
4360
4372
  with suppress(Exception):
@@ -4364,7 +4376,7 @@ class BaseCase(unittest.TestCase):
4364
4376
  elif self.browser == "safari":
4365
4377
  if self.maximize_option:
4366
4378
  try:
4367
- self.driver.maximize_window()
4379
+ self.maximize_window()
4368
4380
  self.wait_for_ready_state_complete()
4369
4381
  except Exception:
4370
4382
  pass # Keep existing browser resolution
@@ -6511,6 +6523,34 @@ class BaseCase(unittest.TestCase):
6511
6523
  self.execute_script(scroll_script)
6512
6524
  time.sleep(0.012)
6513
6525
 
6526
+ def scroll_by_y(self, y):
6527
+ """Scrolls page by y pixels."""
6528
+ self.__check_scope()
6529
+ y = int(y)
6530
+ if self.__is_cdp_swap_needed():
6531
+ self.cdp.scroll_by_y(y)
6532
+ return
6533
+ scroll_script = "window.scrollBy(0, %s);" % y
6534
+ with suppress(Exception):
6535
+ self.execute_script(scroll_script)
6536
+ time.sleep(0.012)
6537
+
6538
+ def scroll_up(self, amount=25):
6539
+ """Scrolls up as a percentage of the page."""
6540
+ if self.__is_cdp_swap_needed():
6541
+ self.cdp.scroll_up(amount)
6542
+ return
6543
+ amount = self.get_window_size()["height"] * amount / 100
6544
+ self.execute_script("window.scrollBy(0, -%s);" % amount)
6545
+
6546
+ def scroll_down(self, amount=25):
6547
+ """Scrolls down as a percentage of the page."""
6548
+ if self.__is_cdp_swap_needed():
6549
+ self.cdp.scroll_down(amount)
6550
+ return
6551
+ amount = self.get_window_size()["height"] * amount / 100
6552
+ self.execute_script("window.scrollBy(0, %s);" % amount)
6553
+
6514
6554
  def click_xpath(self, xpath):
6515
6555
  """Technically, self.click() automatically detects xpath selectors,
6516
6556
  so self.click_xpath() is just a longer name for the same action."""
@@ -11408,7 +11448,13 @@ class BaseCase(unittest.TestCase):
11408
11448
 
11409
11449
  def __is_cdp_swap_needed(self):
11410
11450
  """If the driver is disconnected, use a CDP method when available."""
11411
- return shared_utils.is_cdp_swap_needed(self.driver)
11451
+ cdp_swap_needed = shared_utils.is_cdp_swap_needed(self.driver)
11452
+ if cdp_swap_needed:
11453
+ if not self.cdp:
11454
+ self.cdp = self.driver.cdp
11455
+ return True
11456
+ else:
11457
+ return False
11412
11458
 
11413
11459
  ############
11414
11460
 
@@ -14001,7 +14047,7 @@ class BaseCase(unittest.TestCase):
14001
14047
  )
14002
14048
  raise Exception(message)
14003
14049
  except InvalidArgumentException:
14004
- if not self.browser == "chrome":
14050
+ if not self.is_chromium():
14005
14051
  raise
14006
14052
  chrome_version = self.driver.capabilities["browserVersion"]
14007
14053
  major_chrome_version = chrome_version.split(".")[0]
@@ -14616,7 +14662,7 @@ class BaseCase(unittest.TestCase):
14616
14662
  try:
14617
14663
  shadow_root = element.shadow_root
14618
14664
  except Exception:
14619
- if self.browser == "chrome":
14665
+ if self.is_chromium():
14620
14666
  chrome_dict = self.driver.capabilities["chrome"]
14621
14667
  chrome_dr_version = chrome_dict["chromedriverVersion"]
14622
14668
  chromedriver_version = chrome_dr_version.split(" ")[0]
@@ -264,16 +264,13 @@ class Reveal:
264
264
 
265
265
 
266
266
  class HighCharts:
267
+ LIB = "https://cdn.jsdelivr.net/npm/highcharts"
267
268
  VER = "10.3.3"
268
- HC_CSS = "https://code.highcharts.com/%s/css/highcharts.css" % VER
269
- HC_JS = "https://code.highcharts.com/%s/highcharts.js" % VER
270
- EXPORTING_JS = "https://code.highcharts.com/%s/modules/exporting.js" % VER
271
- EXPORT_DATA_JS = (
272
- "https://code.highcharts.com/%s/modules/export-data.js" % VER
273
- )
274
- ACCESSIBILITY_JS = (
275
- "https://code.highcharts.com/%s/modules/accessibility.js" % VER
276
- )
269
+ HC_CSS = "%s@%s/css/highcharts.css" % (LIB, VER)
270
+ HC_JS = "%s@%s/highcharts.js" % (LIB, VER)
271
+ EXPORTING_JS = "%s@%s/modules/exporting.js" % (LIB, VER)
272
+ EXPORT_DATA_JS = "%s@%s/modules/export-data.js" % (LIB, VER)
273
+ ACCESSIBILITY_JS = "%s@%s/modules/accessibility.js" % (LIB, VER)
277
274
 
278
275
 
279
276
  class BootstrapTour:
@@ -387,6 +384,20 @@ class ValidBrowsers:
387
384
  "ie",
388
385
  "safari",
389
386
  "remote",
387
+ "opera",
388
+ "brave",
389
+ "comet",
390
+ "atlas",
391
+ ]
392
+
393
+
394
+ class ChromiumSubs:
395
+ # Chromium browsers that still use chromedriver
396
+ chromium_subs = [
397
+ "opera",
398
+ "brave",
399
+ "comet",
400
+ "atlas",
390
401
  ]
391
402
 
392
403
 
@@ -430,8 +441,12 @@ class ValidBinaries:
430
441
  "Google Chrome Beta",
431
442
  "Google Chrome Dev",
432
443
  "Brave Browser",
444
+ "Brave",
445
+ "Opera Browser",
433
446
  "Opera",
447
+ "Comet Browser",
434
448
  "Comet",
449
+ "Atlas Browser",
435
450
  "Atlas",
436
451
  ]
437
452
  valid_edge_binaries_on_macos = [
@@ -1278,7 +1278,7 @@ def scroll_to_element(driver, element):
1278
1278
  try:
1279
1279
  screen_width = driver.get_window_size()["width"]
1280
1280
  except Exception:
1281
- screen_width = execute_script("return window.innerWidth;")
1281
+ screen_width = execute_script(driver, "return window.innerWidth;")
1282
1282
  element_location_y = element_location_y - constants.Scroll.Y_OFFSET
1283
1283
  if element_location_y < 0:
1284
1284
  element_location_y = 0
@@ -1327,7 +1327,7 @@ def slow_scroll_to_element(driver, element, *args, **kwargs):
1327
1327
  try:
1328
1328
  screen_width = driver.get_window_size()["width"]
1329
1329
  except Exception:
1330
- screen_width = execute_script("return window.innerWidth;")
1330
+ screen_width = execute_script(driver, "return window.innerWidth;")
1331
1331
  element_location_y = element_location_y - constants.Scroll.Y_OFFSET
1332
1332
  if element_location_y < 0:
1333
1333
  element_location_y = 0