seleniumbase 4.30.8__py3-none-any.whl → 4.31.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.
Files changed (45) hide show
  1. sbase/__init__.py +1 -0
  2. seleniumbase/__init__.py +2 -3
  3. seleniumbase/__version__.py +1 -1
  4. seleniumbase/behave/behave_sb.py +47 -9
  5. seleniumbase/config/settings.py +4 -0
  6. seleniumbase/console_scripts/sb_behave_gui.py +5 -5
  7. seleniumbase/console_scripts/sb_caseplans.py +6 -6
  8. seleniumbase/console_scripts/sb_commander.py +5 -5
  9. seleniumbase/console_scripts/sb_install.py +10 -2
  10. seleniumbase/console_scripts/sb_recorder.py +4 -4
  11. seleniumbase/core/browser_launcher.py +138 -103
  12. seleniumbase/core/mysql.py +1 -4
  13. seleniumbase/core/recorder_helper.py +24 -5
  14. seleniumbase/core/sb_driver.py +2 -3
  15. seleniumbase/core/settings_parser.py +4 -0
  16. seleniumbase/fixtures/base_case.py +307 -492
  17. seleniumbase/fixtures/js_utils.py +19 -52
  18. seleniumbase/fixtures/page_actions.py +3 -6
  19. seleniumbase/fixtures/page_utils.py +20 -58
  20. seleniumbase/plugins/base_plugin.py +2 -3
  21. seleniumbase/plugins/driver_manager.py +169 -3
  22. seleniumbase/plugins/pytest_plugin.py +34 -21
  23. seleniumbase/plugins/sb_manager.py +170 -3
  24. seleniumbase/plugins/selenium_plugin.py +52 -6
  25. seleniumbase/undetected/__init__.py +13 -38
  26. seleniumbase/undetected/dprocess.py +4 -6
  27. seleniumbase/undetected/options.py +3 -6
  28. seleniumbase/undetected/patcher.py +2 -3
  29. {seleniumbase-4.30.8.dist-info → seleniumbase-4.31.0.dist-info}/METADATA +108 -123
  30. {seleniumbase-4.30.8.dist-info → seleniumbase-4.31.0.dist-info}/RECORD +34 -45
  31. {seleniumbase-4.30.8.dist-info → seleniumbase-4.31.0.dist-info}/WHEEL +1 -1
  32. sbase/ReadMe.txt +0 -2
  33. seleniumbase/ReadMe.md +0 -25
  34. seleniumbase/common/ReadMe.md +0 -71
  35. seleniumbase/console_scripts/ReadMe.md +0 -734
  36. seleniumbase/drivers/ReadMe.md +0 -27
  37. seleniumbase/extensions/ReadMe.md +0 -12
  38. seleniumbase/masterqa/ReadMe.md +0 -61
  39. seleniumbase/resources/ReadMe.md +0 -31
  40. seleniumbase/resources/favicon.ico +0 -0
  41. seleniumbase/utilities/selenium_grid/ReadMe.md +0 -84
  42. seleniumbase/utilities/selenium_ide/ReadMe.md +0 -111
  43. {seleniumbase-4.30.8.dist-info → seleniumbase-4.31.0.dist-info}/LICENSE +0 -0
  44. {seleniumbase-4.30.8.dist-info → seleniumbase-4.31.0.dist-info}/entry_points.txt +0 -0
  45. {seleniumbase-4.30.8.dist-info → seleniumbase-4.31.0.dist-info}/top_level.txt +0 -0
@@ -2,6 +2,7 @@
2
2
  import re
3
3
  import requests
4
4
  import time
5
+ from contextlib import suppress
5
6
  from selenium.common.exceptions import NoSuchElementException
6
7
  from selenium.common.exceptions import WebDriverException
7
8
  from selenium.webdriver.common.by import By
@@ -56,11 +57,9 @@ def execute_async_script(driver, script, timeout=settings.LARGE_TIMEOUT):
56
57
  def wait_for_angularjs(driver, timeout=settings.LARGE_TIMEOUT, **kwargs):
57
58
  if hasattr(settings, "SKIP_JS_WAITS") and settings.SKIP_JS_WAITS:
58
59
  return
59
- try:
60
+ with suppress(Exception):
60
61
  # This closes pop-up alerts
61
62
  driver.execute_script("")
62
- except Exception:
63
- pass
64
63
  if (
65
64
  (hasattr(driver, "_is_using_uc") and driver._is_using_uc)
66
65
  or not settings.WAIT_FOR_ANGULARJS
@@ -92,10 +91,8 @@ def wait_for_angularjs(driver, timeout=settings.LARGE_TIMEOUT, **kwargs):
92
91
  "handler": handler,
93
92
  "suffix": suffix,
94
93
  }
95
- try:
94
+ with suppress(Exception):
96
95
  execute_async_script(driver, script, timeout=timeout)
97
- except Exception:
98
- pass
99
96
 
100
97
 
101
98
  def convert_to_css_selector(selector, by=By.CSS_SELECTOR):
@@ -191,14 +188,12 @@ def raise_unable_to_load_jquery_exception(driver):
191
188
  def activate_jquery(driver):
192
189
  # If "jQuery is not defined" on a website, use this method to activate it.
193
190
  # This method is needed because jQuery is not always defined on web sites.
194
- try:
191
+ with suppress(Exception):
195
192
  # Let's first find out if jQuery is already defined.
196
193
  driver.execute_script("jQuery('html');")
197
194
  # Since that command worked, jQuery is defined. Let's return.
198
195
  return
199
- except Exception:
200
- # jQuery is not currently defined. Let's proceed by defining it.
201
- pass
196
+ # jQuery is not defined. It will be loaded in the next part.
202
197
  jquery_js = constants.JQuery.MIN_JS
203
198
  add_js_link(driver, jquery_js)
204
199
  for x in range(36):
@@ -390,11 +385,9 @@ def highlight(driver, selector, by="css selector", loops=4):
390
385
 
391
386
 
392
387
  def highlight_with_js(driver, selector, loops=4, o_bs=""):
393
- try:
388
+ with suppress(Exception):
394
389
  # This closes any pop-up alerts
395
390
  driver.execute_script("")
396
- except Exception:
397
- pass
398
391
  if selector == "html":
399
392
  selector = "body"
400
393
  selector_no_spaces = selector.replace(" ", "")
@@ -490,11 +483,9 @@ def highlight_with_js(driver, selector, loops=4, o_bs=""):
490
483
 
491
484
 
492
485
  def highlight_element_with_js(driver, element, loops=4, o_bs=""):
493
- try:
486
+ with suppress(Exception):
494
487
  # This closes any pop-up alerts
495
488
  driver.execute_script("")
496
- except Exception:
497
- pass
498
489
  script = (
499
490
  """arguments[0].style.boxShadow =
500
491
  '0px 0px 6px 6px rgba(128, 128, 128, 0.5)';"""
@@ -566,11 +557,9 @@ def highlight_element_with_js(driver, element, loops=4, o_bs=""):
566
557
 
567
558
 
568
559
  def highlight_with_jquery(driver, selector, loops=4, o_bs=""):
569
- try:
560
+ with suppress(Exception):
570
561
  # This closes any pop-up alerts
571
562
  driver.execute_script("")
572
- except Exception:
573
- pass
574
563
  if selector == "html":
575
564
  selector = "body"
576
565
  selector_no_spaces = selector.replace(" ", "")
@@ -908,11 +897,9 @@ def set_messenger_theme(
908
897
  time.sleep(0.03)
909
898
  activate_messenger(driver)
910
899
  time.sleep(0.15)
911
- try:
900
+ with suppress(Exception):
912
901
  driver.execute_script(msg_style)
913
902
  time.sleep(0.02)
914
- except Exception:
915
- pass
916
903
  time.sleep(0.05)
917
904
 
918
905
 
@@ -949,7 +936,7 @@ def post_messenger_success_message(driver, message, msg_dur=None):
949
936
  if not msg_dur:
950
937
  msg_dur = settings.DEFAULT_MESSAGE_DURATION
951
938
  msg_dur = float(msg_dur)
952
- try:
939
+ with suppress(Exception):
953
940
  theme = "future"
954
941
  location = "bottom_right"
955
942
  if hasattr(sb_config, "mobile_emulator") and sb_config.mobile_emulator:
@@ -957,28 +944,22 @@ def post_messenger_success_message(driver, message, msg_dur=None):
957
944
  set_messenger_theme(driver, theme=theme, location=location)
958
945
  post_message(driver, message, msg_dur, style="success")
959
946
  time.sleep(msg_dur + 0.07)
960
- except Exception:
961
- pass
962
947
 
963
948
 
964
949
  def post_messenger_error_message(driver, message, msg_dur=None):
965
950
  if not msg_dur:
966
951
  msg_dur = settings.DEFAULT_MESSAGE_DURATION
967
952
  msg_dur = float(msg_dur)
968
- try:
953
+ with suppress(Exception):
969
954
  set_messenger_theme(driver, theme="block", location="top_center")
970
955
  post_message(driver, message, msg_dur, style="error")
971
956
  time.sleep(msg_dur + 0.07)
972
- except Exception:
973
- pass
974
957
 
975
958
 
976
959
  def highlight_with_js_2(driver, message, selector, o_bs, msg_dur):
977
- try:
960
+ with suppress(Exception):
978
961
  # This closes any pop-up alerts
979
962
  driver.execute_script("")
980
- except Exception:
981
- pass
982
963
  if selector == "html":
983
964
  selector = "body"
984
965
  selector_no_spaces = selector.replace(" ", "")
@@ -991,11 +972,9 @@ def highlight_with_js_2(driver, message, selector, o_bs, msg_dur):
991
972
  else:
992
973
  early_exit = True # Changing the box-shadow changes the selector
993
974
  if early_exit:
994
- try:
975
+ with suppress(Exception):
995
976
  activate_jquery(driver)
996
977
  post_messenger_success_message(driver, message, msg_dur)
997
- except Exception:
998
- pass
999
978
  return
1000
979
  script = (
1001
980
  """document.querySelector('%s').style.boxShadow =
@@ -1047,11 +1026,9 @@ def highlight_with_js_2(driver, message, selector, o_bs, msg_dur):
1047
1026
  except Exception:
1048
1027
  return
1049
1028
  time.sleep(0.0181)
1050
- try:
1029
+ with suppress(Exception):
1051
1030
  activate_jquery(driver)
1052
1031
  post_messenger_success_message(driver, message, msg_dur)
1053
- except Exception:
1054
- pass
1055
1032
  script = """document.querySelector('%s').style.boxShadow = '%s';""" % (
1056
1033
  selector,
1057
1034
  o_bs,
@@ -1063,11 +1040,9 @@ def highlight_with_js_2(driver, message, selector, o_bs, msg_dur):
1063
1040
 
1064
1041
 
1065
1042
  def highlight_element_with_js_2(driver, message, element, o_bs, msg_dur):
1066
- try:
1043
+ with suppress(Exception):
1067
1044
  # This closes any pop-up alerts
1068
1045
  driver.execute_script("")
1069
- except Exception:
1070
- pass
1071
1046
  script = (
1072
1047
  """arguments[0].style.boxShadow =
1073
1048
  '0px 0px 6px 6px rgba(128, 128, 128, 0.5)';"""
@@ -1113,11 +1088,9 @@ def highlight_element_with_js_2(driver, message, element, o_bs, msg_dur):
1113
1088
  except Exception:
1114
1089
  return
1115
1090
  time.sleep(0.0181)
1116
- try:
1091
+ with suppress(Exception):
1117
1092
  activate_jquery(driver)
1118
1093
  post_messenger_success_message(driver, message, msg_dur)
1119
- except Exception:
1120
- pass
1121
1094
  script = """arguments[0].style.boxShadow = '%s';""" % (o_bs)
1122
1095
  try:
1123
1096
  driver.execute_script(script, element)
@@ -1138,11 +1111,9 @@ def highlight_with_jquery_2(driver, message, selector, o_bs, msg_dur):
1138
1111
  else:
1139
1112
  early_exit = True # Changing the box-shadow changes the selector
1140
1113
  if early_exit:
1141
- try:
1114
+ with suppress(Exception):
1142
1115
  activate_jquery(driver)
1143
1116
  post_messenger_success_message(driver, message, msg_dur)
1144
- except Exception:
1145
- pass
1146
1117
  return
1147
1118
  script = (
1148
1119
  """jQuery('%s').css('box-shadow',
@@ -1195,11 +1166,9 @@ def highlight_with_jquery_2(driver, message, selector, o_bs, msg_dur):
1195
1166
  return
1196
1167
  time.sleep(0.0181)
1197
1168
 
1198
- try:
1169
+ with suppress(Exception):
1199
1170
  activate_jquery(driver)
1200
1171
  post_messenger_success_message(driver, message, msg_dur)
1201
- except Exception:
1202
- pass
1203
1172
 
1204
1173
  script = """jQuery('%s').css('box-shadow', '%s');""" % (selector, o_bs)
1205
1174
  try:
@@ -1484,12 +1453,10 @@ def get_drag_and_drop_with_offset_script(selector, x, y):
1484
1453
 
1485
1454
 
1486
1455
  def clear_out_console_logs(driver):
1487
- try:
1456
+ with suppress(Exception):
1488
1457
  # Clear out the current page log before navigating to a new page
1489
1458
  # (To make sure that assert_no_js_errors() uses current results)
1490
1459
  driver.get_log("browser")
1491
- except Exception:
1492
- pass
1493
1460
 
1494
1461
 
1495
1462
  def _jq_format(code):
@@ -21,6 +21,7 @@ import codecs
21
21
  import fasteners
22
22
  import os
23
23
  import time
24
+ from contextlib import suppress
24
25
  from selenium.common.exceptions import ElementNotInteractableException
25
26
  from selenium.common.exceptions import ElementNotVisibleException
26
27
  from selenium.common.exceptions import NoAlertPresentException
@@ -1409,12 +1410,10 @@ def switch_to_frame(driver, frame, timeout=settings.SMALL_TIMEOUT):
1409
1410
  else:
1410
1411
  by = "css selector"
1411
1412
  if is_element_visible(driver, frame, by=by):
1412
- try:
1413
+ with suppress(Exception):
1413
1414
  element = driver.find_element(by=by, value=frame)
1414
1415
  driver.switch_to.frame(element)
1415
1416
  return True
1416
- except Exception:
1417
- pass
1418
1417
  now_ms = time.time() * 1000.0
1419
1418
  if now_ms >= stop_ms:
1420
1419
  break
@@ -1548,12 +1547,10 @@ def click_if_visible(
1548
1547
  if is_element_visible(driver, selector, by=by):
1549
1548
  click(driver, selector, by=by, timeout=1)
1550
1549
  elif timeout > 0:
1551
- try:
1550
+ with suppress(Exception):
1552
1551
  wait_for_element_visible(
1553
1552
  driver, selector, by=by, timeout=timeout
1554
1553
  )
1555
- except Exception:
1556
- pass
1557
1554
  if is_element_visible(driver, selector, by=by):
1558
1555
  click(driver, selector, by=by, timeout=1)
1559
1556
 
@@ -16,7 +16,7 @@ def get_domain_url(url):
16
16
  Into this:
17
17
  https://blog.xkcd.com
18
18
  """
19
- if not url.startswith("http://") and not url.startswith("https://"):
19
+ if not url.startswith(("http://", "https://")):
20
20
  return url
21
21
  url_header = url.split("://")[0]
22
22
  simple_url = url.split("://")[1]
@@ -40,45 +40,25 @@ def swap_selector_and_by_if_reversed(selector, by):
40
40
 
41
41
  def is_xpath_selector(selector):
42
42
  """Determine if a selector is an xpath selector."""
43
- if (
44
- selector.startswith("/")
45
- or selector.startswith("./")
46
- or selector.startswith("(")
47
- ):
48
- return True
49
- return False
43
+ return selector.startswith(("/", "./", "("))
50
44
 
51
45
 
52
46
  def is_link_text_selector(selector):
53
47
  """Determine if a selector is a link text selector."""
54
- if (
55
- selector.startswith("link=")
56
- or selector.startswith("link_text=")
57
- or selector.startswith("text=")
58
- ):
59
- return True
60
- return False
48
+ return selector.startswith(("link=", "link_text=", "text="))
61
49
 
62
50
 
63
51
  def is_partial_link_text_selector(selector):
64
52
  """Determine if a selector is a partial link text selector."""
65
- if (
66
- selector.startswith("partial_link=")
67
- or selector.startswith("partial_link_text=")
68
- or selector.startswith("partial_text=")
69
- or selector.startswith("p_link=")
70
- or selector.startswith("p_link_text=")
71
- or selector.startswith("p_text=")
72
- ):
73
- return True
74
- return False
53
+ return selector.startswith((
54
+ "partial_link=", "partial_link_text=", "partial_text=",
55
+ "p_link=", "p_link_text=", "p_text="
56
+ ))
75
57
 
76
58
 
77
59
  def is_name_selector(selector):
78
60
  """Determine if a selector is a name selector."""
79
- if selector.startswith("name=") or selector.startswith("&"):
80
- return True
81
- return False
61
+ return selector.startswith(("name=", "&"))
82
62
 
83
63
 
84
64
  def recalculate_selector(selector, by, xp_ok=True):
@@ -108,10 +88,9 @@ def recalculate_selector(selector, by, xp_ok=True):
108
88
  name = get_name_from_selector(selector)
109
89
  selector = '[name="%s"]' % name
110
90
  by = By.CSS_SELECTOR
111
- if xp_ok:
112
- if ":contains(" in selector and by == By.CSS_SELECTOR:
113
- selector = css_to_xpath.convert_css_to_xpath(selector)
114
- by = By.XPATH
91
+ if xp_ok and ":contains(" in selector and by == By.CSS_SELECTOR:
92
+ selector = css_to_xpath.convert_css_to_xpath(selector)
93
+ by = By.XPATH
115
94
  if by == "":
116
95
  by = By.CSS_SELECTOR
117
96
  if not is_valid_by(by):
@@ -130,21 +109,10 @@ def looks_like_a_page_url(url):
130
109
  possible typos when calling self.get(url), which will try to
131
110
  navigate to the page if a URL is detected, but will instead call
132
111
  self.get_element(URL_AS_A_SELECTOR) if the input is not a URL."""
133
- if (
134
- url.startswith("http:")
135
- or url.startswith("https:")
136
- or url.startswith("://")
137
- or url.startswith("about:")
138
- or url.startswith("blob:")
139
- or url.startswith("chrome:")
140
- or url.startswith("data:")
141
- or url.startswith("edge:")
142
- or url.startswith("file:")
143
- or url.startswith("view-source:")
144
- ):
145
- return True
146
- else:
147
- return False
112
+ return url.startswith((
113
+ "http:", "https:", "://", "about:", "blob:", "chrome:",
114
+ "data:", "edge:", "file:", "view-source:"
115
+ ))
148
116
 
149
117
 
150
118
  def get_link_text_from_selector(selector):
@@ -195,18 +163,12 @@ def is_valid_url(url):
195
163
  r"(?:/?|[/?]\S+)$",
196
164
  re.IGNORECASE,
197
165
  )
198
- if (
166
+ return (
199
167
  regex.match(url)
200
- or url.startswith("about:")
201
- or url.startswith("blob:")
202
- or url.startswith("chrome:")
203
- or url.startswith("data:")
204
- or url.startswith("edge:")
205
- or url.startswith("file:")
206
- ):
207
- return True
208
- else:
209
- return False
168
+ or url.startswith((
169
+ "about:", "blob:", "chrome:", "data:", "edge:", "file:"
170
+ ))
171
+ )
210
172
 
211
173
 
212
174
  def _get_unique_links(page_url, soup):
@@ -2,6 +2,7 @@
2
2
  import ast
3
3
  import sys
4
4
  import time
5
+ from contextlib import suppress
5
6
  from nose.plugins import Plugin
6
7
  from seleniumbase import config as sb_config
7
8
  from seleniumbase.config import settings
@@ -305,14 +306,12 @@ class Base(Plugin):
305
306
  if python3_11_or_newer and py311_patch2:
306
307
  # Handle a bug on Python 3.11 where exceptions aren't seen
307
308
  sb_config._browser_version = None
308
- try:
309
+ with suppress(Exception):
309
310
  test._BaseCase__set_last_page_screenshot()
310
311
  test._BaseCase__set_last_page_url()
311
312
  test._BaseCase__set_last_page_source()
312
313
  sb_config._browser_version = test._get_browser_version()
313
314
  test._log_fail_data()
314
- except Exception:
315
- pass
316
315
  sb_config._excinfo_tb = err
317
316
  log_path = None
318
317
  if hasattr(sb_config, "_test_logpath"):
@@ -7,7 +7,7 @@ Usage --> ``with DriverContext() as driver:``
7
7
 
8
8
  Example -->
9
9
 
10
- ```
10
+ ```python
11
11
  from seleniumbase import DriverContext
12
12
 
13
13
  with DriverContext() as driver:
@@ -27,7 +27,7 @@ Usage --> ``driver = Driver()``
27
27
 
28
28
  Example -->
29
29
 
30
- ```
30
+ ```python
31
31
  from seleniumbase import Driver
32
32
 
33
33
  driver = Driver()
@@ -75,7 +75,7 @@ def Driver(
75
75
  proxy=None, # Use proxy. Format: "SERVER:PORT" or "USER:PASS@SERVER:PORT".
76
76
  proxy_bypass_list=None, # Skip proxy when using the listed domains.
77
77
  proxy_pac_url=None, # Use PAC file. (Format: URL or USERNAME:PASSWORD@URL)
78
- multi_proxy=False, # Allow multiple proxies with auth when multi-threaded.
78
+ multi_proxy=None, # Allow multiple proxies with auth when multi-threaded.
79
79
  agent=None, # Modify the web browser's User-Agent string.
80
80
  cap_file=None, # The desired capabilities to use with a Selenium Grid.
81
81
  cap_string=None, # The desired capabilities to use with a Selenium Grid.
@@ -115,6 +115,8 @@ def Driver(
115
115
  page_load_strategy=None, # Set Chrome PLS to "normal", "eager", or "none".
116
116
  use_wire=None, # Use selenium-wire's webdriver over selenium webdriver.
117
117
  external_pdf=None, # Set Chrome "plugins.always_open_pdf_externally":True.
118
+ window_position=None, # Set the browser's starting window position: "X,Y"
119
+ window_size=None, # Set the browser's starting window size: "Width,Height"
118
120
  is_mobile=None, # Use the mobile device emulator while running tests.
119
121
  mobile=None, # Shortcut / Duplicate of "is_mobile".
120
122
  d_width=None, # Set device width
@@ -131,7 +133,98 @@ def Driver(
131
133
  wire=None, # Shortcut / Duplicate of "use_wire".
132
134
  pls=None, # Shortcut / Duplicate of "page_load_strategy".
133
135
  ):
136
+ """
137
+ * SeleniumBase Driver as a Python Context Manager or a returnable object. *
138
+
139
+ Example 1: (context manager format)
140
+ -----------------------------------
141
+ .. code-block:: python
142
+ from seleniumbase import DriverContext
143
+
144
+ with DriverContext() as driver:
145
+ driver.get("https://google.com/ncr")
146
+
147
+ Example 2: (as a Python returnable)
148
+ -----------------------------------
149
+ .. code-block:: python
150
+ from seleniumbase import Driver
151
+
152
+ driver = Driver()
153
+ driver.get("https://google.com/ncr")
154
+
155
+ Optional Parameters:
156
+ --------------------
157
+ browser: # Choose from "chrome", "edge", "firefox", or "safari".
158
+ headless: # The original headless mode for Chromium and Firefox.
159
+ headless2: # Chromium's new headless mode. (Has more features)
160
+ headed: # Run tests in headed/GUI mode on Linux, where not default.
161
+ locale_code: # Set the Language Locale Code for the web browser.
162
+ protocol: # The Selenium Grid protocol: "http" or "https".
163
+ servername: # The Selenium Grid server/IP used for tests.
164
+ port: # The Selenium Grid port used by the test server.
165
+ proxy: # Use proxy. Format: "SERVER:PORT" or "USER:PASS@SERVER:PORT".
166
+ proxy_bypass_list: # Skip proxy when using the listed domains.
167
+ proxy_pac_url: # Use PAC file. (Format: URL or USERNAME:PASSWORD@URL)
168
+ multi_proxy: # Allow multiple proxies with auth when multi-threaded.
169
+ agent: # Modify the web browser's User-Agent string.
170
+ cap_file: # The desired capabilities to use with a Selenium Grid.
171
+ cap_string: # The desired capabilities to use with a Selenium Grid.
172
+ recorder_ext: # Enables the SeleniumBase Recorder Chromium extension.
173
+ disable_js: # Disable JavaScript on websites. Pages might break!
174
+ disable_csp: # Disable the Content Security Policy of websites.
175
+ enable_ws: # Enable Web Security on Chromium-based browsers.
176
+ disable_ws: # Reverse of "enable_ws". (None and False are different)
177
+ enable_sync: # Enable "Chrome Sync" on websites.
178
+ use_auto_ext: # Use Chrome's automation extension.
179
+ undetectable: # Use undetected-chromedriver to evade bot-detection.
180
+ uc_cdp_events: # Capture CDP events in undetected-chromedriver mode.
181
+ uc_subprocess: # Use undetected-chromedriver as a subprocess.
182
+ log_cdp_events: # Capture {"performance": "ALL", "browser": "ALL"}
183
+ no_sandbox: # (DEPRECATED) - "--no-sandbox" is always used now.
184
+ disable_gpu: # (DEPRECATED) - GPU is disabled if not "swiftshader".
185
+ incognito: # Enable Chromium's Incognito mode.
186
+ guest_mode: # Enable Chromium's Guest mode.
187
+ dark_mode: # Enable Chromium's Dark mode.
188
+ devtools: # Open Chromium's DevTools when the browser opens.
189
+ remote_debug: # Enable Chrome's Debugger on "http://localhost:9222".
190
+ enable_3d_apis: # Enable WebGL and 3D APIs.
191
+ swiftshader: # Chrome: --use-gl=angle / --use-angle=swiftshader-webgl
192
+ ad_block_on: # Block some types of display ads from loading.
193
+ host_resolver_rules: # Set host-resolver-rules, comma-separated.
194
+ block_images: # Block images from loading during tests.
195
+ do_not_track: # Tell websites that you don't want to be tracked.
196
+ chromium_arg: # "ARG=N,ARG2" (Set Chromium args, ","-separated.)
197
+ firefox_arg: # "ARG=N,ARG2" (Set Firefox args, comma-separated.)
198
+ firefox_pref: # SET (Set Firefox PREFERENCE:VALUE set, ","-separated)
199
+ user_data_dir: # Set the Chrome user data directory to use.
200
+ extension_zip: # Load a Chrome Extension .zip|.crx, comma-separated.
201
+ extension_dir: # Load a Chrome Extension directory, comma-separated.
202
+ disable_features: # "F1,F2" (Disable Chrome features, ","-separated.)
203
+ binary_location: # Set path of the Chromium browser binary to use.
204
+ driver_version: # Set the chromedriver or uc_driver version to use.
205
+ page_load_strategy: # Set Chrome PLS to "normal", "eager", or "none".
206
+ use_wire: # Use selenium-wire's webdriver over selenium webdriver.
207
+ external_pdf: # Set Chrome "plugins.always_open_pdf_externally":True.
208
+ window_position: # Set the browser's starting window position: "X,Y"
209
+ window_size: # Set the browser's starting window size: "Width,Height"
210
+ is_mobile: # Use the mobile device emulator while running tests.
211
+ mobile: # Shortcut / Duplicate of "is_mobile".
212
+ d_width: # Set device width
213
+ d_height: # Set device height
214
+ d_p_r: # Set device pixel ratio
215
+ uc: # Shortcut / Duplicate of "undetectable".
216
+ undetected: # Shortcut / Duplicate of "undetectable".
217
+ uc_cdp: # Shortcut / Duplicate of "uc_cdp_events".
218
+ uc_sub: # Shortcut / Duplicate of "uc_subprocess".
219
+ log_cdp: # Shortcut / Duplicate of "log_cdp_events".
220
+ ad_block: # Shortcut / Duplicate of "ad_block_on".
221
+ server: # Shortcut / Duplicate of "servername".
222
+ guest: # Shortcut / Duplicate of "guest_mode".
223
+ wire: # Shortcut / Duplicate of "use_wire".
224
+ pls: # Shortcut / Duplicate of "page_load_strategy".
225
+ """
134
226
  from seleniumbase import config as sb_config
227
+ from seleniumbase.config import settings
135
228
  from seleniumbase.fixtures import constants
136
229
  from seleniumbase.fixtures import shared_utils
137
230
 
@@ -329,6 +422,79 @@ def Driver(
329
422
  break
330
423
  count += 1
331
424
  disable_features = d_f
425
+ w_p = window_position
426
+ if w_p is None and "--window-position" in arg_join:
427
+ count = 0
428
+ for arg in sys_argv:
429
+ if arg.startswith("--window-position="):
430
+ w_p = arg.split("--window-position=")[1]
431
+ break
432
+ elif arg == "--window-position" and len(sys_argv) > count + 1:
433
+ w_p = sys_argv[count + 1]
434
+ if w_p.startswith("-"):
435
+ w_p = None
436
+ break
437
+ count += 1
438
+ window_position = w_p
439
+ if window_position:
440
+ if window_position.count(",") != 1:
441
+ message = (
442
+ '\n\n window_position expects an "x,y" string!'
443
+ '\n (Your input was: "%s")\n' % window_position
444
+ )
445
+ raise Exception(message)
446
+ window_position = window_position.replace(" ", "")
447
+ win_x = None
448
+ win_y = None
449
+ try:
450
+ win_x = int(window_position.split(",")[0])
451
+ win_y = int(window_position.split(",")[1])
452
+ except Exception:
453
+ message = (
454
+ '\n\n Expecting integer values for "x,y"!'
455
+ '\n (window_position input was: "%s")\n'
456
+ % window_position
457
+ )
458
+ raise Exception(message)
459
+ settings.WINDOW_START_X = win_x
460
+ settings.WINDOW_START_Y = win_y
461
+ w_s = window_size
462
+ if w_s is None and "--window-size" in arg_join:
463
+ count = 0
464
+ for arg in sys_argv:
465
+ if arg.startswith("--window-size="):
466
+ w_s = arg.split("--window-size=")[1]
467
+ break
468
+ elif arg == "--window-size" and len(sys_argv) > count + 1:
469
+ w_s = sys_argv[count + 1]
470
+ if w_s.startswith("-"):
471
+ w_s = None
472
+ break
473
+ count += 1
474
+ window_size = w_s
475
+ if window_size:
476
+ if window_size.count(",") != 1:
477
+ message = (
478
+ '\n\n window_size expects a "width,height" string!'
479
+ '\n (Your input was: "%s")\n' % window_size
480
+ )
481
+ raise Exception(message)
482
+ window_size = window_size.replace(" ", "")
483
+ width = None
484
+ height = None
485
+ try:
486
+ width = int(window_size.split(",")[0])
487
+ height = int(window_size.split(",")[1])
488
+ except Exception:
489
+ message = (
490
+ '\n\n Expecting integer values for "width,height"!'
491
+ '\n (window_size input was: "%s")\n' % window_size
492
+ )
493
+ raise Exception(message)
494
+ settings.CHROME_START_WIDTH = width
495
+ settings.CHROME_START_HEIGHT = height
496
+ settings.HEADLESS_START_WIDTH = width
497
+ settings.HEADLESS_START_HEIGHT = height
332
498
  if agent is None and "--agent" in arg_join:
333
499
  count = 0
334
500
  for arg in sys_argv: