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
@@ -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))
|