seleniumbase 4.24.10__py3-none-any.whl → 4.33.15__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.
- 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/detect_b_ver.py +7 -8
- 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 +1234 -632
- 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.10.dist-info → seleniumbase-4.33.15.dist-info}/LICENSE +1 -1
- {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/METADATA +299 -252
- {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/RECORD +68 -70
- {seleniumbase-4.24.10.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.10.dist-info → seleniumbase-4.33.15.dist-info}/entry_points.txt +0 -0
- {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/top_level.txt +0 -0
@@ -4,6 +4,7 @@ import os
|
|
4
4
|
import pytest
|
5
5
|
import sys
|
6
6
|
import time
|
7
|
+
from contextlib import suppress
|
7
8
|
from seleniumbase import config as sb_config
|
8
9
|
from seleniumbase.config import settings
|
9
10
|
from seleniumbase.core import log_helper
|
@@ -16,6 +17,7 @@ if sys.version_info >= (3, 11):
|
|
16
17
|
python3_11_or_newer = True
|
17
18
|
py311_patch2 = constants.PatchPy311.PATCH
|
18
19
|
sys_argv = sys.argv
|
20
|
+
full_time = None
|
19
21
|
pytest_plugins = ["pytester"] # Adds the "testdir" fixture
|
20
22
|
|
21
23
|
|
@@ -59,11 +61,14 @@ def pytest_addoption(parser):
|
|
59
61
|
--binary-location=PATH (Set path of the Chromium browser binary to use.)
|
60
62
|
--driver-version=VER (Set the chromedriver or uc_driver version to use.)
|
61
63
|
--sjw (Skip JS Waits for readyState to be "complete" or Angular to load.)
|
64
|
+
--wfa (Wait for AngularJS to be done loading after specific web actions.)
|
62
65
|
--pls=PLS (Set pageLoadStrategy on Chrome: "normal", "eager", or "none".)
|
63
|
-
--headless (
|
64
|
-
--
|
66
|
+
--headless (The default headless mode. Linux uses this mode by default.)
|
67
|
+
--headless1 (Use Chrome's old headless mode. Fast, but has limitations.)
|
68
|
+
--headless2 (Use Chrome's new headless mode, which supports extensions.)
|
65
69
|
--headed (Run tests in headed/GUI mode on Linux OS, where not default.)
|
66
70
|
--xvfb (Run tests using the Xvfb virtual display server on Linux OS.)
|
71
|
+
--xvfb-metrics=STRING (Set Xvfb display size on Linux: "Width,Height".)
|
67
72
|
--locale=LOCALE_CODE (Set the Language Locale Code for the web browser.)
|
68
73
|
--interval=SECONDS (The autoplay interval for presentations & tour steps)
|
69
74
|
--start-page=URL (The starting URL for the web browser when tests begin.)
|
@@ -81,10 +86,12 @@ def pytest_addoption(parser):
|
|
81
86
|
--block-images (Block images from loading during tests.)
|
82
87
|
--do-not-track (Indicate to websites that you don't want to be tracked.)
|
83
88
|
--verify-delay=SECONDS (The delay before MasterQA verification checks.)
|
89
|
+
--ee / --esc-end (Lets the user end the current test via the ESC key.)
|
84
90
|
--recorder (Enables the Recorder for turning browser actions into code.)
|
85
91
|
--rec-behave (Same as Recorder Mode, but also generates behave-gherkin.)
|
86
92
|
--rec-sleep (If the Recorder is enabled, also records self.sleep calls.)
|
87
93
|
--rec-print (If the Recorder is enabled, prints output after tests end.)
|
94
|
+
--disable-cookies (Disable Cookies on websites. Pages might break!)
|
88
95
|
--disable-js (Disable JavaScript on websites. Pages might break!)
|
89
96
|
--disable-csp (Disable the Content Security Policy of websites.)
|
90
97
|
--disable-ws (Disable Web Security on Chromium-based browsers.)
|
@@ -107,6 +114,7 @@ def pytest_addoption(parser):
|
|
107
114
|
--rcs | --reuse-class-session (Reuse session for tests in class.)
|
108
115
|
--crumbs (Delete all cookies between tests reusing a session.)
|
109
116
|
--disable-beforeunload (Disable the "beforeunload" event on Chrome.)
|
117
|
+
--window-position=X,Y (Set the browser's starting window position.)
|
110
118
|
--window-size=WIDTH,HEIGHT (Set the browser's starting window size.)
|
111
119
|
--maximize (Start tests with the browser window maximized.)
|
112
120
|
--screenshot (Save a screenshot at the end of each test.)
|
@@ -123,10 +131,6 @@ def pytest_addoption(parser):
|
|
123
131
|
cr = ""
|
124
132
|
if "linux" not in sys.platform:
|
125
133
|
# This will be seen when typing "pytest --help" on the command line.
|
126
|
-
if is_windows and hasattr(colorama, "just_fix_windows_console"):
|
127
|
-
colorama.just_fix_windows_console()
|
128
|
-
else:
|
129
|
-
colorama.init(autoreset=True)
|
130
134
|
c1 = colorama.Fore.BLUE + colorama.Back.LIGHTCYAN_EX
|
131
135
|
c2 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
|
132
136
|
c3 = colorama.Fore.MAGENTA + colorama.Back.LIGHTYELLOW_EX
|
@@ -357,6 +361,17 @@ def pytest_addoption(parser):
|
|
357
361
|
and wait_for_angularjs(), which are part of many
|
358
362
|
SeleniumBase methods for improving reliability.""",
|
359
363
|
)
|
364
|
+
parser.addoption(
|
365
|
+
"--wfa",
|
366
|
+
"--wait_for_angularjs",
|
367
|
+
"--wait-for-angularjs",
|
368
|
+
action="store_true",
|
369
|
+
dest="wait_for_angularjs",
|
370
|
+
default=False,
|
371
|
+
help="""Add waiting for AngularJS. (The default setting
|
372
|
+
was changed to no longer wait for AngularJS to
|
373
|
+
finish loading as an extra JavaScript call.)""",
|
374
|
+
)
|
360
375
|
parser.addoption(
|
361
376
|
"--with-db_reporting",
|
362
377
|
"--with-db-reporting",
|
@@ -684,6 +699,15 @@ def pytest_addoption(parser):
|
|
684
699
|
UNLESS using a virtual display with Xvfb.
|
685
700
|
Default: False on Mac/Windows. True on Linux.""",
|
686
701
|
)
|
702
|
+
parser.addoption(
|
703
|
+
"--headless1",
|
704
|
+
action="store_true",
|
705
|
+
dest="headless1",
|
706
|
+
default=False,
|
707
|
+
help="""This option activates the old headless mode,
|
708
|
+
which is faster, but has limitations.
|
709
|
+
(May be phased out by Chrome in the future.)""",
|
710
|
+
)
|
687
711
|
parser.addoption(
|
688
712
|
"--headless2",
|
689
713
|
action="store_true",
|
@@ -715,6 +739,17 @@ def pytest_addoption(parser):
|
|
715
739
|
will no longer be enabled by default on Linux.
|
716
740
|
Default: False. (Linux-ONLY!)""",
|
717
741
|
)
|
742
|
+
parser.addoption(
|
743
|
+
"--xvfb-metrics",
|
744
|
+
"--xvfb_metrics",
|
745
|
+
action="store",
|
746
|
+
dest="xvfb_metrics",
|
747
|
+
default=None,
|
748
|
+
help="""Customize the Xvfb metrics (Width,Height) on Linux.
|
749
|
+
Format: A comma-separated string with the 2 values.
|
750
|
+
Examples: "1920,1080" or "1366,768" or "1024,768".
|
751
|
+
Default: None. (None: "1366,768". Min: "1024,768".)""",
|
752
|
+
)
|
718
753
|
parser.addoption(
|
719
754
|
"--locale_code",
|
720
755
|
"--locale-code",
|
@@ -895,6 +930,16 @@ def pytest_addoption(parser):
|
|
895
930
|
help="""Setting this overrides the default wait time
|
896
931
|
before each MasterQA verification pop-up.""",
|
897
932
|
)
|
933
|
+
parser.addoption(
|
934
|
+
"--esc-end",
|
935
|
+
"--esc_end",
|
936
|
+
"--ee",
|
937
|
+
action="store_true",
|
938
|
+
dest="esc_end",
|
939
|
+
default=False,
|
940
|
+
help="""End the current test early via the ESC key.
|
941
|
+
The test will be marked as skipped.""",
|
942
|
+
)
|
898
943
|
parser.addoption(
|
899
944
|
"--recorder",
|
900
945
|
"--record",
|
@@ -945,6 +990,15 @@ def pytest_addoption(parser):
|
|
945
990
|
help="""The option to disable JavaScript on web pages.
|
946
991
|
Warning: Most web pages will stop working!""",
|
947
992
|
)
|
993
|
+
parser.addoption(
|
994
|
+
"--disable_cookies",
|
995
|
+
"--disable-cookies",
|
996
|
+
action="store_true",
|
997
|
+
dest="disable_cookies",
|
998
|
+
default=False,
|
999
|
+
help="""The option to disable Cookies on web pages.
|
1000
|
+
Warning: Several pages may stop working!""",
|
1001
|
+
)
|
948
1002
|
parser.addoption(
|
949
1003
|
"--disable_csp",
|
950
1004
|
"--disable-csp",
|
@@ -964,6 +1018,7 @@ def pytest_addoption(parser):
|
|
964
1018
|
parser.addoption(
|
965
1019
|
"--disable_ws",
|
966
1020
|
"--disable-ws",
|
1021
|
+
"--dws",
|
967
1022
|
"--disable-web-security",
|
968
1023
|
action="store_true",
|
969
1024
|
dest="disable_ws",
|
@@ -1206,6 +1261,17 @@ def pytest_addoption(parser):
|
|
1206
1261
|
on Chromium browsers (Chrome or Edge).
|
1207
1262
|
This is already the default Firefox option.""",
|
1208
1263
|
)
|
1264
|
+
parser.addoption(
|
1265
|
+
"--window-position",
|
1266
|
+
"--window_position",
|
1267
|
+
action="store",
|
1268
|
+
dest="window_position",
|
1269
|
+
default=None,
|
1270
|
+
help="""The option to set the starting window x,y position
|
1271
|
+
Format: A comma-separated string with the 2 values.
|
1272
|
+
Example: "55,66"
|
1273
|
+
Default: None. (Will use default values if None)""",
|
1274
|
+
)
|
1209
1275
|
parser.addoption(
|
1210
1276
|
"--window-size",
|
1211
1277
|
"--window_size",
|
@@ -1485,6 +1551,9 @@ def pytest_configure(config):
|
|
1485
1551
|
sb_config.mobile_emulator = config.getoption("mobile_emulator")
|
1486
1552
|
sb_config.device_metrics = config.getoption("device_metrics")
|
1487
1553
|
sb_config.headless = config.getoption("headless")
|
1554
|
+
sb_config.headless1 = config.getoption("headless1")
|
1555
|
+
if sb_config.headless1:
|
1556
|
+
sb_config.headless = True
|
1488
1557
|
sb_config.headless2 = config.getoption("headless2")
|
1489
1558
|
if sb_config.headless2 and sb_config.browser == "firefox":
|
1490
1559
|
sb_config.headless2 = False # Only for Chromium browsers
|
@@ -1493,6 +1562,7 @@ def pytest_configure(config):
|
|
1493
1562
|
sb_config.headless2 = False # Only for Chromium browsers
|
1494
1563
|
sb_config.headed = config.getoption("headed")
|
1495
1564
|
sb_config.xvfb = config.getoption("xvfb")
|
1565
|
+
sb_config.xvfb_metrics = config.getoption("xvfb_metrics")
|
1496
1566
|
sb_config.locale_code = config.getoption("locale_code")
|
1497
1567
|
sb_config.interval = config.getoption("interval")
|
1498
1568
|
sb_config.start_page = config.getoption("start_page")
|
@@ -1535,6 +1605,8 @@ def pytest_configure(config):
|
|
1535
1605
|
settings.ARCHIVE_EXISTING_DOWNLOADS = True
|
1536
1606
|
if config.getoption("skip_js_waits"):
|
1537
1607
|
settings.SKIP_JS_WAITS = True
|
1608
|
+
if config.getoption("wait_for_angularjs"):
|
1609
|
+
settings.WAIT_FOR_ANGULARJS = True
|
1538
1610
|
sb_config.all_scripts = config.getoption("all_scripts")
|
1539
1611
|
sb_config._time_limit = config.getoption("time_limit")
|
1540
1612
|
sb_config.time_limit = config.getoption("time_limit")
|
@@ -1549,6 +1621,7 @@ def pytest_configure(config):
|
|
1549
1621
|
sb_config.block_images = config.getoption("block_images")
|
1550
1622
|
sb_config.do_not_track = config.getoption("do_not_track")
|
1551
1623
|
sb_config.verify_delay = config.getoption("verify_delay")
|
1624
|
+
sb_config.esc_end = config.getoption("esc_end")
|
1552
1625
|
sb_config.recorder_mode = config.getoption("recorder_mode")
|
1553
1626
|
sb_config.recorder_ext = config.getoption("recorder_mode") # Again
|
1554
1627
|
sb_config.rec_behave = config.getoption("rec_behave")
|
@@ -1563,6 +1636,7 @@ def pytest_configure(config):
|
|
1563
1636
|
elif sb_config.record_sleep and not sb_config.recorder_mode:
|
1564
1637
|
sb_config.recorder_mode = True
|
1565
1638
|
sb_config.recorder_ext = True
|
1639
|
+
sb_config.disable_cookies = config.getoption("disable_cookies")
|
1566
1640
|
sb_config.disable_js = config.getoption("disable_js")
|
1567
1641
|
sb_config.disable_csp = config.getoption("disable_csp")
|
1568
1642
|
sb_config.disable_ws = config.getoption("disable_ws")
|
@@ -1598,6 +1672,7 @@ def pytest_configure(config):
|
|
1598
1672
|
sb_config.shared_driver = None # The default driver for session reuse
|
1599
1673
|
sb_config.crumbs = config.getoption("crumbs")
|
1600
1674
|
sb_config._disable_beforeunload = config.getoption("_disable_beforeunload")
|
1675
|
+
sb_config.window_position = config.getoption("window_position")
|
1601
1676
|
sb_config.window_size = config.getoption("window_size")
|
1602
1677
|
sb_config.maximize_option = config.getoption("maximize_option")
|
1603
1678
|
sb_config.save_screenshot = config.getoption("save_screenshot")
|
@@ -1634,6 +1709,7 @@ def pytest_configure(config):
|
|
1634
1709
|
sb_config._saved_dashboard_pie = None # Copy of pie chart for html report
|
1635
1710
|
sb_config._dash_final_summary = None # Dash status to add to html report
|
1636
1711
|
sb_config._html_report_name = None # The name of the pytest html report
|
1712
|
+
sb_config._html_report_copy = None # The copy of the pytest html report
|
1637
1713
|
|
1638
1714
|
arg_join = " ".join(sys_argv)
|
1639
1715
|
if (
|
@@ -1667,6 +1743,7 @@ def pytest_configure(config):
|
|
1667
1743
|
if sb_config.dashboard:
|
1668
1744
|
if sb_config._html_report_name == "dashboard.html":
|
1669
1745
|
sb_config._dash_is_html_report = True
|
1746
|
+
sb_config._html_report_copy = "last_report.html"
|
1670
1747
|
|
1671
1748
|
# Recorder Mode does not support multi-threaded / multi-process runs.
|
1672
1749
|
if sb_config.recorder_mode and sb_config._multithreaded:
|
@@ -1691,18 +1768,22 @@ def pytest_configure(config):
|
|
1691
1768
|
and not sb_config.headless2
|
1692
1769
|
and not sb_config.xvfb
|
1693
1770
|
):
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1700
|
-
|
1701
|
-
|
1771
|
+
if not sb_config.undetectable:
|
1772
|
+
print(
|
1773
|
+
"(Linux uses --headless by default. "
|
1774
|
+
"To override, use --headed / --gui. "
|
1775
|
+
"For Xvfb mode instead, use --xvfb. "
|
1776
|
+
"Or you can hide this info by using "
|
1777
|
+
"--headless / --headless2 / --uc.)"
|
1778
|
+
)
|
1779
|
+
sb_config.headless = True
|
1780
|
+
else:
|
1781
|
+
sb_config.xvfb = True
|
1702
1782
|
|
1703
1783
|
# Recorder Mode can still optimize scripts in --headless2 mode.
|
1704
1784
|
if sb_config.recorder_mode and sb_config.headless:
|
1705
1785
|
sb_config.headless = False
|
1786
|
+
sb_config.headless1 = False
|
1706
1787
|
sb_config.headless2 = True
|
1707
1788
|
|
1708
1789
|
if not sb_config.headless and not sb_config.headless2:
|
@@ -1723,6 +1804,7 @@ def pytest_configure(config):
|
|
1723
1804
|
|
1724
1805
|
if sb_config.browser == "safari" and sb_config.headless:
|
1725
1806
|
sb_config.headless = False # Safari doesn't support headless mode
|
1807
|
+
sb_config.headless1 = False
|
1726
1808
|
|
1727
1809
|
if sb_config.dash_title:
|
1728
1810
|
constants.Dashboard.TITLE = sb_config.dash_title.replace("_", " ")
|
@@ -1793,10 +1875,8 @@ def _create_dashboard_assets_():
|
|
1793
1875
|
abs_path = os.path.abspath(".")
|
1794
1876
|
assets_folder = os.path.join(abs_path, "assets")
|
1795
1877
|
if not os.path.exists(assets_folder):
|
1796
|
-
|
1878
|
+
with suppress(Exception):
|
1797
1879
|
os.makedirs(assets_folder, exist_ok=True)
|
1798
|
-
except Exception:
|
1799
|
-
pass
|
1800
1880
|
pytest_style_css = os.path.join(assets_folder, "pytest_style.css")
|
1801
1881
|
add_pytest_style_css = True
|
1802
1882
|
if os.path.exists(pytest_style_css):
|
@@ -1868,20 +1948,14 @@ def pytest_collection_finish(session):
|
|
1868
1948
|
dash_path = os.path.join(os.getcwd(), "dashboard.html")
|
1869
1949
|
dash_url = "file://" + dash_path.replace("\\", "/")
|
1870
1950
|
star_len = len("Dashboard: ") + len(dash_url)
|
1871
|
-
|
1951
|
+
with suppress(Exception):
|
1872
1952
|
terminal_size = os.get_terminal_size().columns
|
1873
1953
|
if terminal_size > 30 and star_len > terminal_size:
|
1874
1954
|
star_len = terminal_size
|
1875
|
-
except Exception:
|
1876
|
-
pass
|
1877
1955
|
stars = "*" * star_len
|
1878
1956
|
c1 = ""
|
1879
1957
|
cr = ""
|
1880
1958
|
if "linux" not in sys.platform:
|
1881
|
-
if is_windows and hasattr(colorama, "just_fix_windows_console"):
|
1882
|
-
colorama.just_fix_windows_console()
|
1883
|
-
else:
|
1884
|
-
colorama.init(autoreset=True)
|
1885
1959
|
c1 = colorama.Fore.BLUE + colorama.Back.LIGHTCYAN_EX
|
1886
1960
|
cr = colorama.Style.RESET_ALL
|
1887
1961
|
if sb_config._multithreaded:
|
@@ -1915,11 +1989,11 @@ def pytest_runtest_teardown(item):
|
|
1915
1989
|
(Has zero effect on tests using --reuse-session / --rs)"""
|
1916
1990
|
if "--co" in sys_argv or "--collect-only" in sys_argv:
|
1917
1991
|
return
|
1918
|
-
|
1992
|
+
with suppress(Exception):
|
1919
1993
|
if hasattr(item, "_testcase") or hasattr(sb_config, "_sb_pdb_driver"):
|
1920
1994
|
if hasattr(item, "_testcase"):
|
1921
1995
|
self = item._testcase
|
1922
|
-
|
1996
|
+
with suppress(Exception):
|
1923
1997
|
if (
|
1924
1998
|
hasattr(self, "driver")
|
1925
1999
|
and self.driver
|
@@ -1927,22 +2001,18 @@ def pytest_runtest_teardown(item):
|
|
1927
2001
|
):
|
1928
2002
|
if not (is_windows or self.driver.service.process):
|
1929
2003
|
self.driver.quit()
|
1930
|
-
except Exception:
|
1931
|
-
pass
|
1932
2004
|
elif (
|
1933
2005
|
hasattr(sb_config, "_sb_pdb_driver")
|
1934
2006
|
and sb_config._sb_pdb_driver
|
1935
2007
|
):
|
1936
|
-
|
2008
|
+
with suppress(Exception):
|
1937
2009
|
if (
|
1938
2010
|
not is_windows
|
1939
2011
|
or sb_config._sb_pdb_driver.service.process
|
1940
2012
|
):
|
1941
2013
|
sb_config._sb_pdb_driver.quit()
|
1942
2014
|
sb_config._sb_pdb_driver = None
|
1943
|
-
|
1944
|
-
pass
|
1945
|
-
try:
|
2015
|
+
with suppress(Exception):
|
1946
2016
|
if (
|
1947
2017
|
hasattr(self, "_xvfb_display")
|
1948
2018
|
and self._xvfb_display
|
@@ -1959,10 +2029,6 @@ def pytest_runtest_teardown(item):
|
|
1959
2029
|
):
|
1960
2030
|
sb_config._virtual_display.stop()
|
1961
2031
|
sb_config._virtual_display = None
|
1962
|
-
except Exception:
|
1963
|
-
pass
|
1964
|
-
except Exception:
|
1965
|
-
pass
|
1966
2032
|
if (
|
1967
2033
|
(
|
1968
2034
|
sb_config._has_exception
|
@@ -1975,6 +2041,7 @@ def pytest_runtest_teardown(item):
|
|
1975
2041
|
if (
|
1976
2042
|
"-s" in sys_argv
|
1977
2043
|
or "--capture=no" in sys_argv
|
2044
|
+
or "--capture=tee-sys" in sys_argv
|
1978
2045
|
or (
|
1979
2046
|
hasattr(sb_config.pytest_config, "invocation_params")
|
1980
2047
|
and (
|
@@ -1982,6 +2049,9 @@ def pytest_runtest_teardown(item):
|
|
1982
2049
|
or "--capture=no" in (
|
1983
2050
|
sb_config.pytest_config.invocation_params.args
|
1984
2051
|
)
|
2052
|
+
or "--capture=tee-sys" in (
|
2053
|
+
sb_config.pytest_config.invocation_params.args
|
2054
|
+
)
|
1985
2055
|
)
|
1986
2056
|
)
|
1987
2057
|
):
|
@@ -1990,6 +2060,10 @@ def pytest_runtest_teardown(item):
|
|
1990
2060
|
sys.stdout.write("\n=> Fail Page: %s\n" % sb_config._fail_page)
|
1991
2061
|
|
1992
2062
|
|
2063
|
+
def pytest_html_duration_format(duration):
|
2064
|
+
return "%.2f" % duration
|
2065
|
+
|
2066
|
+
|
1993
2067
|
def pytest_sessionfinish(session):
|
1994
2068
|
pass
|
1995
2069
|
|
@@ -2040,9 +2114,11 @@ def pytest_terminal_summary(terminalreporter):
|
|
2040
2114
|
)
|
2041
2115
|
|
2042
2116
|
|
2043
|
-
def _perform_pytest_unconfigure_():
|
2117
|
+
def _perform_pytest_unconfigure_(config):
|
2044
2118
|
from seleniumbase.core import proxy_helper
|
2045
2119
|
|
2120
|
+
reporter = config.pluginmanager.get_plugin("terminalreporter")
|
2121
|
+
duration = time.time() - reporter._sessionstarttime
|
2046
2122
|
if (
|
2047
2123
|
(hasattr(sb_config, "multi_proxy") and not sb_config.multi_proxy)
|
2048
2124
|
or not hasattr(sb_config, "multi_proxy")
|
@@ -2067,9 +2143,95 @@ def _perform_pytest_unconfigure_():
|
|
2067
2143
|
log_helper.archive_logs_if_set(
|
2068
2144
|
constants.Logs.LATEST + "/", sb_config.archive_logs
|
2069
2145
|
)
|
2146
|
+
if os.path.exists("./assets/"): # Used by pytest-html reports
|
2147
|
+
with suppress(Exception):
|
2148
|
+
shared_utils.make_dir_files_writable("./assets/")
|
2070
2149
|
log_helper.clear_empty_logs()
|
2071
2150
|
# Dashboard post-processing: Disable time-based refresh and stamp complete
|
2072
2151
|
if not hasattr(sb_config, "dashboard") or not sb_config.dashboard:
|
2152
|
+
html_report_path = None
|
2153
|
+
the_html_r = None
|
2154
|
+
abs_path = os.path.abspath(".")
|
2155
|
+
if sb_config._html_report_name:
|
2156
|
+
html_report_path = os.path.join(
|
2157
|
+
abs_path, sb_config._html_report_name
|
2158
|
+
)
|
2159
|
+
if sb_config._html_report_copy:
|
2160
|
+
html_report_path_copy = os.path.join(
|
2161
|
+
abs_path, sb_config._html_report_copy
|
2162
|
+
)
|
2163
|
+
if (
|
2164
|
+
sb_config._using_html_report
|
2165
|
+
and html_report_path
|
2166
|
+
and os.path.exists(html_report_path)
|
2167
|
+
):
|
2168
|
+
with open(html_report_path, "r", encoding="utf-8") as f:
|
2169
|
+
the_html_r = f.read()
|
2170
|
+
assets_chunk = "if (assets.length === 1) {"
|
2171
|
+
remove_media = "container.classList.remove('media-container')"
|
2172
|
+
rm_n_left = '<div class="media-container__nav--left"><</div>'
|
2173
|
+
rm_n_right = '<div class="media-container__nav--right">></div>'
|
2174
|
+
the_html_r = the_html_r.replace(
|
2175
|
+
assets_chunk,
|
2176
|
+
"%s %s" % (assets_chunk, remove_media),
|
2177
|
+
)
|
2178
|
+
the_html_r = the_html_r.replace(rm_n_left, "")
|
2179
|
+
the_html_r = the_html_r.replace(rm_n_right, "")
|
2180
|
+
the_html_r = the_html_r.replace("<ul>$", "$")
|
2181
|
+
the_html_r = the_html_r.replace("}<ul>", "}")
|
2182
|
+
the_html_r = the_html_r.replace(
|
2183
|
+
"<li>${val}</li>", "${val}, "
|
2184
|
+
)
|
2185
|
+
the_html_r = the_html_r.replace(
|
2186
|
+
"<div>${value}</div>", "<span>${value}</span"
|
2187
|
+
)
|
2188
|
+
ph_link = '<a href="https://pypi.python.org/pypi/pytest-html">'
|
2189
|
+
sb_link = (
|
2190
|
+
'<a href="https://github.com/seleniumbase/SeleniumBase">'
|
2191
|
+
'SeleniumBase</a>'
|
2192
|
+
)
|
2193
|
+
the_html_r = the_html_r.replace(
|
2194
|
+
ph_link, "%s and %s" % (sb_link, ph_link)
|
2195
|
+
)
|
2196
|
+
the_html_r = the_html_r.replace(
|
2197
|
+
"mediaName.innerText", "//mediaName.innerText"
|
2198
|
+
)
|
2199
|
+
the_html_r = the_html_r.replace(
|
2200
|
+
"counter.innerText", "//counter.innerText"
|
2201
|
+
)
|
2202
|
+
run_count = '<p class="run-count">'
|
2203
|
+
run_c_loc = the_html_r.find(run_count)
|
2204
|
+
rc_loc = the_html_r.find(" took ", run_c_loc)
|
2205
|
+
end_rc_loc = the_html_r.find(".</p>", rc_loc)
|
2206
|
+
run_time = "%.2f" % duration
|
2207
|
+
new_time = " ran in %s seconds" % run_time
|
2208
|
+
the_html_r = (
|
2209
|
+
the_html_r[:rc_loc] + new_time + the_html_r[end_rc_loc:]
|
2210
|
+
)
|
2211
|
+
with open(html_report_path, "w", encoding="utf-8") as f:
|
2212
|
+
f.write(the_html_r) # Finalize the HTML report
|
2213
|
+
with suppress(Exception):
|
2214
|
+
shared_utils.make_writable(html_report_path)
|
2215
|
+
with open(html_report_path_copy, "w", encoding="utf-8") as f:
|
2216
|
+
f.write(the_html_r) # Finalize the HTML report copy
|
2217
|
+
with suppress(Exception):
|
2218
|
+
shared_utils.make_writable(html_report_path_copy)
|
2219
|
+
assets_style = "./assets/style.css"
|
2220
|
+
if os.path.exists(assets_style):
|
2221
|
+
html_style = None
|
2222
|
+
with open(assets_style, "r", encoding="utf-8") as f:
|
2223
|
+
html_style = f.read()
|
2224
|
+
if html_style:
|
2225
|
+
html_style = html_style.replace("top: -50px;", "top: 2px;")
|
2226
|
+
html_style = html_style.replace("+ 50px)", "+ 40px)")
|
2227
|
+
html_style = html_style.replace("ht: 240px;", "ht: 228px;")
|
2228
|
+
html_style = html_style.replace(
|
2229
|
+
"- 80px);", "- 80px);\n margin-bottom: -42px;"
|
2230
|
+
)
|
2231
|
+
with open(assets_style, "w", encoding="utf-8") as f:
|
2232
|
+
f.write(html_style)
|
2233
|
+
with suppress(Exception):
|
2234
|
+
shared_utils.make_writable(assets_style)
|
2073
2235
|
# Done with "pytest_unconfigure" unless using the Dashboard
|
2074
2236
|
return
|
2075
2237
|
stamp = ""
|
@@ -2151,12 +2313,34 @@ def _perform_pytest_unconfigure_():
|
|
2151
2313
|
)
|
2152
2314
|
with open(dashboard_path, "w", encoding="utf-8") as f:
|
2153
2315
|
f.write(the_html_d) # Finalize the dashboard
|
2316
|
+
with suppress(Exception):
|
2317
|
+
shared_utils.make_writable(dashboard_path)
|
2318
|
+
assets_style = "./assets/style.css"
|
2319
|
+
if os.path.exists(assets_style):
|
2320
|
+
html_style = None
|
2321
|
+
with open(assets_style, "r", encoding="utf-8") as f:
|
2322
|
+
html_style = f.read()
|
2323
|
+
if html_style:
|
2324
|
+
html_style = html_style.replace("top: -50px;", "top: 2px;")
|
2325
|
+
html_style = html_style.replace("+ 50px)", "+ 40px)")
|
2326
|
+
html_style = html_style.replace("ht: 240px;", "ht: 228px;")
|
2327
|
+
html_style = html_style.replace(
|
2328
|
+
"- 80px);", "- 80px);\n margin-bottom: -42px;"
|
2329
|
+
)
|
2330
|
+
with open(assets_style, "w", encoding="utf-8") as f:
|
2331
|
+
f.write(html_style)
|
2332
|
+
with suppress(Exception):
|
2333
|
+
shared_utils.make_writable(assets_style)
|
2154
2334
|
# Part 2: Appending a pytest html report with dashboard data
|
2155
2335
|
html_report_path = None
|
2156
2336
|
if sb_config._html_report_name:
|
2157
2337
|
html_report_path = os.path.join(
|
2158
2338
|
abs_path, sb_config._html_report_name
|
2159
2339
|
)
|
2340
|
+
if sb_config._html_report_copy:
|
2341
|
+
html_report_path_copy = os.path.join(
|
2342
|
+
abs_path, sb_config._html_report_copy
|
2343
|
+
)
|
2160
2344
|
if (
|
2161
2345
|
sb_config._using_html_report
|
2162
2346
|
and html_report_path
|
@@ -2174,7 +2358,7 @@ def _perform_pytest_unconfigure_():
|
|
2174
2358
|
elif "\\" in h_r_name and h_r_name.endswith(".html"):
|
2175
2359
|
h_r_name = h_r_name.split("\\")[-1]
|
2176
2360
|
the_html_r = the_html_r.replace(
|
2177
|
-
|
2361
|
+
'<h1 id="title">%s</h1>' % h_r_name,
|
2178
2362
|
sb_config._saved_dashboard_pie,
|
2179
2363
|
)
|
2180
2364
|
the_html_r = the_html_r.replace(
|
@@ -2184,8 +2368,55 @@ def _perform_pytest_unconfigure_():
|
|
2184
2368
|
)
|
2185
2369
|
if sb_config._dash_final_summary:
|
2186
2370
|
the_html_r += sb_config._dash_final_summary
|
2371
|
+
assets_chunk = "if (assets.length === 1) {"
|
2372
|
+
remove_media = "container.classList.remove('media-container')"
|
2373
|
+
rm_n_left = '<div class="media-container__nav--left"><</div>'
|
2374
|
+
rm_n_right = '<div class="media-container__nav--right">></div>'
|
2375
|
+
the_html_r = the_html_r.replace(
|
2376
|
+
assets_chunk,
|
2377
|
+
"%s %s" % (assets_chunk, remove_media),
|
2378
|
+
)
|
2379
|
+
the_html_r = the_html_r.replace(rm_n_left, "")
|
2380
|
+
the_html_r = the_html_r.replace(rm_n_right, "")
|
2381
|
+
the_html_r = the_html_r.replace("<ul>$", "$")
|
2382
|
+
the_html_r = the_html_r.replace("}<ul>", "}")
|
2383
|
+
the_html_r = the_html_r.replace(
|
2384
|
+
"<li>${val}</li>", "${val}, "
|
2385
|
+
)
|
2386
|
+
the_html_r = the_html_r.replace(
|
2387
|
+
"<div>${value}</div>", "<span>${value}</span"
|
2388
|
+
)
|
2389
|
+
ph_link = '<a href="https://pypi.python.org/pypi/pytest-html">'
|
2390
|
+
sb_link = (
|
2391
|
+
'<a href="https://github.com/seleniumbase/SeleniumBase">'
|
2392
|
+
'SeleniumBase</a>'
|
2393
|
+
)
|
2394
|
+
the_html_r = the_html_r.replace(
|
2395
|
+
ph_link, "%s and %s" % (sb_link, ph_link)
|
2396
|
+
)
|
2397
|
+
the_html_r = the_html_r.replace(
|
2398
|
+
"mediaName.innerText", "//mediaName.innerText"
|
2399
|
+
)
|
2400
|
+
the_html_r = the_html_r.replace(
|
2401
|
+
"counter.innerText", "//counter.innerText"
|
2402
|
+
)
|
2403
|
+
run_count = '<p class="run-count">'
|
2404
|
+
run_c_loc = the_html_r.find(run_count)
|
2405
|
+
rc_loc = the_html_r.find(" took ", run_c_loc)
|
2406
|
+
end_rc_loc = the_html_r.find(".</p>", rc_loc)
|
2407
|
+
run_time = "%.2f" % duration
|
2408
|
+
new_time = " ran in %s seconds" % run_time
|
2409
|
+
the_html_r = (
|
2410
|
+
the_html_r[:rc_loc] + new_time + the_html_r[end_rc_loc:]
|
2411
|
+
)
|
2187
2412
|
with open(html_report_path, "w", encoding="utf-8") as f:
|
2188
2413
|
f.write(the_html_r) # Finalize the HTML report
|
2414
|
+
with suppress(Exception):
|
2415
|
+
shared_utils.make_writable(html_report_path)
|
2416
|
+
with open(html_report_path_copy, "w", encoding="utf-8") as f:
|
2417
|
+
f.write(the_html_r) # Finalize the HTML report copy
|
2418
|
+
with suppress(Exception):
|
2419
|
+
shared_utils.make_writable(html_report_path_copy)
|
2189
2420
|
except KeyboardInterrupt:
|
2190
2421
|
pass
|
2191
2422
|
except Exception:
|
@@ -2218,19 +2449,19 @@ def pytest_unconfigure(config):
|
|
2218
2449
|
with open(dashboard_path, "w", encoding="utf-8") as f:
|
2219
2450
|
f.write(sb_config._dash_html)
|
2220
2451
|
# Dashboard Multithreaded
|
2221
|
-
_perform_pytest_unconfigure_()
|
2452
|
+
_perform_pytest_unconfigure_(config)
|
2222
2453
|
return
|
2223
2454
|
else:
|
2224
2455
|
# Dash Lock is missing
|
2225
|
-
_perform_pytest_unconfigure_()
|
2456
|
+
_perform_pytest_unconfigure_(config)
|
2226
2457
|
return
|
2227
2458
|
with dash_lock:
|
2228
2459
|
# Multi-threaded tests
|
2229
|
-
_perform_pytest_unconfigure_()
|
2460
|
+
_perform_pytest_unconfigure_(config)
|
2230
2461
|
return
|
2231
2462
|
else:
|
2232
2463
|
# Single-threaded tests
|
2233
|
-
_perform_pytest_unconfigure_()
|
2464
|
+
_perform_pytest_unconfigure_(config)
|
2234
2465
|
return
|
2235
2466
|
|
2236
2467
|
|
@@ -2343,7 +2574,7 @@ def pytest_runtest_makereport(item, call):
|
|
2343
2574
|
)
|
2344
2575
|
if log_path:
|
2345
2576
|
sb_config._log_fail_data()
|
2346
|
-
|
2577
|
+
with suppress(Exception):
|
2347
2578
|
extra_report = None
|
2348
2579
|
if hasattr(item, "_testcase"):
|
2349
2580
|
extra_report = item._testcase._html_report_extra
|
@@ -2379,7 +2610,7 @@ def pytest_runtest_makereport(item, call):
|
|
2379
2610
|
return
|
2380
2611
|
extra = getattr(report, "extra", [])
|
2381
2612
|
if len(extra_report) > 1 and extra_report[1]["content"]:
|
2382
|
-
report.
|
2613
|
+
report.extras = extra + extra_report
|
2383
2614
|
if sb_config._dash_is_html_report:
|
2384
2615
|
# If the Dashboard URL is the same as the HTML Report URL,
|
2385
2616
|
# have the html report refresh back to a dashboard on update.
|
@@ -2387,6 +2618,4 @@ def pytest_runtest_makereport(item, call):
|
|
2387
2618
|
'<script type="text/javascript" src="%s">'
|
2388
2619
|
"</script>" % constants.Dashboard.LIVE_JS
|
2389
2620
|
)
|
2390
|
-
report.
|
2391
|
-
except Exception:
|
2392
|
-
pass
|
2621
|
+
report.extras.append(pytest_html.extras.html(refresh_updates))
|