seleniumbase 4.24.11__py3-none-any.whl → 4.33.15__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- sbase/__init__.py +1 -0
- sbase/steps.py +7 -0
- seleniumbase/__init__.py +16 -7
- seleniumbase/__version__.py +1 -1
- seleniumbase/behave/behave_sb.py +97 -32
- seleniumbase/common/decorators.py +16 -7
- seleniumbase/config/proxy_list.py +3 -3
- seleniumbase/config/settings.py +4 -0
- seleniumbase/console_scripts/logo_helper.py +47 -8
- seleniumbase/console_scripts/run.py +345 -335
- seleniumbase/console_scripts/sb_behave_gui.py +5 -12
- seleniumbase/console_scripts/sb_caseplans.py +6 -13
- seleniumbase/console_scripts/sb_commander.py +5 -12
- seleniumbase/console_scripts/sb_install.py +62 -54
- seleniumbase/console_scripts/sb_mkchart.py +13 -20
- seleniumbase/console_scripts/sb_mkdir.py +11 -17
- seleniumbase/console_scripts/sb_mkfile.py +69 -43
- seleniumbase/console_scripts/sb_mkpres.py +13 -20
- seleniumbase/console_scripts/sb_mkrec.py +88 -21
- seleniumbase/console_scripts/sb_objectify.py +30 -30
- seleniumbase/console_scripts/sb_print.py +5 -12
- seleniumbase/console_scripts/sb_recorder.py +16 -11
- seleniumbase/core/browser_launcher.py +1658 -221
- seleniumbase/core/log_helper.py +42 -27
- seleniumbase/core/mysql.py +1 -4
- seleniumbase/core/proxy_helper.py +35 -30
- seleniumbase/core/recorder_helper.py +24 -5
- seleniumbase/core/sb_cdp.py +1951 -0
- seleniumbase/core/sb_driver.py +162 -8
- seleniumbase/core/settings_parser.py +6 -0
- seleniumbase/core/style_sheet.py +10 -0
- seleniumbase/extensions/recorder.zip +0 -0
- seleniumbase/fixtures/base_case.py +1225 -614
- seleniumbase/fixtures/constants.py +10 -1
- seleniumbase/fixtures/js_utils.py +171 -144
- seleniumbase/fixtures/page_actions.py +177 -13
- seleniumbase/fixtures/page_utils.py +25 -53
- seleniumbase/fixtures/shared_utils.py +97 -11
- seleniumbase/js_code/active_css_js.py +1 -1
- seleniumbase/js_code/recorder_js.py +1 -1
- seleniumbase/plugins/base_plugin.py +2 -3
- seleniumbase/plugins/driver_manager.py +340 -65
- seleniumbase/plugins/pytest_plugin.py +276 -47
- seleniumbase/plugins/sb_manager.py +412 -99
- seleniumbase/plugins/selenium_plugin.py +122 -17
- seleniumbase/translate/translator.py +0 -7
- seleniumbase/undetected/__init__.py +59 -52
- seleniumbase/undetected/cdp.py +0 -1
- seleniumbase/undetected/cdp_driver/__init__.py +1 -0
- seleniumbase/undetected/cdp_driver/_contradict.py +110 -0
- seleniumbase/undetected/cdp_driver/browser.py +829 -0
- seleniumbase/undetected/cdp_driver/cdp_util.py +458 -0
- seleniumbase/undetected/cdp_driver/config.py +334 -0
- seleniumbase/undetected/cdp_driver/connection.py +639 -0
- seleniumbase/undetected/cdp_driver/element.py +1168 -0
- seleniumbase/undetected/cdp_driver/tab.py +1323 -0
- seleniumbase/undetected/dprocess.py +4 -7
- seleniumbase/undetected/options.py +6 -8
- seleniumbase/undetected/patcher.py +11 -13
- seleniumbase/undetected/reactor.py +0 -1
- seleniumbase/undetected/webelement.py +16 -3
- {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/LICENSE +1 -1
- {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/METADATA +299 -252
- {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/RECORD +67 -69
- {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/WHEEL +1 -1
- sbase/ReadMe.txt +0 -2
- seleniumbase/ReadMe.md +0 -25
- seleniumbase/common/ReadMe.md +0 -71
- seleniumbase/console_scripts/ReadMe.md +0 -731
- seleniumbase/drivers/ReadMe.md +0 -27
- seleniumbase/extensions/ReadMe.md +0 -12
- seleniumbase/masterqa/ReadMe.md +0 -61
- seleniumbase/resources/ReadMe.md +0 -31
- seleniumbase/resources/favicon.ico +0 -0
- seleniumbase/utilities/selenium_grid/ReadMe.md +0 -84
- seleniumbase/utilities/selenium_ide/ReadMe.md +0 -111
- {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/entry_points.txt +0 -0
- {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/top_level.txt +0 -0
seleniumbase/core/log_helper.py
CHANGED
@@ -3,9 +3,11 @@ import os
|
|
3
3
|
import shutil
|
4
4
|
import sys
|
5
5
|
import time
|
6
|
+
from contextlib import suppress
|
6
7
|
from seleniumbase import config as sb_config
|
7
8
|
from seleniumbase.config import settings
|
8
9
|
from seleniumbase.fixtures import constants
|
10
|
+
from seleniumbase.fixtures import shared_utils
|
9
11
|
|
10
12
|
python3_11_or_newer = False
|
11
13
|
if sys.version_info >= (3, 11):
|
@@ -13,6 +15,11 @@ if sys.version_info >= (3, 11):
|
|
13
15
|
py311_patch2 = constants.PatchPy311.PATCH
|
14
16
|
|
15
17
|
|
18
|
+
def __is_cdp_swap_needed(driver):
|
19
|
+
"""If the driver is disconnected, use a CDP method when available."""
|
20
|
+
return shared_utils.is_cdp_swap_needed(driver)
|
21
|
+
|
22
|
+
|
16
23
|
def log_screenshot(test_logpath, driver, screenshot=None, get=False):
|
17
24
|
screenshot_name = settings.SCREENSHOT_NAME
|
18
25
|
screenshot_path = os.path.join(test_logpath, screenshot_name)
|
@@ -32,6 +39,8 @@ def log_screenshot(test_logpath, driver, screenshot=None, get=False):
|
|
32
39
|
if screenshot != screenshot_warning:
|
33
40
|
with open(screenshot_path, "wb") as file:
|
34
41
|
file.write(screenshot)
|
42
|
+
with suppress(Exception):
|
43
|
+
shared_utils.make_writable(screenshot_path)
|
35
44
|
else:
|
36
45
|
print("WARNING: %s" % screenshot_warning)
|
37
46
|
if get:
|
@@ -281,14 +290,14 @@ def log_test_failure_data(test, test_logpath, driver, browser, url=None):
|
|
281
290
|
sb_config._report_time = the_time
|
282
291
|
sb_config._report_traceback = traceback_message
|
283
292
|
sb_config._report_exception = exc_message
|
284
|
-
|
285
|
-
|
293
|
+
if not os.path.exists(test_logpath):
|
294
|
+
with suppress(Exception):
|
286
295
|
os.makedirs(test_logpath)
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
296
|
+
with suppress(Exception):
|
297
|
+
log_file = codecs.open(basic_file_path, "w+", encoding="utf-8")
|
298
|
+
log_file.writelines("\r\n".join(data_to_save))
|
299
|
+
log_file.close()
|
300
|
+
shared_utils.make_writable(basic_file_path)
|
292
301
|
|
293
302
|
|
294
303
|
def log_skipped_test_data(test, test_logpath, driver, browser, reason):
|
@@ -297,16 +306,12 @@ def log_skipped_test_data(test, test_logpath, driver, browser, reason):
|
|
297
306
|
browser_version = None
|
298
307
|
driver_version = None
|
299
308
|
driver_name = None
|
300
|
-
|
309
|
+
with suppress(Exception):
|
301
310
|
browser_version = get_browser_version(driver)
|
302
|
-
|
303
|
-
pass
|
304
|
-
try:
|
311
|
+
with suppress(Exception):
|
305
312
|
driver_name, driver_version = get_driver_name_and_version(
|
306
313
|
driver, browser
|
307
314
|
)
|
308
|
-
except Exception:
|
309
|
-
pass
|
310
315
|
if browser_version:
|
311
316
|
headless = ""
|
312
317
|
if test.headless and browser in ["chrome", "edge", "firefox"]:
|
@@ -343,9 +348,11 @@ def log_skipped_test_data(test, test_logpath, driver, browser, reason):
|
|
343
348
|
data_to_save.append(" * Skip Reason: %s" % reason)
|
344
349
|
data_to_save.append("")
|
345
350
|
file_path = os.path.join(test_logpath, "skip_reason.txt")
|
346
|
-
|
347
|
-
|
348
|
-
|
351
|
+
with suppress(Exception):
|
352
|
+
log_file = codecs.open(file_path, "w+", encoding="utf-8")
|
353
|
+
log_file.writelines("\r\n".join(data_to_save))
|
354
|
+
log_file.close()
|
355
|
+
shared_utils.make_writable(file_path)
|
349
356
|
|
350
357
|
|
351
358
|
def log_page_source(test_logpath, driver, source=None):
|
@@ -354,7 +361,11 @@ def log_page_source(test_logpath, driver, source=None):
|
|
354
361
|
page_source = source
|
355
362
|
else:
|
356
363
|
try:
|
357
|
-
page_source =
|
364
|
+
page_source = None
|
365
|
+
if __is_cdp_swap_needed(driver):
|
366
|
+
page_source = driver.cdp.get_page_source()
|
367
|
+
else:
|
368
|
+
page_source = driver.page_source
|
358
369
|
page_source = get_html_source_with_base_href(driver, page_source)
|
359
370
|
except Exception:
|
360
371
|
source = constants.Warnings.PAGE_SOURCE_UNDEFINED
|
@@ -368,15 +379,15 @@ def log_page_source(test_logpath, driver, source=None):
|
|
368
379
|
"unresponsive, or closed prematurely!</h4>"
|
369
380
|
)
|
370
381
|
)
|
371
|
-
|
372
|
-
|
382
|
+
if not os.path.exists(test_logpath):
|
383
|
+
with suppress(Exception):
|
373
384
|
os.makedirs(test_logpath)
|
374
|
-
except Exception:
|
375
|
-
pass
|
376
385
|
html_file_path = os.path.join(test_logpath, html_file_name)
|
377
|
-
|
378
|
-
|
379
|
-
|
386
|
+
with suppress(Exception):
|
387
|
+
html_file = codecs.open(html_file_path, "w+", encoding="utf-8")
|
388
|
+
html_file.write(page_source)
|
389
|
+
html_file.close()
|
390
|
+
shared_utils.make_writable(html_file_path)
|
380
391
|
|
381
392
|
|
382
393
|
def get_test_id(test):
|
@@ -446,7 +457,11 @@ def get_test_name(test):
|
|
446
457
|
|
447
458
|
def get_last_page(driver):
|
448
459
|
try:
|
449
|
-
last_page =
|
460
|
+
last_page = None
|
461
|
+
if __is_cdp_swap_needed(driver):
|
462
|
+
last_page = driver.cdp.get_current_url()
|
463
|
+
else:
|
464
|
+
last_page = driver.current_url
|
450
465
|
except Exception:
|
451
466
|
last_page = "[WARNING! Browser Not Open!]"
|
452
467
|
if len(last_page) < 5:
|
@@ -543,7 +558,7 @@ def log_folder_setup(log_path, archive_logs=False):
|
|
543
558
|
try:
|
544
559
|
os.makedirs(log_path)
|
545
560
|
except Exception:
|
546
|
-
pass #
|
561
|
+
pass # Only reachable during multi-threaded runs
|
547
562
|
else:
|
548
563
|
saved_folder = "%s/../%s/" % (log_path, constants.Logs.SAVED)
|
549
564
|
archived_folder = os.path.realpath(saved_folder) + "/"
|
@@ -551,7 +566,7 @@ def log_folder_setup(log_path, archive_logs=False):
|
|
551
566
|
try:
|
552
567
|
os.makedirs(archived_folder)
|
553
568
|
except Exception:
|
554
|
-
pass #
|
569
|
+
pass # Only reachable during multi-threaded runs
|
555
570
|
archived_logs = "%slogs_%s" % (archived_folder, int(time.time()))
|
556
571
|
if len(os.listdir(log_path)) > 0:
|
557
572
|
try:
|
seleniumbase/core/mysql.py
CHANGED
@@ -35,10 +35,7 @@ class DatabaseManager:
|
|
35
35
|
import cryptography # noqa: F401
|
36
36
|
import pymysql
|
37
37
|
except Exception:
|
38
|
-
|
39
|
-
shared_utils.pip_install("PyMySQL[rsa]", version="1.0.2")
|
40
|
-
else:
|
41
|
-
shared_utils.pip_install("PyMySQL[rsa]", version="1.1.0")
|
38
|
+
shared_utils.pip_install("PyMySQL[rsa]", version="1.1.1")
|
42
39
|
import pymysql
|
43
40
|
db_server = settings.DB_HOST
|
44
41
|
db_port = settings.DB_PORT
|
@@ -2,10 +2,12 @@ import os
|
|
2
2
|
import re
|
3
3
|
import warnings
|
4
4
|
import zipfile
|
5
|
+
from contextlib import suppress
|
5
6
|
from seleniumbase.config import proxy_list
|
6
7
|
from seleniumbase.config import settings
|
7
8
|
from seleniumbase.fixtures import constants
|
8
9
|
from seleniumbase.fixtures import page_utils
|
10
|
+
from seleniumbase.fixtures import shared_utils
|
9
11
|
|
10
12
|
DOWNLOADS_DIR = constants.Files.DOWNLOADS_FOLDER
|
11
13
|
PROXY_ZIP_PATH = os.path.join(DOWNLOADS_DIR, "proxy.zip")
|
@@ -109,31 +111,35 @@ def create_proxy_ext(
|
|
109
111
|
""""minimum_chrome_version":"22.0.0"\n"""
|
110
112
|
"""}"""
|
111
113
|
)
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
proxy_ext_dir
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
114
|
+
abs_path = os.path.abspath(".")
|
115
|
+
downloads_path = os.path.join(abs_path, DOWNLOADS_DIR)
|
116
|
+
if not os.path.exists(downloads_path):
|
117
|
+
os.mkdir(downloads_path)
|
118
|
+
if zip_it:
|
119
|
+
zf = zipfile.ZipFile(PROXY_ZIP_PATH, mode="w")
|
120
|
+
zf.writestr("background.js", background_js)
|
121
|
+
zf.writestr("manifest.json", manifest_json)
|
122
|
+
zf.close()
|
123
|
+
with suppress(Exception):
|
124
|
+
shared_utils.make_writable(PROXY_ZIP_PATH)
|
125
|
+
else:
|
126
|
+
proxy_ext_dir = PROXY_DIR_PATH
|
127
|
+
if not os.path.exists(proxy_ext_dir):
|
128
|
+
os.mkdir(proxy_ext_dir)
|
129
|
+
with suppress(Exception):
|
130
|
+
shared_utils.make_writable(proxy_ext_dir)
|
131
|
+
manifest_file = os.path.join(proxy_ext_dir, "manifest.json")
|
132
|
+
with open(manifest_file, mode="w") as f:
|
133
|
+
f.write(manifest_json)
|
134
|
+
with suppress(Exception):
|
135
|
+
shared_utils.make_writable(manifest_json)
|
136
|
+
proxy_host = proxy_string.split(":")[0]
|
137
|
+
proxy_port = proxy_string.split(":")[1]
|
138
|
+
background_file = os.path.join(proxy_ext_dir, "background.js")
|
139
|
+
with open(background_file, mode="w") as f:
|
140
|
+
f.write(background_js)
|
141
|
+
with suppress(Exception):
|
142
|
+
shared_utils.make_writable(background_js)
|
137
143
|
|
138
144
|
|
139
145
|
def remove_proxy_zip_if_present():
|
@@ -141,13 +147,12 @@ def remove_proxy_zip_if_present():
|
|
141
147
|
Used in the implementation of https://stackoverflow.com/a/35293284
|
142
148
|
for https://stackoverflow.com/questions/12848327/
|
143
149
|
"""
|
144
|
-
|
145
|
-
|
150
|
+
if os.path.exists(PROXY_ZIP_PATH):
|
151
|
+
with suppress(Exception):
|
146
152
|
os.remove(PROXY_ZIP_PATH)
|
147
|
-
|
153
|
+
if os.path.exists(PROXY_ZIP_LOCK):
|
154
|
+
with suppress(Exception):
|
148
155
|
os.remove(PROXY_ZIP_LOCK)
|
149
|
-
except Exception:
|
150
|
-
pass
|
151
156
|
|
152
157
|
|
153
158
|
def validate_proxy_string(proxy_string):
|
@@ -422,9 +422,14 @@ def generate_sbase_code(srt_actions):
|
|
422
422
|
):
|
423
423
|
import unicodedata
|
424
424
|
|
425
|
-
|
426
|
-
|
427
|
-
|
425
|
+
text_list = False
|
426
|
+
try:
|
427
|
+
action[1][0] = unicodedata.normalize("NFKC", action[1][0])
|
428
|
+
action[1][0] = action[1][0].replace("\n", "\\n")
|
429
|
+
action[1][0] = action[1][0].replace("\u00B6", "")
|
430
|
+
except Exception:
|
431
|
+
text_list = True
|
432
|
+
|
428
433
|
method = "assert_text"
|
429
434
|
if action[0] == "as_et":
|
430
435
|
method = "assert_exact_text"
|
@@ -437,7 +442,17 @@ def generate_sbase_code(srt_actions):
|
|
437
442
|
elif action[0] == "da_et":
|
438
443
|
method = "deferred_assert_exact_text"
|
439
444
|
if action[1][1] != "html":
|
440
|
-
if
|
445
|
+
if text_list and '"' not in action[1][1]:
|
446
|
+
sb_actions.append(
|
447
|
+
'self.%s(%s, "%s")'
|
448
|
+
% (method, action[1][0], action[1][1])
|
449
|
+
)
|
450
|
+
elif text_list and "'" not in action[1][1]:
|
451
|
+
sb_actions.append(
|
452
|
+
"self.%s(%s, '%s')"
|
453
|
+
% (method, action[1][0], action[1][1])
|
454
|
+
)
|
455
|
+
elif '"' not in action[1][0] and '"' not in action[1][1]:
|
441
456
|
sb_actions.append(
|
442
457
|
'self.%s("%s", "%s")'
|
443
458
|
% (method, action[1][0], action[1][1])
|
@@ -458,7 +473,11 @@ def generate_sbase_code(srt_actions):
|
|
458
473
|
% (method, action[1][0], action[1][1])
|
459
474
|
)
|
460
475
|
else:
|
461
|
-
if
|
476
|
+
if text_list:
|
477
|
+
sb_actions.append(
|
478
|
+
'self.%s(%s)' % (method, action[1][0])
|
479
|
+
)
|
480
|
+
elif '"' not in action[1][0]:
|
462
481
|
sb_actions.append(
|
463
482
|
'self.%s("%s")' % (method, action[1][0])
|
464
483
|
)
|