seleniumbase 4.44.2__py3-none-any.whl → 4.45.10__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.
- seleniumbase/__version__.py +1 -1
- seleniumbase/behave/behave_sb.py +14 -0
- seleniumbase/console_scripts/run.py +1 -0
- seleniumbase/console_scripts/sb_install.py +142 -11
- seleniumbase/console_scripts/sb_mkdir.py +76 -0
- seleniumbase/console_scripts/sb_mkrec.py +25 -0
- seleniumbase/console_scripts/sb_recorder.py +40 -3
- seleniumbase/core/browser_launcher.py +279 -117
- seleniumbase/core/detect_b_ver.py +8 -6
- seleniumbase/core/log_helper.py +11 -16
- seleniumbase/core/mysql.py +1 -1
- seleniumbase/core/report_helper.py +3 -7
- seleniumbase/core/sb_cdp.py +275 -78
- seleniumbase/core/sb_driver.py +36 -5
- seleniumbase/core/session_helper.py +2 -4
- seleniumbase/drivers/chromium_drivers/__init__.py +0 -0
- seleniumbase/fixtures/base_case.py +251 -201
- seleniumbase/fixtures/constants.py +1 -0
- seleniumbase/fixtures/js_utils.py +52 -14
- seleniumbase/fixtures/page_actions.py +18 -7
- seleniumbase/fixtures/page_utils.py +4 -2
- seleniumbase/fixtures/shared_utils.py +2 -4
- seleniumbase/masterqa/master_qa.py +16 -2
- seleniumbase/plugins/base_plugin.py +8 -0
- seleniumbase/plugins/driver_manager.py +15 -5
- seleniumbase/plugins/pytest_plugin.py +43 -57
- seleniumbase/plugins/sb_manager.py +23 -19
- seleniumbase/plugins/selenium_plugin.py +20 -13
- seleniumbase/undetected/__init__.py +11 -10
- seleniumbase/undetected/cdp.py +1 -12
- seleniumbase/undetected/cdp_driver/browser.py +330 -128
- seleniumbase/undetected/cdp_driver/cdp_util.py +48 -14
- seleniumbase/undetected/cdp_driver/config.py +78 -11
- seleniumbase/undetected/cdp_driver/connection.py +15 -43
- seleniumbase/undetected/cdp_driver/element.py +37 -22
- seleniumbase/undetected/cdp_driver/tab.py +414 -39
- {seleniumbase-4.44.2.dist-info → seleniumbase-4.45.10.dist-info}/METADATA +140 -152
- {seleniumbase-4.44.2.dist-info → seleniumbase-4.45.10.dist-info}/RECORD +42 -41
- {seleniumbase-4.44.2.dist-info → seleniumbase-4.45.10.dist-info}/licenses/LICENSE +1 -1
- {seleniumbase-4.44.2.dist-info → seleniumbase-4.45.10.dist-info}/WHEEL +0 -0
- {seleniumbase-4.44.2.dist-info → seleniumbase-4.45.10.dist-info}/entry_points.txt +0 -0
- {seleniumbase-4.44.2.dist-info → seleniumbase-4.45.10.dist-info}/top_level.txt +0 -0
|
@@ -31,7 +31,7 @@ def wait_for_ready_state_complete(driver, timeout=settings.LARGE_TIMEOUT):
|
|
|
31
31
|
(Previously, tests would fail immediately if exceeding the timeout.)"""
|
|
32
32
|
if hasattr(driver, "_swap_driver"):
|
|
33
33
|
return
|
|
34
|
-
if
|
|
34
|
+
if getattr(settings, "SKIP_JS_WAITS", None):
|
|
35
35
|
return
|
|
36
36
|
start_ms = time.time() * 1000.0
|
|
37
37
|
stop_ms = start_ms + (timeout * 1000.0)
|
|
@@ -65,13 +65,13 @@ def execute_async_script(driver, script, timeout=settings.LARGE_TIMEOUT):
|
|
|
65
65
|
|
|
66
66
|
|
|
67
67
|
def wait_for_angularjs(driver, timeout=settings.LARGE_TIMEOUT, **kwargs):
|
|
68
|
-
if
|
|
68
|
+
if getattr(settings, "SKIP_JS_WAITS", None):
|
|
69
69
|
return
|
|
70
70
|
with suppress(Exception):
|
|
71
71
|
# This closes pop-up alerts
|
|
72
72
|
execute_script(driver, "")
|
|
73
73
|
if (
|
|
74
|
-
(
|
|
74
|
+
getattr(driver, "_is_using_uc", None)
|
|
75
75
|
or not settings.WAIT_FOR_ANGULARJS
|
|
76
76
|
):
|
|
77
77
|
wait_for_ready_state_complete(driver)
|
|
@@ -211,6 +211,19 @@ def activate_jquery(driver):
|
|
|
211
211
|
try:
|
|
212
212
|
execute_script(driver, "jQuery('html');")
|
|
213
213
|
return
|
|
214
|
+
except TypeError as e:
|
|
215
|
+
if (
|
|
216
|
+
(
|
|
217
|
+
shared_utils.is_cdp_swap_needed(driver)
|
|
218
|
+
or hasattr(driver, "_swap_driver")
|
|
219
|
+
)
|
|
220
|
+
and "cannot unpack non-iterable" in str(e)
|
|
221
|
+
):
|
|
222
|
+
pass
|
|
223
|
+
else:
|
|
224
|
+
if x == 18:
|
|
225
|
+
add_js_link(driver, jquery_js)
|
|
226
|
+
time.sleep(0.1)
|
|
214
227
|
except Exception:
|
|
215
228
|
if x == 18:
|
|
216
229
|
add_js_link(driver, jquery_js)
|
|
@@ -282,6 +295,18 @@ def safe_execute_script(driver, script):
|
|
|
282
295
|
This method will load jQuery if it wasn't already loaded."""
|
|
283
296
|
try:
|
|
284
297
|
execute_script(driver, script)
|
|
298
|
+
except TypeError as e:
|
|
299
|
+
if (
|
|
300
|
+
(
|
|
301
|
+
shared_utils.is_cdp_swap_needed(driver)
|
|
302
|
+
or hasattr(driver, "_swap_driver")
|
|
303
|
+
)
|
|
304
|
+
and "cannot unpack non-iterable" in str(e)
|
|
305
|
+
):
|
|
306
|
+
pass
|
|
307
|
+
else:
|
|
308
|
+
activate_jquery(driver) # It's a good thing we can define it here
|
|
309
|
+
execute_script(driver, script)
|
|
285
310
|
except Exception:
|
|
286
311
|
# The likely reason this fails is because: "jQuery is not defined"
|
|
287
312
|
activate_jquery(driver) # It's a good thing we can define it here
|
|
@@ -874,7 +899,7 @@ def set_messenger_theme(
|
|
|
874
899
|
theme = "future"
|
|
875
900
|
if location == "default":
|
|
876
901
|
location = "bottom_right"
|
|
877
|
-
if
|
|
902
|
+
if getattr(sb_config, "mobile_emulator", None):
|
|
878
903
|
location = "top_center"
|
|
879
904
|
if max_messages == "default":
|
|
880
905
|
max_messages = "8"
|
|
@@ -914,15 +939,16 @@ def set_messenger_theme(
|
|
|
914
939
|
% (max_messages, messenger_location, theme)
|
|
915
940
|
)
|
|
916
941
|
try:
|
|
942
|
+
time.sleep(0.015)
|
|
917
943
|
execute_script(driver, msg_style)
|
|
918
944
|
except Exception:
|
|
919
|
-
time.sleep(0.
|
|
945
|
+
time.sleep(0.035)
|
|
920
946
|
activate_messenger(driver)
|
|
921
|
-
time.sleep(0.
|
|
947
|
+
time.sleep(0.175)
|
|
922
948
|
with suppress(Exception):
|
|
923
949
|
execute_script(driver, msg_style)
|
|
924
|
-
time.sleep(0.
|
|
925
|
-
time.sleep(0.
|
|
950
|
+
time.sleep(0.035)
|
|
951
|
+
time.sleep(0.055)
|
|
926
952
|
|
|
927
953
|
|
|
928
954
|
def post_message(driver, message, msg_dur=None, style="info"):
|
|
@@ -977,7 +1003,7 @@ def post_messenger_success_message(driver, message, msg_dur=None):
|
|
|
977
1003
|
with suppress(Exception):
|
|
978
1004
|
theme = "future"
|
|
979
1005
|
location = "bottom_right"
|
|
980
|
-
if
|
|
1006
|
+
if getattr(sb_config, "mobile_emulator", None):
|
|
981
1007
|
location = "top_right"
|
|
982
1008
|
set_messenger_theme(driver, theme=theme, location=location)
|
|
983
1009
|
post_message(driver, message, msg_dur, style="success")
|
|
@@ -1310,22 +1336,34 @@ def slow_scroll_to_element(driver, element, *args, **kwargs):
|
|
|
1310
1336
|
element_location_y = None
|
|
1311
1337
|
try:
|
|
1312
1338
|
if shared_utils.is_cdp_swap_needed(driver):
|
|
1313
|
-
element.get_position().y
|
|
1339
|
+
element_location_y = element.get_position().y
|
|
1314
1340
|
else:
|
|
1315
1341
|
element_location_y = element.location["y"]
|
|
1316
1342
|
except Exception:
|
|
1317
|
-
|
|
1343
|
+
if shared_utils.is_cdp_swap_needed(driver):
|
|
1344
|
+
element.scroll_into_view()
|
|
1345
|
+
else:
|
|
1346
|
+
element.location_once_scrolled_into_view
|
|
1318
1347
|
return
|
|
1319
1348
|
try:
|
|
1320
|
-
|
|
1349
|
+
if shared_utils.is_cdp_swap_needed(driver):
|
|
1350
|
+
element_location_x = element.get_position().x
|
|
1351
|
+
else:
|
|
1352
|
+
element_location_x = element.location["x"]
|
|
1321
1353
|
except Exception:
|
|
1322
1354
|
element_location_x = 0
|
|
1323
1355
|
try:
|
|
1324
|
-
|
|
1356
|
+
if shared_utils.is_cdp_swap_needed(driver):
|
|
1357
|
+
element_width = element.get_position().width
|
|
1358
|
+
else:
|
|
1359
|
+
element_width = element.size["width"]
|
|
1325
1360
|
except Exception:
|
|
1326
1361
|
element_width = 0
|
|
1327
1362
|
try:
|
|
1328
|
-
|
|
1363
|
+
if shared_utils.is_cdp_swap_needed(driver):
|
|
1364
|
+
screen_width = driver.cdp.get_window_size()["width"]
|
|
1365
|
+
else:
|
|
1366
|
+
screen_width = driver.get_window_size()["width"]
|
|
1329
1367
|
except Exception:
|
|
1330
1368
|
screen_width = execute_script(driver, "return window.innerWidth;")
|
|
1331
1369
|
element_location_y = element_location_y - constants.Scroll.Y_OFFSET
|
|
@@ -1646,11 +1646,7 @@ def switch_to_frame(
|
|
|
1646
1646
|
|
|
1647
1647
|
|
|
1648
1648
|
def __switch_to_window(driver, window_handle, uc_lock=True):
|
|
1649
|
-
if (
|
|
1650
|
-
hasattr(driver, "_is_using_uc")
|
|
1651
|
-
and driver._is_using_uc
|
|
1652
|
-
and uc_lock
|
|
1653
|
-
):
|
|
1649
|
+
if getattr(driver, "_is_using_uc", None) and uc_lock:
|
|
1654
1650
|
gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
|
|
1655
1651
|
with gui_lock:
|
|
1656
1652
|
driver.switch_to.window(window_handle)
|
|
@@ -1734,8 +1730,7 @@ def switch_to_window(
|
|
|
1734
1730
|
|
|
1735
1731
|
def _reconnect_if_disconnected(driver):
|
|
1736
1732
|
if (
|
|
1737
|
-
|
|
1738
|
-
and driver._is_using_uc
|
|
1733
|
+
getattr(driver, "_is_using_uc", None)
|
|
1739
1734
|
and hasattr(driver, "is_connected")
|
|
1740
1735
|
and not driver.is_connected()
|
|
1741
1736
|
):
|
|
@@ -1756,6 +1751,22 @@ def open_url(driver, url):
|
|
|
1756
1751
|
if __is_cdp_swap_needed(driver):
|
|
1757
1752
|
driver.cdp.open(url)
|
|
1758
1753
|
return
|
|
1754
|
+
elif (
|
|
1755
|
+
getattr(driver, "_is_using_uc", None)
|
|
1756
|
+
# and getattr(driver, "_is_using_auth", None)
|
|
1757
|
+
and not getattr(driver, "_is_using_cdp", None)
|
|
1758
|
+
):
|
|
1759
|
+
# Auth in UC Mode requires CDP Mode
|
|
1760
|
+
# (and now we're always forcing it)
|
|
1761
|
+
driver.uc_activate_cdp_mode(url)
|
|
1762
|
+
return
|
|
1763
|
+
elif (
|
|
1764
|
+
getattr(driver, "_is_using_uc", None)
|
|
1765
|
+
and getattr(driver, "_is_using_cdp", None)
|
|
1766
|
+
):
|
|
1767
|
+
driver.disconnect()
|
|
1768
|
+
driver.cdp.open(url)
|
|
1769
|
+
return
|
|
1759
1770
|
url = str(url).strip() # Remove leading and trailing whitespace
|
|
1760
1771
|
if not page_utils.looks_like_a_page_url(url):
|
|
1761
1772
|
if page_utils.is_valid_url("https://" + url):
|
|
@@ -293,12 +293,14 @@ def _print_unique_links_with_status_codes(page_url, soup):
|
|
|
293
293
|
print(link, " -> ", status_code)
|
|
294
294
|
|
|
295
295
|
|
|
296
|
-
def _download_file_to(
|
|
296
|
+
def _download_file_to(
|
|
297
|
+
file_url, destination_folder, new_file_name=None, headers=None
|
|
298
|
+
):
|
|
297
299
|
if new_file_name:
|
|
298
300
|
file_name = new_file_name
|
|
299
301
|
else:
|
|
300
302
|
file_name = file_url.split("/")[-1]
|
|
301
|
-
r = requests.get(file_url, timeout=5)
|
|
303
|
+
r = requests.get(file_url, headers=headers, timeout=5)
|
|
302
304
|
file_path = os.path.join(destination_folder, file_name)
|
|
303
305
|
download_file_lock = fasteners.InterProcessLock(
|
|
304
306
|
constants.MultiBrowser.DOWNLOAD_FILE_LOCK
|
|
@@ -147,8 +147,7 @@ def fix_url_as_needed(url):
|
|
|
147
147
|
|
|
148
148
|
def reconnect_if_disconnected(driver):
|
|
149
149
|
if (
|
|
150
|
-
|
|
151
|
-
and driver._is_using_uc
|
|
150
|
+
getattr(driver, "_is_using_uc", None)
|
|
152
151
|
and hasattr(driver, "is_connected")
|
|
153
152
|
and not driver.is_connected()
|
|
154
153
|
):
|
|
@@ -298,8 +297,7 @@ def __time_limit_exceeded(message):
|
|
|
298
297
|
|
|
299
298
|
def check_if_time_limit_exceeded():
|
|
300
299
|
if (
|
|
301
|
-
|
|
302
|
-
and sb_config.time_limit
|
|
300
|
+
getattr(sb_config, "time_limit", None)
|
|
303
301
|
and not sb_config.recorder_mode
|
|
304
302
|
):
|
|
305
303
|
time_limit = sb_config.time_limit
|
|
@@ -11,6 +11,11 @@ from seleniumbase.config import settings
|
|
|
11
11
|
from seleniumbase.fixtures import js_utils
|
|
12
12
|
|
|
13
13
|
|
|
14
|
+
python3_11_or_newer = False
|
|
15
|
+
if sys.version_info >= (3, 11):
|
|
16
|
+
python3_11_or_newer = True
|
|
17
|
+
|
|
18
|
+
|
|
14
19
|
class MasterQA(BaseCase):
|
|
15
20
|
def setUp(self):
|
|
16
21
|
self.check_count = 0
|
|
@@ -309,8 +314,17 @@ class MasterQA(BaseCase):
|
|
|
309
314
|
if hasattr(sys, "last_traceback") and sys.last_traceback is not None:
|
|
310
315
|
has_exception = True
|
|
311
316
|
elif hasattr(self, "_outcome"):
|
|
312
|
-
if hasattr(self._outcome, "errors")
|
|
313
|
-
|
|
317
|
+
if hasattr(self._outcome, "errors"):
|
|
318
|
+
if python3_11_or_newer:
|
|
319
|
+
if (
|
|
320
|
+
self._outcome.errors
|
|
321
|
+
and self._outcome.errors[-1]
|
|
322
|
+
and self._outcome.errors[-1][1]
|
|
323
|
+
):
|
|
324
|
+
has_exception = True
|
|
325
|
+
else:
|
|
326
|
+
if self._outcome.errors:
|
|
327
|
+
has_exception = True
|
|
314
328
|
else:
|
|
315
329
|
has_exception = sys.exc_info()[1] is not None
|
|
316
330
|
return has_exception
|
|
@@ -240,14 +240,22 @@ class Base(Plugin):
|
|
|
240
240
|
test.test.test_id = test.id()
|
|
241
241
|
test.test.is_nosetest = True
|
|
242
242
|
test.test.environment = self.options.environment
|
|
243
|
+
sb_config.environment = self.options.environment
|
|
243
244
|
test.test.env = self.options.environment # Add a shortened version
|
|
244
245
|
test.test.account = self.options.account
|
|
246
|
+
sb_config.account = self.options.account
|
|
245
247
|
test.test.data = self.options.data
|
|
248
|
+
sb_config.data = self.options.data
|
|
246
249
|
test.test.var1 = self.options.var1
|
|
250
|
+
sb_config.var1 = self.options.var1
|
|
247
251
|
test.test.var2 = self.options.var2
|
|
252
|
+
sb_config.var2 = self.options.var2
|
|
248
253
|
test.test.var3 = self.options.var3
|
|
254
|
+
sb_config.var3 = self.options.var3
|
|
249
255
|
test.test.variables = variables # Already verified is a dictionary
|
|
256
|
+
sb_config.variables = variables
|
|
250
257
|
test.test.settings_file = self.options.settings_file
|
|
258
|
+
sb_config.settings_file = self.options.settings_file
|
|
251
259
|
test.test._final_debug = self.options.final_debug
|
|
252
260
|
test.test.log_path = self.options.log_path
|
|
253
261
|
if self.options.archive_downloads:
|
|
@@ -140,6 +140,7 @@ def Driver(
|
|
|
140
140
|
pls=None, # Shortcut / Duplicate of "page_load_strategy".
|
|
141
141
|
cft=None, # Use "Chrome for Testing"
|
|
142
142
|
chs=None, # Use "Chrome-Headless-Shell"
|
|
143
|
+
use_chromium=None, # Use base "Chromium"
|
|
143
144
|
) -> sb_driver.DriverMethods:
|
|
144
145
|
"""
|
|
145
146
|
* SeleniumBase Driver as a Python Context Manager or a returnable object. *
|
|
@@ -665,11 +666,15 @@ def Driver(
|
|
|
665
666
|
if arg.startswith("--bl="):
|
|
666
667
|
binary_location = arg.split("--bl=")[1]
|
|
667
668
|
break
|
|
668
|
-
if
|
|
669
|
+
if use_chromium and not binary_location:
|
|
670
|
+
binary_location = "_chromium_"
|
|
671
|
+
elif cft and not binary_location:
|
|
669
672
|
binary_location = "cft"
|
|
670
673
|
elif chs and not binary_location:
|
|
671
674
|
binary_location = "chs"
|
|
672
|
-
if "--
|
|
675
|
+
if "--use-chromium" in sys_argv and not binary_location:
|
|
676
|
+
binary_location = "_chromium_"
|
|
677
|
+
elif "--cft" in sys_argv and not binary_location:
|
|
673
678
|
binary_location = "cft"
|
|
674
679
|
elif "--chs" in sys_argv and not binary_location:
|
|
675
680
|
binary_location = "chs"
|
|
@@ -742,9 +747,12 @@ def Driver(
|
|
|
742
747
|
uc_cdp_events = True
|
|
743
748
|
else:
|
|
744
749
|
uc_cdp_events = False
|
|
745
|
-
if
|
|
750
|
+
if (
|
|
751
|
+
undetectable
|
|
752
|
+
and browser not in ["chrome", "opera", "brave", "comet", "atlas"]
|
|
753
|
+
):
|
|
746
754
|
message = (
|
|
747
|
-
'\n Undetected-Chromedriver Mode ONLY supports
|
|
755
|
+
'\n Undetected-Chromedriver Mode ONLY supports Chromium browsers!'
|
|
748
756
|
'\n ("uc=True" / "undetectable=True" / "--uc")'
|
|
749
757
|
'\n (Your browser choice was: "%s".)'
|
|
750
758
|
'\n (Will use "%s" without UC Mode.)\n' % (browser, browser)
|
|
@@ -775,7 +783,9 @@ def Driver(
|
|
|
775
783
|
if headless2 and browser == "firefox":
|
|
776
784
|
headless2 = False # Only for Chromium browsers
|
|
777
785
|
headless = True # Firefox has regular headless
|
|
778
|
-
elif browser not in [
|
|
786
|
+
elif browser not in [
|
|
787
|
+
"chrome", "edge", "opera", "brave", "comet", "atlas"
|
|
788
|
+
]:
|
|
779
789
|
headless2 = False # Only for Chromium browsers
|
|
780
790
|
if disable_csp is None:
|
|
781
791
|
if (
|
|
@@ -33,6 +33,7 @@ def pytest_addoption(parser):
|
|
|
33
33
|
--brave (Shortcut for "--browser=brave".)
|
|
34
34
|
--comet (Shortcut for "--browser=comet".)
|
|
35
35
|
--atlas (Shortcut for "--browser=atlas".)
|
|
36
|
+
--use-chromium (Shortcut for using base `Chromium`)
|
|
36
37
|
--cft (Shortcut for using `Chrome for Testing`)
|
|
37
38
|
--chs (Shortcut for using `Chrome-Headless-Shell`)
|
|
38
39
|
--settings-file=FILE (Override default SeleniumBase settings.)
|
|
@@ -219,6 +220,13 @@ def pytest_addoption(parser):
|
|
|
219
220
|
default=False,
|
|
220
221
|
help="""Shortcut for --browser=atlas""",
|
|
221
222
|
)
|
|
223
|
+
parser.addoption(
|
|
224
|
+
"--use-chromium",
|
|
225
|
+
action="store_true",
|
|
226
|
+
dest="use_chromium",
|
|
227
|
+
default=False,
|
|
228
|
+
help="""Shortcut for using base `Chromium`""",
|
|
229
|
+
)
|
|
222
230
|
parser.addoption(
|
|
223
231
|
"--cft",
|
|
224
232
|
action="store_true",
|
|
@@ -625,7 +633,7 @@ def pytest_addoption(parser):
|
|
|
625
633
|
help="""Designates the three device metrics of the mobile
|
|
626
634
|
emulator: CSS Width, CSS Height, and Pixel-Ratio.
|
|
627
635
|
Format: A comma-separated string with the 3 values.
|
|
628
|
-
Examples: "375,734,5" or "
|
|
636
|
+
Examples: "375,734,5" or "412,732,3" or "390,715,3"
|
|
629
637
|
Default: None. (Will use default values if None)""",
|
|
630
638
|
)
|
|
631
639
|
parser.addoption(
|
|
@@ -1622,10 +1630,12 @@ def pytest_addoption(parser):
|
|
|
1622
1630
|
if (
|
|
1623
1631
|
using_recorder
|
|
1624
1632
|
and browser_changes == 1
|
|
1625
|
-
and browser_text not in [
|
|
1633
|
+
and browser_text not in [
|
|
1634
|
+
"chrome", "edge", "opera", "brave", "comet", "atlas", "chromium"
|
|
1635
|
+
]
|
|
1626
1636
|
):
|
|
1627
1637
|
message = (
|
|
1628
|
-
"\n Recorder Mode ONLY supports
|
|
1638
|
+
"\n Recorder Mode ONLY supports Chromium browsers!"
|
|
1629
1639
|
'\n (Your browser choice was: "%s")\n' % browser_list[0]
|
|
1630
1640
|
)
|
|
1631
1641
|
raise Exception(message)
|
|
@@ -1644,7 +1654,9 @@ def pytest_addoption(parser):
|
|
|
1644
1654
|
undetectable = True
|
|
1645
1655
|
if (
|
|
1646
1656
|
browser_changes == 1
|
|
1647
|
-
and browser_text not in [
|
|
1657
|
+
and browser_text not in [
|
|
1658
|
+
"chrome", "opera", "brave", "comet", "atlas", "chromium"
|
|
1659
|
+
]
|
|
1648
1660
|
and undetectable
|
|
1649
1661
|
):
|
|
1650
1662
|
message = (
|
|
@@ -1712,7 +1724,11 @@ def pytest_configure(config):
|
|
|
1712
1724
|
if sb_config.headless2 and sb_config.browser == "firefox":
|
|
1713
1725
|
sb_config.headless2 = False # Only for Chromium browsers
|
|
1714
1726
|
sb_config.headless = True # Firefox has regular headless
|
|
1715
|
-
elif
|
|
1727
|
+
elif (
|
|
1728
|
+
sb_config.browser not in [
|
|
1729
|
+
"chrome", "edge", "opera", "brave", "comet", "atlas", "chromium"
|
|
1730
|
+
]
|
|
1731
|
+
):
|
|
1716
1732
|
sb_config.headless2 = False # Only for Chromium browsers
|
|
1717
1733
|
sb_config.headed = config.getoption("headed")
|
|
1718
1734
|
sb_config.xvfb = config.getoption("xvfb")
|
|
@@ -1727,7 +1743,7 @@ def pytest_configure(config):
|
|
|
1727
1743
|
sb_config.extension_dir = config.getoption("extension_dir")
|
|
1728
1744
|
sb_config.disable_features = config.getoption("disable_features")
|
|
1729
1745
|
sb_config.binary_location = config.getoption("binary_location")
|
|
1730
|
-
if
|
|
1746
|
+
if getattr(sb_config, "_cdp_bin_loc", None):
|
|
1731
1747
|
sb_config.binary_location = sb_config._cdp_bin_loc
|
|
1732
1748
|
elif not sb_config.binary_location:
|
|
1733
1749
|
if (
|
|
@@ -1758,7 +1774,9 @@ def pytest_configure(config):
|
|
|
1758
1774
|
bin_loc = detect_b_ver.get_binary_location("atlas")
|
|
1759
1775
|
if bin_loc and os.path.exists(bin_loc):
|
|
1760
1776
|
sb_config.binary_location = bin_loc
|
|
1761
|
-
if config.getoption("
|
|
1777
|
+
if config.getoption("use_chromium") and not sb_config.binary_location:
|
|
1778
|
+
sb_config.binary_location = "_chromium_"
|
|
1779
|
+
elif config.getoption("use_cft") and not sb_config.binary_location:
|
|
1762
1780
|
sb_config.binary_location = "cft"
|
|
1763
1781
|
elif config.getoption("use_chs") and not sb_config.binary_location:
|
|
1764
1782
|
sb_config.binary_location = "chs"
|
|
@@ -1918,26 +1936,16 @@ def pytest_configure(config):
|
|
|
1918
1936
|
or " -n=" in arg_join
|
|
1919
1937
|
or " -n" in arg_join
|
|
1920
1938
|
or "-c" in sys_argv
|
|
1921
|
-
or (
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
"-n=" in config.inicfg["addopts"]
|
|
1925
|
-
or "-n " in config.inicfg["addopts"]
|
|
1926
|
-
or "-n" in config.inicfg["addopts"]
|
|
1927
|
-
)
|
|
1928
|
-
)
|
|
1939
|
+
or "-n=" in config.getini("addopts")
|
|
1940
|
+
or "-n " in config.getini("addopts")
|
|
1941
|
+
or "-n" in config.getini("addopts")
|
|
1929
1942
|
):
|
|
1930
1943
|
sb_config._multithreaded = True
|
|
1931
1944
|
if (
|
|
1932
1945
|
"--html" in sys_argv
|
|
1933
1946
|
or " --html=" in arg_join
|
|
1934
|
-
or (
|
|
1935
|
-
|
|
1936
|
-
and (
|
|
1937
|
-
"--html=" in config.inicfg["addopts"]
|
|
1938
|
-
or "--html " in config.inicfg["addopts"]
|
|
1939
|
-
)
|
|
1940
|
-
)
|
|
1947
|
+
or "--html=" in config.getini("addopts")
|
|
1948
|
+
or "--html " in config.getini("addopts")
|
|
1941
1949
|
):
|
|
1942
1950
|
sb_config._using_html_report = True
|
|
1943
1951
|
sb_config._html_report_name = config.getoption("htmlpath")
|
|
@@ -2195,16 +2203,12 @@ def pytest_runtest_teardown(item):
|
|
|
2195
2203
|
self = item._testcase
|
|
2196
2204
|
with suppress(Exception):
|
|
2197
2205
|
if (
|
|
2198
|
-
|
|
2199
|
-
and self.driver
|
|
2206
|
+
getattr(self, "driver", None)
|
|
2200
2207
|
and "--pdb" not in sys_argv
|
|
2201
2208
|
):
|
|
2202
2209
|
if not (is_windows or self.driver.service.process):
|
|
2203
2210
|
self.driver.quit()
|
|
2204
|
-
elif (
|
|
2205
|
-
hasattr(sb_config, "_sb_pdb_driver")
|
|
2206
|
-
and sb_config._sb_pdb_driver
|
|
2207
|
-
):
|
|
2211
|
+
elif getattr(sb_config, "_sb_pdb_driver", None):
|
|
2208
2212
|
with suppress(Exception):
|
|
2209
2213
|
if (
|
|
2210
2214
|
not is_windows
|
|
@@ -2214,32 +2218,18 @@ def pytest_runtest_teardown(item):
|
|
|
2214
2218
|
sb_config._sb_pdb_driver = None
|
|
2215
2219
|
with suppress(Exception):
|
|
2216
2220
|
if (
|
|
2217
|
-
|
|
2218
|
-
and self._xvfb_display
|
|
2221
|
+
getattr(self, "_xvfb_display", None)
|
|
2219
2222
|
and hasattr(self._xvfb_display, "stop")
|
|
2220
|
-
and (
|
|
2221
|
-
not hasattr(sb_config, "reuse_session")
|
|
2222
|
-
or (
|
|
2223
|
-
hasattr(sb_config, "reuse_session")
|
|
2224
|
-
and not sb_config.reuse_session
|
|
2225
|
-
)
|
|
2226
|
-
)
|
|
2223
|
+
and not getattr(sb_config, "reuse_session", None)
|
|
2227
2224
|
):
|
|
2228
2225
|
self.headless_active = False
|
|
2229
2226
|
sb_config.headless_active = False
|
|
2230
2227
|
self._xvfb_display.stop()
|
|
2231
2228
|
self._xvfb_display = None
|
|
2232
2229
|
if (
|
|
2233
|
-
|
|
2234
|
-
and sb_config._virtual_display
|
|
2230
|
+
getattr(sb_config, "_virtual_display", None)
|
|
2235
2231
|
and hasattr(sb_config._virtual_display, "stop")
|
|
2236
|
-
and (
|
|
2237
|
-
not hasattr(sb_config, "reuse_session")
|
|
2238
|
-
or (
|
|
2239
|
-
hasattr(sb_config, "reuse_session")
|
|
2240
|
-
and not sb_config.reuse_session
|
|
2241
|
-
)
|
|
2242
|
-
)
|
|
2232
|
+
and not getattr(sb_config, "reuse_session", None)
|
|
2243
2233
|
):
|
|
2244
2234
|
sb_config._virtual_display.stop()
|
|
2245
2235
|
sb_config._virtual_display = None
|
|
@@ -2338,12 +2328,9 @@ def _perform_pytest_unconfigure_(config):
|
|
|
2338
2328
|
else:
|
|
2339
2329
|
start_time = reporter._session_start.time # (pytest >= 8.4.0)
|
|
2340
2330
|
duration = time.time() - start_time
|
|
2341
|
-
if (
|
|
2342
|
-
(hasattr(sb_config, "multi_proxy") and not sb_config.multi_proxy)
|
|
2343
|
-
or not hasattr(sb_config, "multi_proxy")
|
|
2344
|
-
):
|
|
2331
|
+
if not getattr(sb_config, "multi_proxy", None):
|
|
2345
2332
|
proxy_helper.remove_proxy_zip_if_present()
|
|
2346
|
-
if
|
|
2333
|
+
if getattr(sb_config, "reuse_session", None):
|
|
2347
2334
|
# Close the shared browser session
|
|
2348
2335
|
if sb_config.shared_driver:
|
|
2349
2336
|
try:
|
|
@@ -2360,14 +2347,13 @@ def _perform_pytest_unconfigure_(config):
|
|
|
2360
2347
|
sb_config.shared_driver = None
|
|
2361
2348
|
with suppress(Exception):
|
|
2362
2349
|
if (
|
|
2363
|
-
|
|
2364
|
-
and sb_config._virtual_display
|
|
2350
|
+
getattr(sb_config, "_virtual_display", None)
|
|
2365
2351
|
and hasattr(sb_config._virtual_display, "stop")
|
|
2366
2352
|
):
|
|
2367
2353
|
sb_config._virtual_display.stop()
|
|
2368
2354
|
sb_config._virtual_display = None
|
|
2369
2355
|
sb_config.headless_active = False
|
|
2370
|
-
if
|
|
2356
|
+
if getattr(sb_config, "_vd_list", None):
|
|
2371
2357
|
if isinstance(sb_config._vd_list, list):
|
|
2372
2358
|
for display in sb_config._vd_list:
|
|
2373
2359
|
if display:
|
|
@@ -2382,7 +2368,7 @@ def _perform_pytest_unconfigure_(config):
|
|
|
2382
2368
|
shared_utils.make_dir_files_writable("./assets/")
|
|
2383
2369
|
log_helper.clear_empty_logs()
|
|
2384
2370
|
# Dashboard post-processing: Disable time-based refresh and stamp complete
|
|
2385
|
-
if not
|
|
2371
|
+
if not getattr(sb_config, "dashboard", None):
|
|
2386
2372
|
html_report_path = None
|
|
2387
2373
|
the_html_r = None
|
|
2388
2374
|
abs_path = os.path.abspath(".")
|
|
@@ -2687,11 +2673,11 @@ def pytest_unconfigure(config):
|
|
|
2687
2673
|
)
|
|
2688
2674
|
):
|
|
2689
2675
|
return
|
|
2690
|
-
if
|
|
2676
|
+
if getattr(sb_config, "_multithreaded", None):
|
|
2691
2677
|
import fasteners
|
|
2692
2678
|
|
|
2693
2679
|
dash_lock = fasteners.InterProcessLock(constants.Dashboard.LOCKFILE)
|
|
2694
|
-
if
|
|
2680
|
+
if getattr(sb_config, "dashboard", None):
|
|
2695
2681
|
# Multi-threaded tests with the Dashboard
|
|
2696
2682
|
abs_path = os.path.abspath(".")
|
|
2697
2683
|
dash_lock_file = constants.Dashboard.LOCKFILE
|
|
@@ -10,13 +10,13 @@ Example -->
|
|
|
10
10
|
```python
|
|
11
11
|
from seleniumbase import SB
|
|
12
12
|
|
|
13
|
-
with SB(uc=True) as sb:
|
|
14
|
-
|
|
15
|
-
sb.
|
|
16
|
-
sb.
|
|
17
|
-
sb.
|
|
18
|
-
sb.
|
|
19
|
-
sb.
|
|
13
|
+
with SB(uc=True, test=True) as sb:
|
|
14
|
+
url = "https://google.com/ncr"
|
|
15
|
+
sb.activate_cdp_mode(url)
|
|
16
|
+
sb.type('[title="Search"]', "SeleniumBase GitHub page")
|
|
17
|
+
sb.click("div:not([jsname]) > * > input")
|
|
18
|
+
sb.sleep(2)
|
|
19
|
+
print(sb.get_page_title())
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
# (The browser exits automatically after the "with" block ends.)
|
|
@@ -123,6 +123,7 @@ def SB(
|
|
|
123
123
|
wfa=None, # Shortcut / Duplicate of "wait_for_angularjs".
|
|
124
124
|
cft=None, # Use "Chrome for Testing"
|
|
125
125
|
chs=None, # Use "Chrome-Headless-Shell"
|
|
126
|
+
use_chromium=None, # Use base "Chromium"
|
|
126
127
|
save_screenshot=None, # Save a screenshot at the end of each test.
|
|
127
128
|
no_screenshot=None, # No screenshots saved unless tests directly ask it.
|
|
128
129
|
page_load_strategy=None, # Set Chrome PLS to "normal", "eager", or "none".
|
|
@@ -144,14 +145,13 @@ def SB(
|
|
|
144
145
|
.. code-block:: python
|
|
145
146
|
from seleniumbase import SB
|
|
146
147
|
|
|
147
|
-
with SB() as sb:
|
|
148
|
-
|
|
149
|
-
sb.
|
|
150
|
-
sb.
|
|
151
|
-
sb.click(
|
|
152
|
-
sb.
|
|
153
|
-
sb.
|
|
154
|
-
sb.sleep(0.5)
|
|
148
|
+
with SB(uc=True, test=True) as sb:
|
|
149
|
+
url = "https://google.com/ncr"
|
|
150
|
+
sb.activate_cdp_mode(url)
|
|
151
|
+
sb.type('[title="Search"]', "SeleniumBase GitHub page")
|
|
152
|
+
sb.click("div:not([jsname]) > * > input")
|
|
153
|
+
sb.sleep(2)
|
|
154
|
+
print(sb.get_page_title())
|
|
155
155
|
|
|
156
156
|
Optional Parameters:
|
|
157
157
|
--------------------
|
|
@@ -700,11 +700,15 @@ def SB(
|
|
|
700
700
|
if arg.startswith("--bl="):
|
|
701
701
|
binary_location = arg.split("--bl=")[1]
|
|
702
702
|
break
|
|
703
|
-
if
|
|
703
|
+
if use_chromium and not binary_location:
|
|
704
|
+
binary_location = "_chromium_"
|
|
705
|
+
elif cft and not binary_location:
|
|
704
706
|
binary_location = "cft"
|
|
705
707
|
elif chs and not binary_location:
|
|
706
708
|
binary_location = "chs"
|
|
707
|
-
if "--
|
|
709
|
+
if "--use-chromium" in sys_argv and not binary_location:
|
|
710
|
+
binary_location = "_chromium_"
|
|
711
|
+
elif "--cft" in sys_argv and not binary_location:
|
|
708
712
|
binary_location = "cft"
|
|
709
713
|
elif "--chs" in sys_argv and not binary_location:
|
|
710
714
|
binary_location = "chs"
|
|
@@ -805,7 +809,7 @@ def SB(
|
|
|
805
809
|
and browser not in ["chrome", "opera", "brave", "comet", "atlas"]
|
|
806
810
|
):
|
|
807
811
|
message = (
|
|
808
|
-
'\n Undetected-Chromedriver Mode ONLY supports
|
|
812
|
+
'\n Undetected-Chromedriver Mode ONLY supports Chromium browsers!'
|
|
809
813
|
'\n ("uc=True" / "undetectable=True" / "--uc")'
|
|
810
814
|
'\n (Your browser choice was: "%s".)'
|
|
811
815
|
'\n (Will use "%s" without UC Mode.)\n' % (browser, browser)
|
|
@@ -831,7 +835,7 @@ def SB(
|
|
|
831
835
|
if headless2 and browser == "firefox":
|
|
832
836
|
headless2 = False # Only for Chromium browsers
|
|
833
837
|
headless = True # Firefox has regular headless
|
|
834
|
-
elif browser not in ["chrome", "edge"]:
|
|
838
|
+
elif browser not in ["chrome", "edge", "opera", "brave", "comet", "atlas"]:
|
|
835
839
|
headless2 = False # Only for Chromium browsers
|
|
836
840
|
if not headless and not headless2:
|
|
837
841
|
headed = True
|