seleniumbase 4.33.4__py3-none-any.whl → 4.34.2__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- seleniumbase/__version__.py +1 -1
- seleniumbase/behave/behave_sb.py +10 -2
- seleniumbase/console_scripts/run.py +6 -2
- seleniumbase/console_scripts/sb_commander.py +5 -5
- seleniumbase/console_scripts/sb_install.py +235 -6
- seleniumbase/console_scripts/sb_mkdir.py +1 -0
- seleniumbase/core/browser_launcher.py +358 -105
- seleniumbase/core/log_helper.py +33 -12
- seleniumbase/core/proxy_helper.py +35 -30
- seleniumbase/core/sb_cdp.py +277 -74
- seleniumbase/core/settings_parser.py +2 -0
- seleniumbase/core/style_sheet.py +10 -0
- seleniumbase/fixtures/base_case.py +216 -127
- seleniumbase/fixtures/constants.py +3 -0
- seleniumbase/fixtures/js_utils.py +2 -0
- seleniumbase/fixtures/page_actions.py +7 -2
- seleniumbase/fixtures/shared_utils.py +25 -0
- seleniumbase/plugins/driver_manager.py +28 -0
- seleniumbase/plugins/pytest_plugin.py +110 -0
- seleniumbase/plugins/sb_manager.py +41 -0
- seleniumbase/plugins/selenium_plugin.py +9 -0
- seleniumbase/undetected/cdp_driver/_contradict.py +3 -3
- seleniumbase/undetected/cdp_driver/browser.py +8 -6
- seleniumbase/undetected/cdp_driver/cdp_util.py +3 -0
- seleniumbase/undetected/cdp_driver/config.py +0 -1
- seleniumbase/undetected/cdp_driver/element.py +22 -20
- seleniumbase/undetected/patcher.py +20 -5
- {seleniumbase-4.33.4.dist-info → seleniumbase-4.34.2.dist-info}/LICENSE +1 -1
- {seleniumbase-4.33.4.dist-info → seleniumbase-4.34.2.dist-info}/METADATA +111 -86
- {seleniumbase-4.33.4.dist-info → seleniumbase-4.34.2.dist-info}/RECORD +33 -33
- {seleniumbase-4.33.4.dist-info → seleniumbase-4.34.2.dist-info}/WHEEL +1 -1
- {seleniumbase-4.33.4.dist-info → seleniumbase-4.34.2.dist-info}/entry_points.txt +0 -0
- {seleniumbase-4.33.4.dist-info → seleniumbase-4.34.2.dist-info}/top_level.txt +0 -0
@@ -400,6 +400,7 @@ class ValidBinaries:
|
|
400
400
|
"google-chrome-beta",
|
401
401
|
"google-chrome-dev",
|
402
402
|
"google-chrome-unstable",
|
403
|
+
"chrome-headless-shell",
|
403
404
|
"brave-browser",
|
404
405
|
"brave-browser-stable",
|
405
406
|
"brave",
|
@@ -418,6 +419,7 @@ class ValidBinaries:
|
|
418
419
|
"Google Chrome",
|
419
420
|
"Chromium",
|
420
421
|
"Google Chrome for Testing",
|
422
|
+
"chrome-headless-shell",
|
421
423
|
"Google Chrome Beta",
|
422
424
|
"Google Chrome Dev",
|
423
425
|
"Brave Browser",
|
@@ -429,6 +431,7 @@ class ValidBinaries:
|
|
429
431
|
valid_chrome_binaries_on_windows = [
|
430
432
|
"chrome.exe",
|
431
433
|
"chromium.exe",
|
434
|
+
"chrome-headless-shell.exe",
|
432
435
|
"brave.exe",
|
433
436
|
"opera.exe",
|
434
437
|
]
|
@@ -1188,6 +1188,8 @@ def highlight_with_jquery_2(driver, message, selector, o_bs, msg_dur):
|
|
1188
1188
|
def get_active_element_css(driver):
|
1189
1189
|
from seleniumbase.js_code import active_css_js
|
1190
1190
|
|
1191
|
+
if shared_utils.is_cdp_swap_needed(driver):
|
1192
|
+
return driver.cdp.get_active_element_css()
|
1191
1193
|
return execute_script(driver, active_css_js.get_active_element_css)
|
1192
1194
|
|
1193
1195
|
|
@@ -1342,7 +1342,8 @@ def save_page_source(driver, name, folder=None):
|
|
1342
1342
|
"""
|
1343
1343
|
from seleniumbase.core import log_helper
|
1344
1344
|
|
1345
|
-
|
1345
|
+
if not __is_cdp_swap_needed(driver):
|
1346
|
+
_reconnect_if_disconnected(driver) # If disconnected without CDP
|
1346
1347
|
if not name.endswith(".html"):
|
1347
1348
|
name = name + ".html"
|
1348
1349
|
if folder:
|
@@ -1353,7 +1354,11 @@ def save_page_source(driver, name, folder=None):
|
|
1353
1354
|
html_file_path = os.path.join(file_path, name)
|
1354
1355
|
else:
|
1355
1356
|
html_file_path = name
|
1356
|
-
page_source =
|
1357
|
+
page_source = None
|
1358
|
+
if __is_cdp_swap_needed(driver):
|
1359
|
+
page_source = driver.cdp.get_page_source()
|
1360
|
+
else:
|
1361
|
+
page_source = driver.page_source
|
1357
1362
|
html_file = codecs.open(html_file_path, "w+", "utf-8")
|
1358
1363
|
rendered_source = log_helper.get_html_source_with_base_href(
|
1359
1364
|
driver, page_source
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"""Shared utility methods"""
|
2
2
|
import colorama
|
3
3
|
import os
|
4
|
+
import pathlib
|
4
5
|
import platform
|
5
6
|
import sys
|
6
7
|
import time
|
@@ -128,6 +129,30 @@ def is_chrome_130_or_newer(self, binary_location=None):
|
|
128
129
|
return False
|
129
130
|
|
130
131
|
|
132
|
+
def make_dir_files_writable(dir_path):
|
133
|
+
# Make all files in the given directory writable.
|
134
|
+
for file_path in pathlib.Path(dir_path).glob("*"):
|
135
|
+
if file_path.is_file():
|
136
|
+
mode = os.stat(file_path).st_mode
|
137
|
+
mode |= (mode & 0o444) >> 1 # copy R bits to W
|
138
|
+
with suppress(Exception):
|
139
|
+
os.chmod(file_path, mode)
|
140
|
+
|
141
|
+
|
142
|
+
def make_writable(file_path):
|
143
|
+
# Set permissions to: "If you can read it, you can write it."
|
144
|
+
mode = os.stat(file_path).st_mode
|
145
|
+
mode |= (mode & 0o444) >> 1 # copy R bits to W
|
146
|
+
os.chmod(file_path, mode)
|
147
|
+
|
148
|
+
|
149
|
+
def make_executable(file_path):
|
150
|
+
# Set permissions to: "If you can read it, you can execute it."
|
151
|
+
mode = os.stat(file_path).st_mode
|
152
|
+
mode |= (mode & 0o444) >> 2 # copy R bits to X
|
153
|
+
os.chmod(file_path, mode)
|
154
|
+
|
155
|
+
|
131
156
|
def format_exc(exception, message):
|
132
157
|
"""Formats an exception message to make the output cleaner."""
|
133
158
|
from selenium.common.exceptions import ElementNotVisibleException
|
@@ -530,6 +530,34 @@ def Driver(
|
|
530
530
|
break
|
531
531
|
count += 1
|
532
532
|
user_agent = agent
|
533
|
+
found_bl = None
|
534
|
+
if binary_location is None and "--binary-location" in arg_join:
|
535
|
+
count = 0
|
536
|
+
for arg in sys_argv:
|
537
|
+
if arg.startswith("--binary-location="):
|
538
|
+
found_bl = arg.split("--binary-location=")[1]
|
539
|
+
break
|
540
|
+
elif arg == "--binary-location" and len(sys_argv) > count + 1:
|
541
|
+
found_bl = sys_argv[count + 1]
|
542
|
+
if found_bl.startswith("-"):
|
543
|
+
found_bl = None
|
544
|
+
break
|
545
|
+
count += 1
|
546
|
+
if found_bl:
|
547
|
+
binary_location = found_bl
|
548
|
+
if binary_location is None and "--bl=" in arg_join:
|
549
|
+
for arg in sys_argv:
|
550
|
+
if arg.startswith("--bl="):
|
551
|
+
binary_location = arg.split("--bl=")[1]
|
552
|
+
break
|
553
|
+
if (
|
554
|
+
binary_location
|
555
|
+
and binary_location.lower() == "chs"
|
556
|
+
and browser == "chrome"
|
557
|
+
):
|
558
|
+
headless = True
|
559
|
+
headless1 = False
|
560
|
+
headless2 = False
|
533
561
|
recorder_mode = False
|
534
562
|
if recorder_ext:
|
535
563
|
recorder_mode = True
|
@@ -656,6 +656,7 @@ def pytest_addoption(parser):
|
|
656
656
|
parser.addoption(
|
657
657
|
"--binary_location",
|
658
658
|
"--binary-location",
|
659
|
+
"--bl",
|
659
660
|
action="store",
|
660
661
|
dest="binary_location",
|
661
662
|
default=None,
|
@@ -1371,6 +1372,7 @@ def pytest_addoption(parser):
|
|
1371
1372
|
|
1372
1373
|
arg_join = " ".join(sys_argv)
|
1373
1374
|
sb_config._browser_shortcut = None
|
1375
|
+
sb_config._vd_list = []
|
1374
1376
|
|
1375
1377
|
# SeleniumBase does not support pytest-timeout due to hanging browsers.
|
1376
1378
|
for arg in sys_argv:
|
@@ -1573,6 +1575,14 @@ def pytest_configure(config):
|
|
1573
1575
|
sb_config.extension_dir = config.getoption("extension_dir")
|
1574
1576
|
sb_config.disable_features = config.getoption("disable_features")
|
1575
1577
|
sb_config.binary_location = config.getoption("binary_location")
|
1578
|
+
if (
|
1579
|
+
sb_config.binary_location
|
1580
|
+
and sb_config.binary_location.lower() == "chs"
|
1581
|
+
and sb_config.browser == "chrome"
|
1582
|
+
):
|
1583
|
+
sb_config.headless = True
|
1584
|
+
sb_config.headless1 = False
|
1585
|
+
sb_config.headless2 = False
|
1576
1586
|
sb_config.driver_version = config.getoption("driver_version")
|
1577
1587
|
sb_config.page_load_strategy = config.getoption("page_load_strategy")
|
1578
1588
|
sb_config.with_testing_base = config.getoption("with_testing_base")
|
@@ -1709,6 +1719,7 @@ def pytest_configure(config):
|
|
1709
1719
|
sb_config._saved_dashboard_pie = None # Copy of pie chart for html report
|
1710
1720
|
sb_config._dash_final_summary = None # Dash status to add to html report
|
1711
1721
|
sb_config._html_report_name = None # The name of the pytest html report
|
1722
|
+
sb_config._html_report_copy = None # The copy of the pytest html report
|
1712
1723
|
|
1713
1724
|
arg_join = " ".join(sys_argv)
|
1714
1725
|
if (
|
@@ -1742,6 +1753,7 @@ def pytest_configure(config):
|
|
1742
1753
|
if sb_config.dashboard:
|
1743
1754
|
if sb_config._html_report_name == "dashboard.html":
|
1744
1755
|
sb_config._dash_is_html_report = True
|
1756
|
+
sb_config._html_report_copy = "last_report.html"
|
1745
1757
|
|
1746
1758
|
# Recorder Mode does not support multi-threaded / multi-process runs.
|
1747
1759
|
if sb_config.recorder_mode and sb_config._multithreaded:
|
@@ -2015,6 +2027,13 @@ def pytest_runtest_teardown(item):
|
|
2015
2027
|
hasattr(self, "_xvfb_display")
|
2016
2028
|
and self._xvfb_display
|
2017
2029
|
and hasattr(self._xvfb_display, "stop")
|
2030
|
+
and (
|
2031
|
+
not hasattr(sb_config, "reuse_session")
|
2032
|
+
or (
|
2033
|
+
hasattr(sb_config, "reuse_session")
|
2034
|
+
and not sb_config.reuse_session
|
2035
|
+
)
|
2036
|
+
)
|
2018
2037
|
):
|
2019
2038
|
self.headless_active = False
|
2020
2039
|
sb_config.headless_active = False
|
@@ -2024,6 +2043,13 @@ def pytest_runtest_teardown(item):
|
|
2024
2043
|
hasattr(sb_config, "_virtual_display")
|
2025
2044
|
and sb_config._virtual_display
|
2026
2045
|
and hasattr(sb_config._virtual_display, "stop")
|
2046
|
+
and (
|
2047
|
+
not hasattr(sb_config, "reuse_session")
|
2048
|
+
or (
|
2049
|
+
hasattr(sb_config, "reuse_session")
|
2050
|
+
and not sb_config.reuse_session
|
2051
|
+
)
|
2052
|
+
)
|
2027
2053
|
):
|
2028
2054
|
sb_config._virtual_display.stop()
|
2029
2055
|
sb_config._virtual_display = None
|
@@ -2137,10 +2163,28 @@ def _perform_pytest_unconfigure_(config):
|
|
2137
2163
|
except Exception:
|
2138
2164
|
pass
|
2139
2165
|
sb_config.shared_driver = None
|
2166
|
+
with suppress(Exception):
|
2167
|
+
if (
|
2168
|
+
hasattr(sb_config, "_virtual_display")
|
2169
|
+
and sb_config._virtual_display
|
2170
|
+
and hasattr(sb_config._virtual_display, "stop")
|
2171
|
+
):
|
2172
|
+
sb_config._virtual_display.stop()
|
2173
|
+
sb_config._virtual_display = None
|
2174
|
+
sb_config.headless_active = False
|
2175
|
+
if hasattr(sb_config, "_vd_list") and sb_config._vd_list:
|
2176
|
+
if isinstance(sb_config._vd_list, list):
|
2177
|
+
for display in sb_config._vd_list:
|
2178
|
+
if display:
|
2179
|
+
with suppress(Exception):
|
2180
|
+
display.stop()
|
2140
2181
|
if hasattr(sb_config, "log_path") and sb_config.item_count > 0:
|
2141
2182
|
log_helper.archive_logs_if_set(
|
2142
2183
|
constants.Logs.LATEST + "/", sb_config.archive_logs
|
2143
2184
|
)
|
2185
|
+
if os.path.exists("./assets/"): # Used by pytest-html reports
|
2186
|
+
with suppress(Exception):
|
2187
|
+
shared_utils.make_dir_files_writable("./assets/")
|
2144
2188
|
log_helper.clear_empty_logs()
|
2145
2189
|
# Dashboard post-processing: Disable time-based refresh and stamp complete
|
2146
2190
|
if not hasattr(sb_config, "dashboard") or not sb_config.dashboard:
|
@@ -2151,6 +2195,10 @@ def _perform_pytest_unconfigure_(config):
|
|
2151
2195
|
html_report_path = os.path.join(
|
2152
2196
|
abs_path, sb_config._html_report_name
|
2153
2197
|
)
|
2198
|
+
if sb_config._html_report_copy:
|
2199
|
+
html_report_path_copy = os.path.join(
|
2200
|
+
abs_path, sb_config._html_report_copy
|
2201
|
+
)
|
2154
2202
|
if (
|
2155
2203
|
sb_config._using_html_report
|
2156
2204
|
and html_report_path
|
@@ -2184,6 +2232,9 @@ def _perform_pytest_unconfigure_(config):
|
|
2184
2232
|
the_html_r = the_html_r.replace(
|
2185
2233
|
ph_link, "%s and %s" % (sb_link, ph_link)
|
2186
2234
|
)
|
2235
|
+
the_html_r = the_html_r.replace(
|
2236
|
+
"findAll('.collapsible", "//findAll('.collapsible"
|
2237
|
+
)
|
2187
2238
|
the_html_r = the_html_r.replace(
|
2188
2239
|
"mediaName.innerText", "//mediaName.innerText"
|
2189
2240
|
)
|
@@ -2201,6 +2252,31 @@ def _perform_pytest_unconfigure_(config):
|
|
2201
2252
|
)
|
2202
2253
|
with open(html_report_path, "w", encoding="utf-8") as f:
|
2203
2254
|
f.write(the_html_r) # Finalize the HTML report
|
2255
|
+
with suppress(Exception):
|
2256
|
+
shared_utils.make_writable(html_report_path)
|
2257
|
+
with open(html_report_path_copy, "w", encoding="utf-8") as f:
|
2258
|
+
f.write(the_html_r) # Finalize the HTML report copy
|
2259
|
+
with suppress(Exception):
|
2260
|
+
shared_utils.make_writable(html_report_path_copy)
|
2261
|
+
assets_style = "./assets/style.css"
|
2262
|
+
if os.path.exists(assets_style):
|
2263
|
+
html_style = None
|
2264
|
+
with open(assets_style, "r", encoding="utf-8") as f:
|
2265
|
+
html_style = f.read()
|
2266
|
+
if html_style:
|
2267
|
+
html_style = html_style.replace("top: -50px;", "top: 2px;")
|
2268
|
+
html_style = html_style.replace("+ 50px)", "+ 40px)")
|
2269
|
+
html_style = html_style.replace("ht: 240px;", "ht: 228px;")
|
2270
|
+
html_style = html_style.replace(
|
2271
|
+
"- 80px);", "- 80px);\n margin-bottom: -42px;"
|
2272
|
+
)
|
2273
|
+
html_style = html_style.replace(".collapsible", ".oldc")
|
2274
|
+
html_style = html_style.replace(" (hide details)", "")
|
2275
|
+
html_style = html_style.replace(" (show details)", "")
|
2276
|
+
with open(assets_style, "w", encoding="utf-8") as f:
|
2277
|
+
f.write(html_style)
|
2278
|
+
with suppress(Exception):
|
2279
|
+
shared_utils.make_writable(assets_style)
|
2204
2280
|
# Done with "pytest_unconfigure" unless using the Dashboard
|
2205
2281
|
return
|
2206
2282
|
stamp = ""
|
@@ -2282,12 +2358,37 @@ def _perform_pytest_unconfigure_(config):
|
|
2282
2358
|
)
|
2283
2359
|
with open(dashboard_path, "w", encoding="utf-8") as f:
|
2284
2360
|
f.write(the_html_d) # Finalize the dashboard
|
2361
|
+
with suppress(Exception):
|
2362
|
+
shared_utils.make_writable(dashboard_path)
|
2363
|
+
assets_style = "./assets/style.css"
|
2364
|
+
if os.path.exists(assets_style):
|
2365
|
+
html_style = None
|
2366
|
+
with open(assets_style, "r", encoding="utf-8") as f:
|
2367
|
+
html_style = f.read()
|
2368
|
+
if html_style:
|
2369
|
+
html_style = html_style.replace("top: -50px;", "top: 2px;")
|
2370
|
+
html_style = html_style.replace("+ 50px)", "+ 40px)")
|
2371
|
+
html_style = html_style.replace("ht: 240px;", "ht: 228px;")
|
2372
|
+
html_style = html_style.replace(
|
2373
|
+
"- 80px);", "- 80px);\n margin-bottom: -42px;"
|
2374
|
+
)
|
2375
|
+
html_style = html_style.replace(".collapsible", ".oldc")
|
2376
|
+
html_style = html_style.replace(" (hide details)", "")
|
2377
|
+
html_style = html_style.replace(" (show details)", "")
|
2378
|
+
with open(assets_style, "w", encoding="utf-8") as f:
|
2379
|
+
f.write(html_style)
|
2380
|
+
with suppress(Exception):
|
2381
|
+
shared_utils.make_writable(assets_style)
|
2285
2382
|
# Part 2: Appending a pytest html report with dashboard data
|
2286
2383
|
html_report_path = None
|
2287
2384
|
if sb_config._html_report_name:
|
2288
2385
|
html_report_path = os.path.join(
|
2289
2386
|
abs_path, sb_config._html_report_name
|
2290
2387
|
)
|
2388
|
+
if sb_config._html_report_copy:
|
2389
|
+
html_report_path_copy = os.path.join(
|
2390
|
+
abs_path, sb_config._html_report_copy
|
2391
|
+
)
|
2291
2392
|
if (
|
2292
2393
|
sb_config._using_html_report
|
2293
2394
|
and html_report_path
|
@@ -2341,6 +2442,9 @@ def _perform_pytest_unconfigure_(config):
|
|
2341
2442
|
the_html_r = the_html_r.replace(
|
2342
2443
|
ph_link, "%s and %s" % (sb_link, ph_link)
|
2343
2444
|
)
|
2445
|
+
the_html_r = the_html_r.replace(
|
2446
|
+
"findAll('.collapsible", "//findAll('.collapsible"
|
2447
|
+
)
|
2344
2448
|
the_html_r = the_html_r.replace(
|
2345
2449
|
"mediaName.innerText", "//mediaName.innerText"
|
2346
2450
|
)
|
@@ -2358,6 +2462,12 @@ def _perform_pytest_unconfigure_(config):
|
|
2358
2462
|
)
|
2359
2463
|
with open(html_report_path, "w", encoding="utf-8") as f:
|
2360
2464
|
f.write(the_html_r) # Finalize the HTML report
|
2465
|
+
with suppress(Exception):
|
2466
|
+
shared_utils.make_writable(html_report_path)
|
2467
|
+
with open(html_report_path_copy, "w", encoding="utf-8") as f:
|
2468
|
+
f.write(the_html_r) # Finalize the HTML report copy
|
2469
|
+
with suppress(Exception):
|
2470
|
+
shared_utils.make_writable(html_report_path_copy)
|
2361
2471
|
except KeyboardInterrupt:
|
2362
2472
|
pass
|
2363
2473
|
except Exception:
|
@@ -568,6 +568,34 @@ def SB(
|
|
568
568
|
break
|
569
569
|
count += 1
|
570
570
|
user_agent = agent
|
571
|
+
found_bl = None
|
572
|
+
if binary_location is None and "--binary-location" in arg_join:
|
573
|
+
count = 0
|
574
|
+
for arg in sys_argv:
|
575
|
+
if arg.startswith("--binary-location="):
|
576
|
+
found_bl = arg.split("--binary-location=")[1]
|
577
|
+
break
|
578
|
+
elif arg == "--binary-location" and len(sys_argv) > count + 1:
|
579
|
+
found_bl = sys_argv[count + 1]
|
580
|
+
if found_bl.startswith("-"):
|
581
|
+
found_bl = None
|
582
|
+
break
|
583
|
+
count += 1
|
584
|
+
if found_bl:
|
585
|
+
binary_location = found_bl
|
586
|
+
if binary_location is None and "--bl=" in arg_join:
|
587
|
+
for arg in sys_argv:
|
588
|
+
if arg.startswith("--bl="):
|
589
|
+
binary_location = arg.split("--bl=")[1]
|
590
|
+
break
|
591
|
+
if (
|
592
|
+
binary_location
|
593
|
+
and binary_location.lower() == "chs"
|
594
|
+
and browser == "chrome"
|
595
|
+
):
|
596
|
+
headless = True
|
597
|
+
headless1 = False
|
598
|
+
headless2 = False
|
571
599
|
recorder_mode = False
|
572
600
|
if recorder_ext:
|
573
601
|
recorder_mode = True
|
@@ -1256,6 +1284,19 @@ def SB(
|
|
1256
1284
|
print(traceback.format_exc().strip())
|
1257
1285
|
if test and not test_passed:
|
1258
1286
|
print("********** ERROR: The test AND the tearDown() FAILED!")
|
1287
|
+
if (
|
1288
|
+
hasattr(sb_config, "_virtual_display")
|
1289
|
+
and sb_config._virtual_display
|
1290
|
+
and hasattr(sb_config._virtual_display, "stop")
|
1291
|
+
):
|
1292
|
+
try:
|
1293
|
+
sb_config._virtual_display.stop()
|
1294
|
+
sb_config._virtual_display = None
|
1295
|
+
sb_config.headless_active = False
|
1296
|
+
except AttributeError:
|
1297
|
+
pass
|
1298
|
+
except Exception:
|
1299
|
+
pass
|
1259
1300
|
end_time = time.time()
|
1260
1301
|
run_time = end_time - start_time
|
1261
1302
|
sb_config = sb_config_backup
|
@@ -397,6 +397,7 @@ class SeleniumBrowser(Plugin):
|
|
397
397
|
parser.addoption(
|
398
398
|
"--binary_location",
|
399
399
|
"--binary-location",
|
400
|
+
"--bl",
|
400
401
|
action="store",
|
401
402
|
dest="binary_location",
|
402
403
|
default=None,
|
@@ -1202,6 +1203,14 @@ class SeleniumBrowser(Plugin):
|
|
1202
1203
|
test.test.extension_dir = self.options.extension_dir
|
1203
1204
|
test.test.disable_features = self.options.disable_features
|
1204
1205
|
test.test.binary_location = self.options.binary_location
|
1206
|
+
if (
|
1207
|
+
test.test.binary_location
|
1208
|
+
and test.test.binary_location.lower() == "chs"
|
1209
|
+
and test.test.browser == "chrome"
|
1210
|
+
):
|
1211
|
+
test.test.headless = True
|
1212
|
+
test.test.headless1 = False
|
1213
|
+
test.test.headless2 = False
|
1205
1214
|
test.test.driver_version = self.options.driver_version
|
1206
1215
|
test.test.page_load_strategy = self.options.page_load_strategy
|
1207
1216
|
test.test.chromium_arg = self.options.chromium_arg
|
@@ -31,12 +31,12 @@ class ContraDict(dict):
|
|
31
31
|
|
32
32
|
def __init__(self, *args, **kwargs):
|
33
33
|
super().__init__()
|
34
|
-
silent = kwargs.pop("silent", False)
|
34
|
+
# silent = kwargs.pop("silent", False)
|
35
35
|
_ = dict(*args, **kwargs)
|
36
36
|
|
37
37
|
super().__setattr__("__dict__", self)
|
38
38
|
for k, v in _.items():
|
39
|
-
_check_key(k, self, False,
|
39
|
+
_check_key(k, self, False, True)
|
40
40
|
super().__setitem__(k, _wrap(self.__class__, v))
|
41
41
|
|
42
42
|
def __setitem__(self, key, value):
|
@@ -90,7 +90,7 @@ _warning_names_message = """\n\
|
|
90
90
|
|
91
91
|
|
92
92
|
def _check_key(
|
93
|
-
key: str, mapping: _Mapping, boolean: bool = False, silent=
|
93
|
+
key: str, mapping: _Mapping, boolean: bool = False, silent=True
|
94
94
|
):
|
95
95
|
"""Checks `key` and warns if needed.
|
96
96
|
:param key:
|
@@ -10,6 +10,7 @@ import pathlib
|
|
10
10
|
import pickle
|
11
11
|
import re
|
12
12
|
import shutil
|
13
|
+
import time
|
13
14
|
import urllib.parse
|
14
15
|
import urllib.request
|
15
16
|
import warnings
|
@@ -30,8 +31,6 @@ def get_registered_instances():
|
|
30
31
|
|
31
32
|
|
32
33
|
def deconstruct_browser():
|
33
|
-
import time
|
34
|
-
|
35
34
|
for _ in __registered__instances__:
|
36
35
|
if not _.stopped:
|
37
36
|
_.stop()
|
@@ -117,8 +116,13 @@ class Browser:
|
|
117
116
|
port=port,
|
118
117
|
**kwargs,
|
119
118
|
)
|
120
|
-
|
121
|
-
|
119
|
+
try:
|
120
|
+
instance = cls(config)
|
121
|
+
await instance.start()
|
122
|
+
except Exception:
|
123
|
+
time.sleep(0.15)
|
124
|
+
instance = cls(config)
|
125
|
+
await instance.start()
|
122
126
|
return instance
|
123
127
|
|
124
128
|
def __init__(self, config: Config, **kwargs):
|
@@ -379,8 +383,6 @@ class Browser:
|
|
379
383
|
--------------------------------
|
380
384
|
Failed to connect to the browser
|
381
385
|
--------------------------------
|
382
|
-
Possibly because you are running as "root".
|
383
|
-
If so, you may need to use no_sandbox=True.
|
384
386
|
"""
|
385
387
|
)
|
386
388
|
)
|
@@ -84,6 +84,9 @@ def __activate_virtual_display_as_needed(
|
|
84
84
|
"\nX11 display failed! Will use regular xvfb!"
|
85
85
|
)
|
86
86
|
__activate_standard_virtual_display()
|
87
|
+
else:
|
88
|
+
sb_config._virtual_display = _xvfb_display
|
89
|
+
sb_config.headless_active = True
|
87
90
|
except Exception as e:
|
88
91
|
if hasattr(e, "msg"):
|
89
92
|
print("\n" + str(e.msg))
|
@@ -1,6 +1,5 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
import asyncio
|
3
|
-
import json
|
4
3
|
import logging
|
5
4
|
import pathlib
|
6
5
|
import secrets
|
@@ -387,18 +386,16 @@ class Element:
|
|
387
386
|
|
388
387
|
async def get_js_attributes_async(self):
|
389
388
|
return ContraDict(
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
389
|
+
await self.apply(
|
390
|
+
"""
|
391
|
+
function (e) {
|
392
|
+
let o = {}
|
393
|
+
for(let k in e){
|
394
|
+
o[k] = e[k]
|
395
|
+
}
|
396
|
+
return o
|
397
397
|
}
|
398
|
-
|
399
|
-
}
|
400
|
-
"""
|
401
|
-
)
|
398
|
+
"""
|
402
399
|
)
|
403
400
|
)
|
404
401
|
|
@@ -441,12 +438,15 @@ class Element:
|
|
441
438
|
)
|
442
439
|
)
|
443
440
|
)
|
444
|
-
|
445
|
-
if
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
441
|
+
try:
|
442
|
+
if result and result[0]:
|
443
|
+
if return_by_value:
|
444
|
+
return result[0].value
|
445
|
+
return result[0]
|
446
|
+
elif result[1]:
|
447
|
+
return result[1]
|
448
|
+
except Exception:
|
449
|
+
return self
|
450
450
|
|
451
451
|
async def get_position_async(self, abs=False) -> Position:
|
452
452
|
if not self.parent or not self.object_id:
|
@@ -883,6 +883,8 @@ class Element:
|
|
883
883
|
self,
|
884
884
|
duration: typing.Union[float, int] = 0.5,
|
885
885
|
color: typing.Optional[str] = "EE4488",
|
886
|
+
x_offset: typing.Union[float, int] = 0,
|
887
|
+
y_offset: typing.Union[float, int] = 0,
|
886
888
|
):
|
887
889
|
"""
|
888
890
|
Displays for a short time a red dot on the element.
|
@@ -910,8 +912,8 @@ class Element:
|
|
910
912
|
"width:8px;height:8px;border-radius:50%;background:#{};"
|
911
913
|
"animation:show-pointer-ani {:.2f}s ease 1;"
|
912
914
|
).format(
|
913
|
-
pos.center[0] - 4, # -4 to account for
|
914
|
-
pos.center[1] - 4,
|
915
|
+
pos.center[0] + x_offset - 4, # -4 to account for the circle
|
916
|
+
pos.center[1] + y_offset - 4, # -4 to account for the circle
|
915
917
|
color,
|
916
918
|
duration,
|
917
919
|
)
|
@@ -8,6 +8,8 @@ import sys
|
|
8
8
|
import time
|
9
9
|
import zipfile
|
10
10
|
from contextlib import suppress
|
11
|
+
from seleniumbase.console_scripts import sb_install
|
12
|
+
from seleniumbase.fixtures import shared_utils
|
11
13
|
|
12
14
|
logger = logging.getLogger(__name__)
|
13
15
|
IS_POSIX = sys.platform.startswith(("darwin", "cygwin", "linux"))
|
@@ -106,7 +108,14 @@ class Patcher(object):
|
|
106
108
|
release = self.fetch_release_number()
|
107
109
|
self.version_main = release.split(".")[0]
|
108
110
|
self.version_full = release
|
109
|
-
|
111
|
+
if int(self.version_main) < 115:
|
112
|
+
self.unzip_package(self.fetch_package())
|
113
|
+
else:
|
114
|
+
sb_install.main(
|
115
|
+
override="chromedriver %s" % self.version_main,
|
116
|
+
intel_for_uc=shared_utils.is_arm_mac(),
|
117
|
+
force_uc=True,
|
118
|
+
)
|
110
119
|
return self.patch()
|
111
120
|
|
112
121
|
def patch(self):
|
@@ -121,6 +130,12 @@ class Patcher(object):
|
|
121
130
|
path += "_%s" % self.version_main
|
122
131
|
path = path.upper()
|
123
132
|
logger.debug("Getting release number from %s" % path)
|
133
|
+
if self.version_main and int(self.version_main) > 114:
|
134
|
+
return (
|
135
|
+
sb_install.get_cft_latest_version_from_milestone(
|
136
|
+
str(self.version_main)
|
137
|
+
)
|
138
|
+
)
|
124
139
|
return urlopen(self.url_repo + path).read().decode()
|
125
140
|
|
126
141
|
def fetch_package(self):
|
@@ -187,7 +202,7 @@ class Patcher(object):
|
|
187
202
|
with io.open(executable_path, "rb") as fh:
|
188
203
|
if re.search(
|
189
204
|
b"window.cdc_adoQpoasnfa76pfcZLmcfl_"
|
190
|
-
b"(Array|Promise|Symbol|Object|Proxy|JSON)",
|
205
|
+
b"(Array|Promise|Symbol|Object|Proxy|JSON|Window)",
|
191
206
|
fh.read()
|
192
207
|
):
|
193
208
|
return False
|
@@ -210,14 +225,14 @@ class Patcher(object):
|
|
210
225
|
file_bin = fh.read()
|
211
226
|
file_bin = re.sub(
|
212
227
|
b"window\\.cdc_[a-zA-Z0-9]{22}_"
|
213
|
-
b"(Array|Promise|Symbol|Object|Proxy|JSON)"
|
214
|
-
b"
|
228
|
+
b"(Array|Promise|Symbol|Object|Proxy|JSON|Window) "
|
229
|
+
b"= window\\.(Array|Promise|Symbol|Object|Proxy|JSON|Window);",
|
215
230
|
gen_js_whitespaces,
|
216
231
|
file_bin,
|
217
232
|
)
|
218
233
|
file_bin = re.sub(
|
219
234
|
b"window\\.cdc_[a-zA-Z0-9]{22}_"
|
220
|
-
b"(Array|Promise|Symbol|Object|Proxy|JSON) \\|\\|",
|
235
|
+
b"(Array|Promise|Symbol|Object|Proxy|JSON|Window) \\|\\|",
|
221
236
|
gen_js_whitespaces,
|
222
237
|
file_bin,
|
223
238
|
)
|