seleniumbase 4.30.8__py3-none-any.whl → 4.31.1__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 (47) 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 +59 -11
  5. seleniumbase/config/settings.py +4 -0
  6. seleniumbase/console_scripts/logo_helper.py +47 -0
  7. seleniumbase/console_scripts/run.py +7 -4
  8. seleniumbase/console_scripts/sb_behave_gui.py +5 -5
  9. seleniumbase/console_scripts/sb_caseplans.py +6 -6
  10. seleniumbase/console_scripts/sb_commander.py +5 -5
  11. seleniumbase/console_scripts/sb_install.py +10 -2
  12. seleniumbase/console_scripts/sb_recorder.py +4 -4
  13. seleniumbase/core/browser_launcher.py +179 -108
  14. seleniumbase/core/mysql.py +1 -4
  15. seleniumbase/core/recorder_helper.py +24 -5
  16. seleniumbase/core/sb_driver.py +13 -3
  17. seleniumbase/core/settings_parser.py +4 -0
  18. seleniumbase/fixtures/base_case.py +324 -493
  19. seleniumbase/fixtures/js_utils.py +19 -52
  20. seleniumbase/fixtures/page_actions.py +3 -6
  21. seleniumbase/fixtures/page_utils.py +18 -53
  22. seleniumbase/plugins/base_plugin.py +2 -3
  23. seleniumbase/plugins/driver_manager.py +182 -5
  24. seleniumbase/plugins/pytest_plugin.py +51 -23
  25. seleniumbase/plugins/sb_manager.py +185 -5
  26. seleniumbase/plugins/selenium_plugin.py +71 -8
  27. seleniumbase/undetected/__init__.py +13 -38
  28. seleniumbase/undetected/dprocess.py +4 -6
  29. seleniumbase/undetected/options.py +3 -6
  30. seleniumbase/undetected/patcher.py +2 -3
  31. {seleniumbase-4.30.8.dist-info → seleniumbase-4.31.1.dist-info}/METADATA +111 -125
  32. {seleniumbase-4.30.8.dist-info → seleniumbase-4.31.1.dist-info}/RECORD +36 -47
  33. {seleniumbase-4.30.8.dist-info → seleniumbase-4.31.1.dist-info}/WHEEL +1 -1
  34. sbase/ReadMe.txt +0 -2
  35. seleniumbase/ReadMe.md +0 -25
  36. seleniumbase/common/ReadMe.md +0 -71
  37. seleniumbase/console_scripts/ReadMe.md +0 -734
  38. seleniumbase/drivers/ReadMe.md +0 -27
  39. seleniumbase/extensions/ReadMe.md +0 -12
  40. seleniumbase/masterqa/ReadMe.md +0 -61
  41. seleniumbase/resources/ReadMe.md +0 -31
  42. seleniumbase/resources/favicon.ico +0 -0
  43. seleniumbase/utilities/selenium_grid/ReadMe.md +0 -84
  44. seleniumbase/utilities/selenium_ide/ReadMe.md +0 -111
  45. {seleniumbase-4.30.8.dist-info → seleniumbase-4.31.1.dist-info}/LICENSE +0 -0
  46. {seleniumbase-4.30.8.dist-info → seleniumbase-4.31.1.dist-info}/entry_points.txt +0 -0
  47. {seleniumbase-4.30.8.dist-info → seleniumbase-4.31.1.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):
@@ -197,12 +165,9 @@ def is_valid_url(url):
197
165
  )
198
166
  if (
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:")
168
+ or url.startswith((
169
+ "about:", "blob:", "chrome:", "data:", "edge:", "file:"
170
+ ))
206
171
  ):
207
172
  return True
208
173
  else:
@@ -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()
@@ -65,8 +65,9 @@ class DriverContext():
65
65
 
66
66
  def Driver(
67
67
  browser=None, # Choose from "chrome", "edge", "firefox", or "safari".
68
- headless=None, # The original headless mode for Chromium and Firefox.
69
- headless2=None, # Chromium's new headless mode. (Has more features)
68
+ headless=None, # Use the default headless mode for Chromium and Firefox.
69
+ headless1=None, # Use Chromium's old headless mode. (Fast, but limited)
70
+ headless2=None, # Use Chromium's new headless mode. (Has more features)
70
71
  headed=None, # Run tests in headed/GUI mode on Linux, where not default.
71
72
  locale_code=None, # Set the Language Locale Code for the web browser.
72
73
  protocol=None, # The Selenium Grid protocol: "http" or "https".
@@ -75,7 +76,7 @@ def Driver(
75
76
  proxy=None, # Use proxy. Format: "SERVER:PORT" or "USER:PASS@SERVER:PORT".
76
77
  proxy_bypass_list=None, # Skip proxy when using the listed domains.
77
78
  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.
79
+ multi_proxy=None, # Allow multiple proxies with auth when multi-threaded.
79
80
  agent=None, # Modify the web browser's User-Agent string.
80
81
  cap_file=None, # The desired capabilities to use with a Selenium Grid.
81
82
  cap_string=None, # The desired capabilities to use with a Selenium Grid.
@@ -115,6 +116,8 @@ def Driver(
115
116
  page_load_strategy=None, # Set Chrome PLS to "normal", "eager", or "none".
116
117
  use_wire=None, # Use selenium-wire's webdriver over selenium webdriver.
117
118
  external_pdf=None, # Set Chrome "plugins.always_open_pdf_externally":True.
119
+ window_position=None, # Set the browser's starting window position: "X,Y"
120
+ window_size=None, # Set the browser's starting window size: "Width,Height"
118
121
  is_mobile=None, # Use the mobile device emulator while running tests.
119
122
  mobile=None, # Shortcut / Duplicate of "is_mobile".
120
123
  d_width=None, # Set device width
@@ -131,7 +134,99 @@ def Driver(
131
134
  wire=None, # Shortcut / Duplicate of "use_wire".
132
135
  pls=None, # Shortcut / Duplicate of "page_load_strategy".
133
136
  ):
137
+ """
138
+ * SeleniumBase Driver as a Python Context Manager or a returnable object. *
139
+
140
+ Example 1: (context manager format)
141
+ -----------------------------------
142
+ .. code-block:: python
143
+ from seleniumbase import DriverContext
144
+
145
+ with DriverContext() as driver:
146
+ driver.get("https://google.com/ncr")
147
+
148
+ Example 2: (as a Python returnable)
149
+ -----------------------------------
150
+ .. code-block:: python
151
+ from seleniumbase import Driver
152
+
153
+ driver = Driver()
154
+ driver.get("https://google.com/ncr")
155
+
156
+ Optional Parameters:
157
+ --------------------
158
+ browser (str): Choose from "chrome", "edge", "firefox", or "safari".
159
+ headless (bool): Use the default headless mode for Chromium and Firefox.
160
+ headless1 (bool): Use Chromium's old headless mode. (Fast, but limited)
161
+ headless2 (bool): Use Chromium's new headless mode. (Has more features)
162
+ headed (bool): Run tests in headed/GUI mode on Linux, where not default.
163
+ locale_code (str): Set the Language Locale Code for the web browser.
164
+ protocol (str): The Selenium Grid protocol: "http" or "https".
165
+ servername (str): The Selenium Grid server/IP used for tests.
166
+ port (int): The Selenium Grid port used by the test server.
167
+ proxy (str): Use proxy. Format: "SERVER:PORT" or "USER:PASS@SERVER:PORT".
168
+ proxy_bypass_list (str): Skip proxy when using the listed domains.
169
+ proxy_pac_url (str): Use PAC file. (Format: URL or USERNAME:PASSWORD@URL)
170
+ multi_proxy (bool): Allow multiple proxies with auth when multi-threaded.
171
+ agent (str): Modify the web browser's User-Agent string.
172
+ cap_file (str): The desired capabilities to use with a Selenium Grid.
173
+ cap_string (str): The desired capabilities to use with a Selenium Grid.
174
+ recorder_ext (bool): Enables the SeleniumBase Recorder Chromium extension.
175
+ disable_js (bool): Disable JavaScript on websites. Pages might break!
176
+ disable_csp (bool): Disable the Content Security Policy of websites.
177
+ enable_ws (bool): Enable Web Security on Chromium-based browsers.
178
+ disable_ws (bool): Reverse of "enable_ws". (None and False are different)
179
+ enable_sync (bool): Enable "Chrome Sync" on websites.
180
+ use_auto_ext (bool): Use Chrome's automation extension.
181
+ undetectable (bool): Use undetected-chromedriver to evade bot-detection.
182
+ uc_cdp_events (bool): Capture CDP events in undetected-chromedriver mode.
183
+ uc_subprocess (bool): Use undetected-chromedriver as a subprocess.
184
+ log_cdp_events (bool): Capture {"performance": "ALL", "browser": "ALL"}
185
+ no_sandbox (bool): (DEPRECATED) - "--no-sandbox" is always used now.
186
+ disable_gpu (bool): (DEPRECATED) - GPU is disabled if not "swiftshader".
187
+ incognito (bool): Enable Chromium's Incognito mode.
188
+ guest_mode (bool): Enable Chromium's Guest mode.
189
+ dark_mode (bool): Enable Chromium's Dark mode.
190
+ devtools (bool): Open Chromium's DevTools when the browser opens.
191
+ remote_debug (bool): Enable Chrome's Debugger on "http://localhost:9222".
192
+ enable_3d_apis (bool): Enable WebGL and 3D APIs.
193
+ swiftshader (bool): Chrome: --use-gl=angle / --use-angle=swiftshader-webgl
194
+ ad_block_on (bool): Block some types of display ads from loading.
195
+ host_resolver_rules (str): Set host-resolver-rules, comma-separated.
196
+ block_images (bool): Block images from loading during tests.
197
+ do_not_track (bool): Tell websites that you don't want to be tracked.
198
+ chromium_arg (str): "ARG=N,ARG2" (Set Chromium args, ","-separated.)
199
+ firefox_arg (str): "ARG=N,ARG2" (Set Firefox args, comma-separated.)
200
+ firefox_pref (str): SET (Set Firefox PREFERENCE:VALUE set, ","-separated)
201
+ user_data_dir (str): Set the Chrome user data directory to use.
202
+ extension_zip (str): Load a Chrome Extension .zip|.crx, comma-separated.
203
+ extension_dir (str): Load a Chrome Extension directory, comma-separated.
204
+ disable_features (str): "F1,F2" (Disable Chrome features, ","-separated.)
205
+ binary_location (str): Set path of the Chromium browser binary to use.
206
+ driver_version (str): Set the chromedriver or uc_driver version to use.
207
+ page_load_strategy (str): Set Chrome PLS to "normal", "eager", or "none".
208
+ use_wire (bool): Use selenium-wire's webdriver over selenium webdriver.
209
+ external_pdf (bool): Set Chrome "plugins.always_open_pdf_externally":True
210
+ window_position (x,y): Set the browser's starting window position: "X,Y"
211
+ window_size (w,h): Set the browser's starting window size: "Width,Height"
212
+ is_mobile (bool): Use the mobile device emulator while running tests.
213
+ mobile (bool): Shortcut / Duplicate of "is_mobile".
214
+ d_width (int): Set device width
215
+ d_height (int): Set device height
216
+ d_p_r (float): Set device pixel ratio
217
+ uc (bool): Shortcut / Duplicate of "undetectable".
218
+ undetected (bool): Shortcut / Duplicate of "undetectable".
219
+ uc_cdp (bool): Shortcut / Duplicate of "uc_cdp_events".
220
+ uc_sub (bool): Shortcut / Duplicate of "uc_subprocess".
221
+ log_cdp (bool): Shortcut / Duplicate of "log_cdp_events".
222
+ ad_block (bool): Shortcut / Duplicate of "ad_block_on".
223
+ server (str): Shortcut / Duplicate of "servername".
224
+ guest (bool): Shortcut / Duplicate of "guest_mode".
225
+ wire (bool): Shortcut / Duplicate of "use_wire".
226
+ pls (str): Shortcut / Duplicate of "page_load_strategy".
227
+ """
134
228
  from seleniumbase import config as sb_config
229
+ from seleniumbase.config import settings
135
230
  from seleniumbase.fixtures import constants
136
231
  from seleniumbase.fixtures import shared_utils
137
232
 
@@ -243,6 +338,13 @@ def Driver(
243
338
  headless = True
244
339
  else:
245
340
  headless = False
341
+ if headless1 is None:
342
+ if "--headless1" in sys_argv:
343
+ headless1 = True
344
+ else:
345
+ headless1 = False
346
+ if headless1:
347
+ headless = True
246
348
  if headless2 is None:
247
349
  if "--headless2" in sys_argv:
248
350
  headless2 = True
@@ -329,6 +431,79 @@ def Driver(
329
431
  break
330
432
  count += 1
331
433
  disable_features = d_f
434
+ w_p = window_position
435
+ if w_p is None and "--window-position" in arg_join:
436
+ count = 0
437
+ for arg in sys_argv:
438
+ if arg.startswith("--window-position="):
439
+ w_p = arg.split("--window-position=")[1]
440
+ break
441
+ elif arg == "--window-position" and len(sys_argv) > count + 1:
442
+ w_p = sys_argv[count + 1]
443
+ if w_p.startswith("-"):
444
+ w_p = None
445
+ break
446
+ count += 1
447
+ window_position = w_p
448
+ if window_position:
449
+ if window_position.count(",") != 1:
450
+ message = (
451
+ '\n\n window_position expects an "x,y" string!'
452
+ '\n (Your input was: "%s")\n' % window_position
453
+ )
454
+ raise Exception(message)
455
+ window_position = window_position.replace(" ", "")
456
+ win_x = None
457
+ win_y = None
458
+ try:
459
+ win_x = int(window_position.split(",")[0])
460
+ win_y = int(window_position.split(",")[1])
461
+ except Exception:
462
+ message = (
463
+ '\n\n Expecting integer values for "x,y"!'
464
+ '\n (window_position input was: "%s")\n'
465
+ % window_position
466
+ )
467
+ raise Exception(message)
468
+ settings.WINDOW_START_X = win_x
469
+ settings.WINDOW_START_Y = win_y
470
+ w_s = window_size
471
+ if w_s is None and "--window-size" in arg_join:
472
+ count = 0
473
+ for arg in sys_argv:
474
+ if arg.startswith("--window-size="):
475
+ w_s = arg.split("--window-size=")[1]
476
+ break
477
+ elif arg == "--window-size" and len(sys_argv) > count + 1:
478
+ w_s = sys_argv[count + 1]
479
+ if w_s.startswith("-"):
480
+ w_s = None
481
+ break
482
+ count += 1
483
+ window_size = w_s
484
+ if window_size:
485
+ if window_size.count(",") != 1:
486
+ message = (
487
+ '\n\n window_size expects a "width,height" string!'
488
+ '\n (Your input was: "%s")\n' % window_size
489
+ )
490
+ raise Exception(message)
491
+ window_size = window_size.replace(" ", "")
492
+ width = None
493
+ height = None
494
+ try:
495
+ width = int(window_size.split(",")[0])
496
+ height = int(window_size.split(",")[1])
497
+ except Exception:
498
+ message = (
499
+ '\n\n Expecting integer values for "width,height"!'
500
+ '\n (window_size input was: "%s")\n' % window_size
501
+ )
502
+ raise Exception(message)
503
+ settings.CHROME_START_WIDTH = width
504
+ settings.CHROME_START_HEIGHT = height
505
+ settings.HEADLESS_START_WIDTH = width
506
+ settings.HEADLESS_START_HEIGHT = height
332
507
  if agent is None and "--agent" in arg_join:
333
508
  count = 0
334
509
  for arg in sys_argv:
@@ -435,6 +610,7 @@ def Driver(
435
610
  headless = True
436
611
  if recorder_mode and headless:
437
612
  headless = False
613
+ headless1 = False
438
614
  headless2 = True
439
615
  if headless2 and browser == "firefox":
440
616
  headless2 = False # Only for Chromium browsers
@@ -607,6 +783,7 @@ def Driver(
607
783
  log_cdp_events=log_cdp_events,
608
784
  no_sandbox=no_sandbox,
609
785
  disable_gpu=disable_gpu,
786
+ headless1=headless1,
610
787
  headless2=headless2,
611
788
  incognito=incognito,
612
789
  guest_mode=guest_mode,