seleniumbase 4.33.3__py3-none-any.whl → 4.33.5__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/console_scripts/sb_mkdir.py +2 -1
- seleniumbase/core/browser_launcher.py +78 -53
- seleniumbase/fixtures/base_case.py +88 -69
- seleniumbase/plugins/pytest_plugin.py +131 -8
- {seleniumbase-4.33.3.dist-info → seleniumbase-4.33.5.dist-info}/METADATA +3 -4
- {seleniumbase-4.33.3.dist-info → seleniumbase-4.33.5.dist-info}/RECORD +11 -11
- {seleniumbase-4.33.3.dist-info → seleniumbase-4.33.5.dist-info}/LICENSE +0 -0
- {seleniumbase-4.33.3.dist-info → seleniumbase-4.33.5.dist-info}/WHEEL +0 -0
- {seleniumbase-4.33.3.dist-info → seleniumbase-4.33.5.dist-info}/entry_points.txt +0 -0
- {seleniumbase-4.33.3.dist-info → seleniumbase-4.33.5.dist-info}/top_level.txt +0 -0
seleniumbase/__version__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
# seleniumbase package
|
2
|
-
__version__ = "4.33.
|
2
|
+
__version__ = "4.33.5"
|
@@ -120,7 +120,7 @@ def main():
|
|
120
120
|
|
121
121
|
data = []
|
122
122
|
data.append("[pytest]")
|
123
|
-
data.append("addopts = --capture=
|
123
|
+
data.append("addopts = --capture=tee-sys -p no:cacheprovider")
|
124
124
|
data.append("norecursedirs = .* build dist recordings temp assets")
|
125
125
|
data.append("filterwarnings =")
|
126
126
|
data.append(" ignore::pytest.PytestWarning")
|
@@ -259,6 +259,7 @@ def main():
|
|
259
259
|
data.append("report_archives")
|
260
260
|
data.append("archived_reports")
|
261
261
|
data.append("html_report.html")
|
262
|
+
data.append("last_report.html")
|
262
263
|
data.append("report.html")
|
263
264
|
data.append("report.xml")
|
264
265
|
data.append("dashboard.html")
|
@@ -97,6 +97,13 @@ def log_d(message):
|
|
97
97
|
print(message)
|
98
98
|
|
99
99
|
|
100
|
+
def make_writable(file_path):
|
101
|
+
# Set permissions to: "If you can read it, you can write it."
|
102
|
+
mode = os.stat(file_path).st_mode
|
103
|
+
mode |= (mode & 0o444) >> 1 # copy R bits to W
|
104
|
+
os.chmod(file_path, mode)
|
105
|
+
|
106
|
+
|
100
107
|
def make_executable(file_path):
|
101
108
|
# Set permissions to: "If you can read it, you can execute it."
|
102
109
|
mode = os.stat(file_path).st_mode
|
@@ -810,66 +817,84 @@ def verify_pyautogui_has_a_headed_browser(driver):
|
|
810
817
|
)
|
811
818
|
|
812
819
|
|
820
|
+
def __install_pyautogui_if_missing():
|
821
|
+
try:
|
822
|
+
import pyautogui
|
823
|
+
with suppress(Exception):
|
824
|
+
use_pyautogui_ver = constants.PyAutoGUI.VER
|
825
|
+
if pyautogui.__version__ != use_pyautogui_ver:
|
826
|
+
del pyautogui
|
827
|
+
shared_utils.pip_install(
|
828
|
+
"pyautogui", version=use_pyautogui_ver
|
829
|
+
)
|
830
|
+
import pyautogui
|
831
|
+
except Exception:
|
832
|
+
print("\nPyAutoGUI required! Installing now...")
|
833
|
+
shared_utils.pip_install(
|
834
|
+
"pyautogui", version=constants.PyAutoGUI.VER
|
835
|
+
)
|
836
|
+
try:
|
837
|
+
import pyautogui
|
838
|
+
except Exception:
|
839
|
+
if (
|
840
|
+
IS_LINUX
|
841
|
+
and hasattr(sb_config, "xvfb")
|
842
|
+
and hasattr(sb_config, "headed")
|
843
|
+
and hasattr(sb_config, "headless")
|
844
|
+
and hasattr(sb_config, "headless2")
|
845
|
+
and (not sb_config.headed or sb_config.xvfb)
|
846
|
+
and not (sb_config.headless or sb_config.headless2)
|
847
|
+
):
|
848
|
+
from sbvirtualdisplay import Display
|
849
|
+
xvfb_width = 1366
|
850
|
+
xvfb_height = 768
|
851
|
+
if (
|
852
|
+
hasattr(sb_config, "_xvfb_width")
|
853
|
+
and sb_config._xvfb_width
|
854
|
+
and isinstance(sb_config._xvfb_width, int)
|
855
|
+
and hasattr(sb_config, "_xvfb_height")
|
856
|
+
and sb_config._xvfb_height
|
857
|
+
and isinstance(sb_config._xvfb_height, int)
|
858
|
+
):
|
859
|
+
xvfb_width = sb_config._xvfb_width
|
860
|
+
xvfb_height = sb_config._xvfb_height
|
861
|
+
if xvfb_width < 1024:
|
862
|
+
xvfb_width = 1024
|
863
|
+
sb_config._xvfb_width = xvfb_width
|
864
|
+
if xvfb_height < 768:
|
865
|
+
xvfb_height = 768
|
866
|
+
sb_config._xvfb_height = xvfb_height
|
867
|
+
with suppress(Exception):
|
868
|
+
xvfb_display = Display(
|
869
|
+
visible=True,
|
870
|
+
size=(xvfb_width, xvfb_height),
|
871
|
+
backend="xvfb",
|
872
|
+
use_xauth=True,
|
873
|
+
)
|
874
|
+
xvfb_display.start()
|
875
|
+
|
876
|
+
|
813
877
|
def install_pyautogui_if_missing(driver):
|
814
878
|
verify_pyautogui_has_a_headed_browser(driver)
|
815
879
|
pip_find_lock = fasteners.InterProcessLock(
|
816
880
|
constants.PipInstall.FINDLOCK
|
817
881
|
)
|
818
|
-
|
882
|
+
try:
|
883
|
+
with pip_find_lock:
|
884
|
+
pass
|
885
|
+
except Exception:
|
886
|
+
# Need write permissions
|
887
|
+
with suppress(Exception):
|
888
|
+
make_writable(constants.PipInstall.FINDLOCK)
|
819
889
|
try:
|
820
|
-
|
821
|
-
|
822
|
-
use_pyautogui_ver = constants.PyAutoGUI.VER
|
823
|
-
if pyautogui.__version__ != use_pyautogui_ver:
|
824
|
-
del pyautogui
|
825
|
-
shared_utils.pip_install(
|
826
|
-
"pyautogui", version=use_pyautogui_ver
|
827
|
-
)
|
828
|
-
import pyautogui
|
890
|
+
with pip_find_lock:
|
891
|
+
pass
|
829
892
|
except Exception:
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
import pyautogui
|
836
|
-
except Exception:
|
837
|
-
if (
|
838
|
-
IS_LINUX
|
839
|
-
and hasattr(sb_config, "xvfb")
|
840
|
-
and hasattr(sb_config, "headed")
|
841
|
-
and hasattr(sb_config, "headless")
|
842
|
-
and hasattr(sb_config, "headless2")
|
843
|
-
and (not sb_config.headed or sb_config.xvfb)
|
844
|
-
and not (sb_config.headless or sb_config.headless2)
|
845
|
-
):
|
846
|
-
from sbvirtualdisplay import Display
|
847
|
-
xvfb_width = 1366
|
848
|
-
xvfb_height = 768
|
849
|
-
if (
|
850
|
-
hasattr(sb_config, "_xvfb_width")
|
851
|
-
and sb_config._xvfb_width
|
852
|
-
and isinstance(sb_config._xvfb_width, int)
|
853
|
-
and hasattr(sb_config, "_xvfb_height")
|
854
|
-
and sb_config._xvfb_height
|
855
|
-
and isinstance(sb_config._xvfb_height, int)
|
856
|
-
):
|
857
|
-
xvfb_width = sb_config._xvfb_width
|
858
|
-
xvfb_height = sb_config._xvfb_height
|
859
|
-
if xvfb_width < 1024:
|
860
|
-
xvfb_width = 1024
|
861
|
-
sb_config._xvfb_width = xvfb_width
|
862
|
-
if xvfb_height < 768:
|
863
|
-
xvfb_height = 768
|
864
|
-
sb_config._xvfb_height = xvfb_height
|
865
|
-
with suppress(Exception):
|
866
|
-
xvfb_display = Display(
|
867
|
-
visible=True,
|
868
|
-
size=(xvfb_width, xvfb_height),
|
869
|
-
backend="xvfb",
|
870
|
-
use_xauth=True,
|
871
|
-
)
|
872
|
-
xvfb_display.start()
|
893
|
+
# Since missing permissions, skip the locks
|
894
|
+
__install_pyautogui_if_missing()
|
895
|
+
return
|
896
|
+
with pip_find_lock: # Prevent issues with multiple processes
|
897
|
+
__install_pyautogui_if_missing()
|
873
898
|
|
874
899
|
|
875
900
|
def get_configured_pyautogui(pyautogui_copy):
|
@@ -13974,84 +13974,103 @@ class BaseCase(unittest.TestCase):
|
|
13974
13974
|
self.headless_active = True
|
13975
13975
|
sb_config.headless_active = True
|
13976
13976
|
|
13977
|
+
def __activate_virtual_display(self):
|
13978
|
+
if self.undetectable and not (self.headless or self.headless2):
|
13979
|
+
from sbvirtualdisplay import Display
|
13980
|
+
import Xlib.display
|
13981
|
+
try:
|
13982
|
+
if not self._xvfb_width:
|
13983
|
+
self._xvfb_width = 1366
|
13984
|
+
if not self._xvfb_height:
|
13985
|
+
self._xvfb_height = 768
|
13986
|
+
self._xvfb_display = Display(
|
13987
|
+
visible=True,
|
13988
|
+
size=(self._xvfb_width, self._xvfb_height),
|
13989
|
+
backend="xvfb",
|
13990
|
+
use_xauth=True,
|
13991
|
+
)
|
13992
|
+
self._xvfb_display.start()
|
13993
|
+
if "DISPLAY" not in os.environ.keys():
|
13994
|
+
print(
|
13995
|
+
"\nX11 display failed! Will use regular xvfb!"
|
13996
|
+
)
|
13997
|
+
self.__activate_standard_virtual_display()
|
13998
|
+
except Exception as e:
|
13999
|
+
if hasattr(e, "msg"):
|
14000
|
+
print("\n" + str(e.msg))
|
14001
|
+
else:
|
14002
|
+
print(e)
|
14003
|
+
print("\nX11 display failed! Will use regular xvfb!")
|
14004
|
+
self.__activate_standard_virtual_display()
|
14005
|
+
return
|
14006
|
+
pyautogui_is_installed = False
|
14007
|
+
try:
|
14008
|
+
import pyautogui
|
14009
|
+
with suppress(Exception):
|
14010
|
+
use_pyautogui_ver = constants.PyAutoGUI.VER
|
14011
|
+
if pyautogui.__version__ != use_pyautogui_ver:
|
14012
|
+
del pyautogui # To get newer ver
|
14013
|
+
shared_utils.pip_install(
|
14014
|
+
"pyautogui", version=use_pyautogui_ver
|
14015
|
+
)
|
14016
|
+
import pyautogui
|
14017
|
+
pyautogui_is_installed = True
|
14018
|
+
except Exception:
|
14019
|
+
message = (
|
14020
|
+
"PyAutoGUI is required for UC Mode on Linux! "
|
14021
|
+
"Installing now..."
|
14022
|
+
)
|
14023
|
+
print("\n" + message)
|
14024
|
+
shared_utils.pip_install(
|
14025
|
+
"pyautogui", version=constants.PyAutoGUI.VER
|
14026
|
+
)
|
14027
|
+
import pyautogui
|
14028
|
+
pyautogui_is_installed = True
|
14029
|
+
if (
|
14030
|
+
pyautogui_is_installed
|
14031
|
+
and hasattr(pyautogui, "_pyautogui_x11")
|
14032
|
+
):
|
14033
|
+
try:
|
14034
|
+
pyautogui._pyautogui_x11._display = (
|
14035
|
+
Xlib.display.Display(os.environ['DISPLAY'])
|
14036
|
+
)
|
14037
|
+
sb_config._pyautogui_x11_display = (
|
14038
|
+
pyautogui._pyautogui_x11._display
|
14039
|
+
)
|
14040
|
+
except Exception as e:
|
14041
|
+
if hasattr(e, "msg"):
|
14042
|
+
print("\n" + str(e.msg))
|
14043
|
+
else:
|
14044
|
+
print(e)
|
14045
|
+
else:
|
14046
|
+
self.__activate_standard_virtual_display()
|
14047
|
+
|
13977
14048
|
def __activate_virtual_display_as_needed(self):
|
13978
14049
|
"""This is only needed on Linux.
|
13979
14050
|
The "--xvfb" arg is still useful, as it prevents headless mode,
|
13980
14051
|
which is the default mode on Linux unless using another arg."""
|
13981
14052
|
if "linux" in sys.platform and (not self.headed or self.xvfb):
|
13982
|
-
from sbvirtualdisplay import Display
|
13983
14053
|
pip_find_lock = fasteners.InterProcessLock(
|
13984
14054
|
constants.PipInstall.FINDLOCK
|
13985
14055
|
)
|
14056
|
+
try:
|
14057
|
+
with pip_find_lock:
|
14058
|
+
pass
|
14059
|
+
except Exception:
|
14060
|
+
# Need write permissions
|
14061
|
+
with suppress(Exception):
|
14062
|
+
mode = os.stat(constants.PipInstall.FINDLOCK).st_mode
|
14063
|
+
mode |= (mode & 0o444) >> 1 # copy R bits to W
|
14064
|
+
os.chmod(constants.PipInstall.FINDLOCK, mode)
|
14065
|
+
try:
|
14066
|
+
with pip_find_lock:
|
14067
|
+
pass
|
14068
|
+
except Exception:
|
14069
|
+
# Since missing permissions, skip the locks
|
14070
|
+
self.__activate_virtual_display()
|
14071
|
+
return
|
13986
14072
|
with pip_find_lock: # Prevent issues with multiple processes
|
13987
|
-
|
13988
|
-
import Xlib.display
|
13989
|
-
try:
|
13990
|
-
if not self._xvfb_width:
|
13991
|
-
self._xvfb_width = 1366
|
13992
|
-
if not self._xvfb_height:
|
13993
|
-
self._xvfb_height = 768
|
13994
|
-
self._xvfb_display = Display(
|
13995
|
-
visible=True,
|
13996
|
-
size=(self._xvfb_width, self._xvfb_height),
|
13997
|
-
backend="xvfb",
|
13998
|
-
use_xauth=True,
|
13999
|
-
)
|
14000
|
-
self._xvfb_display.start()
|
14001
|
-
if "DISPLAY" not in os.environ.keys():
|
14002
|
-
print(
|
14003
|
-
"\nX11 display failed! Will use regular xvfb!"
|
14004
|
-
)
|
14005
|
-
self.__activate_standard_virtual_display()
|
14006
|
-
except Exception as e:
|
14007
|
-
if hasattr(e, "msg"):
|
14008
|
-
print("\n" + str(e.msg))
|
14009
|
-
else:
|
14010
|
-
print(e)
|
14011
|
-
print("\nX11 display failed! Will use regular xvfb!")
|
14012
|
-
self.__activate_standard_virtual_display()
|
14013
|
-
return
|
14014
|
-
pyautogui_is_installed = False
|
14015
|
-
try:
|
14016
|
-
import pyautogui
|
14017
|
-
with suppress(Exception):
|
14018
|
-
use_pyautogui_ver = constants.PyAutoGUI.VER
|
14019
|
-
if pyautogui.__version__ != use_pyautogui_ver:
|
14020
|
-
del pyautogui # To get newer ver
|
14021
|
-
shared_utils.pip_install(
|
14022
|
-
"pyautogui", version=use_pyautogui_ver
|
14023
|
-
)
|
14024
|
-
import pyautogui
|
14025
|
-
pyautogui_is_installed = True
|
14026
|
-
except Exception:
|
14027
|
-
message = (
|
14028
|
-
"PyAutoGUI is required for UC Mode on Linux! "
|
14029
|
-
"Installing now..."
|
14030
|
-
)
|
14031
|
-
print("\n" + message)
|
14032
|
-
shared_utils.pip_install(
|
14033
|
-
"pyautogui", version=constants.PyAutoGUI.VER
|
14034
|
-
)
|
14035
|
-
import pyautogui
|
14036
|
-
pyautogui_is_installed = True
|
14037
|
-
if (
|
14038
|
-
pyautogui_is_installed
|
14039
|
-
and hasattr(pyautogui, "_pyautogui_x11")
|
14040
|
-
):
|
14041
|
-
try:
|
14042
|
-
pyautogui._pyautogui_x11._display = (
|
14043
|
-
Xlib.display.Display(os.environ['DISPLAY'])
|
14044
|
-
)
|
14045
|
-
sb_config._pyautogui_x11_display = (
|
14046
|
-
pyautogui._pyautogui_x11._display
|
14047
|
-
)
|
14048
|
-
except Exception as e:
|
14049
|
-
if hasattr(e, "msg"):
|
14050
|
-
print("\n" + str(e.msg))
|
14051
|
-
else:
|
14052
|
-
print(e)
|
14053
|
-
else:
|
14054
|
-
self.__activate_standard_virtual_display()
|
14073
|
+
self.__activate_virtual_display()
|
14055
14074
|
|
14056
14075
|
def __ad_block_as_needed(self):
|
14057
14076
|
"""This is an internal method for handling ad-blocking.
|
@@ -17,6 +17,7 @@ if sys.version_info >= (3, 11):
|
|
17
17
|
python3_11_or_newer = True
|
18
18
|
py311_patch2 = constants.PatchPy311.PATCH
|
19
19
|
sys_argv = sys.argv
|
20
|
+
full_time = None
|
20
21
|
pytest_plugins = ["pytester"] # Adds the "testdir" fixture
|
21
22
|
|
22
23
|
|
@@ -1708,6 +1709,7 @@ def pytest_configure(config):
|
|
1708
1709
|
sb_config._saved_dashboard_pie = None # Copy of pie chart for html report
|
1709
1710
|
sb_config._dash_final_summary = None # Dash status to add to html report
|
1710
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
|
1711
1713
|
|
1712
1714
|
arg_join = " ".join(sys_argv)
|
1713
1715
|
if (
|
@@ -1741,6 +1743,7 @@ def pytest_configure(config):
|
|
1741
1743
|
if sb_config.dashboard:
|
1742
1744
|
if sb_config._html_report_name == "dashboard.html":
|
1743
1745
|
sb_config._dash_is_html_report = True
|
1746
|
+
sb_config._html_report_copy = "last_report.html"
|
1744
1747
|
|
1745
1748
|
# Recorder Mode does not support multi-threaded / multi-process runs.
|
1746
1749
|
if sb_config.recorder_mode and sb_config._multithreaded:
|
@@ -2038,6 +2041,7 @@ def pytest_runtest_teardown(item):
|
|
2038
2041
|
if (
|
2039
2042
|
"-s" in sys_argv
|
2040
2043
|
or "--capture=no" in sys_argv
|
2044
|
+
or "--capture=tee-sys" in sys_argv
|
2041
2045
|
or (
|
2042
2046
|
hasattr(sb_config.pytest_config, "invocation_params")
|
2043
2047
|
and (
|
@@ -2045,6 +2049,9 @@ def pytest_runtest_teardown(item):
|
|
2045
2049
|
or "--capture=no" in (
|
2046
2050
|
sb_config.pytest_config.invocation_params.args
|
2047
2051
|
)
|
2052
|
+
or "--capture=tee-sys" in (
|
2053
|
+
sb_config.pytest_config.invocation_params.args
|
2054
|
+
)
|
2048
2055
|
)
|
2049
2056
|
)
|
2050
2057
|
):
|
@@ -2053,6 +2060,10 @@ def pytest_runtest_teardown(item):
|
|
2053
2060
|
sys.stdout.write("\n=> Fail Page: %s\n" % sb_config._fail_page)
|
2054
2061
|
|
2055
2062
|
|
2063
|
+
def pytest_html_duration_format(duration):
|
2064
|
+
return "%.2f" % duration
|
2065
|
+
|
2066
|
+
|
2056
2067
|
def pytest_sessionfinish(session):
|
2057
2068
|
pass
|
2058
2069
|
|
@@ -2103,9 +2114,11 @@ def pytest_terminal_summary(terminalreporter):
|
|
2103
2114
|
)
|
2104
2115
|
|
2105
2116
|
|
2106
|
-
def _perform_pytest_unconfigure_():
|
2117
|
+
def _perform_pytest_unconfigure_(config):
|
2107
2118
|
from seleniumbase.core import proxy_helper
|
2108
2119
|
|
2120
|
+
reporter = config.pluginmanager.get_plugin("terminalreporter")
|
2121
|
+
duration = time.time() - reporter._sessionstarttime
|
2109
2122
|
if (
|
2110
2123
|
(hasattr(sb_config, "multi_proxy") and not sb_config.multi_proxy)
|
2111
2124
|
or not hasattr(sb_config, "multi_proxy")
|
@@ -2133,6 +2146,69 @@ def _perform_pytest_unconfigure_():
|
|
2133
2146
|
log_helper.clear_empty_logs()
|
2134
2147
|
# Dashboard post-processing: Disable time-based refresh and stamp complete
|
2135
2148
|
if not hasattr(sb_config, "dashboard") or not sb_config.dashboard:
|
2149
|
+
html_report_path = None
|
2150
|
+
the_html_r = None
|
2151
|
+
abs_path = os.path.abspath(".")
|
2152
|
+
if sb_config._html_report_name:
|
2153
|
+
html_report_path = os.path.join(
|
2154
|
+
abs_path, sb_config._html_report_name
|
2155
|
+
)
|
2156
|
+
if sb_config._html_report_copy:
|
2157
|
+
html_report_path_copy = os.path.join(
|
2158
|
+
abs_path, sb_config._html_report_copy
|
2159
|
+
)
|
2160
|
+
if (
|
2161
|
+
sb_config._using_html_report
|
2162
|
+
and html_report_path
|
2163
|
+
and os.path.exists(html_report_path)
|
2164
|
+
):
|
2165
|
+
with open(html_report_path, "r", encoding="utf-8") as f:
|
2166
|
+
the_html_r = f.read()
|
2167
|
+
assets_chunk = "if (assets.length === 1) {"
|
2168
|
+
remove_media = "container.classList.remove('media-container')"
|
2169
|
+
rm_n_left = '<div class="media-container__nav--left"><</div>'
|
2170
|
+
rm_n_right = '<div class="media-container__nav--right">></div>'
|
2171
|
+
the_html_r = the_html_r.replace(
|
2172
|
+
assets_chunk,
|
2173
|
+
"%s %s" % (assets_chunk, remove_media),
|
2174
|
+
)
|
2175
|
+
the_html_r = the_html_r.replace(rm_n_left, "")
|
2176
|
+
the_html_r = the_html_r.replace(rm_n_right, "")
|
2177
|
+
the_html_r = the_html_r.replace("<ul>$", "$")
|
2178
|
+
the_html_r = the_html_r.replace("}<ul>", "}")
|
2179
|
+
the_html_r = the_html_r.replace(
|
2180
|
+
"<li>${val}</li>", "${val}, "
|
2181
|
+
)
|
2182
|
+
the_html_r = the_html_r.replace(
|
2183
|
+
"<div>${value}</div>", "<span>${value}</span"
|
2184
|
+
)
|
2185
|
+
ph_link = '<a href="https://pypi.python.org/pypi/pytest-html">'
|
2186
|
+
sb_link = (
|
2187
|
+
'<a href="https://github.com/seleniumbase/SeleniumBase">'
|
2188
|
+
'SeleniumBase</a>'
|
2189
|
+
)
|
2190
|
+
the_html_r = the_html_r.replace(
|
2191
|
+
ph_link, "%s and %s" % (sb_link, ph_link)
|
2192
|
+
)
|
2193
|
+
the_html_r = the_html_r.replace(
|
2194
|
+
"mediaName.innerText", "//mediaName.innerText"
|
2195
|
+
)
|
2196
|
+
the_html_r = the_html_r.replace(
|
2197
|
+
"counter.innerText", "//counter.innerText"
|
2198
|
+
)
|
2199
|
+
run_count = '<p class="run-count">'
|
2200
|
+
run_c_loc = the_html_r.find(run_count)
|
2201
|
+
rc_loc = the_html_r.find(" took ", run_c_loc)
|
2202
|
+
end_rc_loc = the_html_r.find(".</p>", rc_loc)
|
2203
|
+
run_time = "%.2f" % duration
|
2204
|
+
new_time = " ran in %s seconds" % run_time
|
2205
|
+
the_html_r = (
|
2206
|
+
the_html_r[:rc_loc] + new_time + the_html_r[end_rc_loc:]
|
2207
|
+
)
|
2208
|
+
with open(html_report_path, "w", encoding="utf-8") as f:
|
2209
|
+
f.write(the_html_r) # Finalize the HTML report
|
2210
|
+
with open(html_report_path_copy, "w", encoding="utf-8") as f:
|
2211
|
+
f.write(the_html_r) # Finalize the HTML report
|
2136
2212
|
# Done with "pytest_unconfigure" unless using the Dashboard
|
2137
2213
|
return
|
2138
2214
|
stamp = ""
|
@@ -2220,6 +2296,10 @@ def _perform_pytest_unconfigure_():
|
|
2220
2296
|
html_report_path = os.path.join(
|
2221
2297
|
abs_path, sb_config._html_report_name
|
2222
2298
|
)
|
2299
|
+
if sb_config._html_report_copy:
|
2300
|
+
html_report_path_copy = os.path.join(
|
2301
|
+
abs_path, sb_config._html_report_copy
|
2302
|
+
)
|
2223
2303
|
if (
|
2224
2304
|
sb_config._using_html_report
|
2225
2305
|
and html_report_path
|
@@ -2237,7 +2317,7 @@ def _perform_pytest_unconfigure_():
|
|
2237
2317
|
elif "\\" in h_r_name and h_r_name.endswith(".html"):
|
2238
2318
|
h_r_name = h_r_name.split("\\")[-1]
|
2239
2319
|
the_html_r = the_html_r.replace(
|
2240
|
-
|
2320
|
+
'<h1 id="title">%s</h1>' % h_r_name,
|
2241
2321
|
sb_config._saved_dashboard_pie,
|
2242
2322
|
)
|
2243
2323
|
the_html_r = the_html_r.replace(
|
@@ -2247,8 +2327,51 @@ def _perform_pytest_unconfigure_():
|
|
2247
2327
|
)
|
2248
2328
|
if sb_config._dash_final_summary:
|
2249
2329
|
the_html_r += sb_config._dash_final_summary
|
2330
|
+
assets_chunk = "if (assets.length === 1) {"
|
2331
|
+
remove_media = "container.classList.remove('media-container')"
|
2332
|
+
rm_n_left = '<div class="media-container__nav--left"><</div>'
|
2333
|
+
rm_n_right = '<div class="media-container__nav--right">></div>'
|
2334
|
+
the_html_r = the_html_r.replace(
|
2335
|
+
assets_chunk,
|
2336
|
+
"%s %s" % (assets_chunk, remove_media),
|
2337
|
+
)
|
2338
|
+
the_html_r = the_html_r.replace(rm_n_left, "")
|
2339
|
+
the_html_r = the_html_r.replace(rm_n_right, "")
|
2340
|
+
the_html_r = the_html_r.replace("<ul>$", "$")
|
2341
|
+
the_html_r = the_html_r.replace("}<ul>", "}")
|
2342
|
+
the_html_r = the_html_r.replace(
|
2343
|
+
"<li>${val}</li>", "${val}, "
|
2344
|
+
)
|
2345
|
+
the_html_r = the_html_r.replace(
|
2346
|
+
"<div>${value}</div>", "<span>${value}</span"
|
2347
|
+
)
|
2348
|
+
ph_link = '<a href="https://pypi.python.org/pypi/pytest-html">'
|
2349
|
+
sb_link = (
|
2350
|
+
'<a href="https://github.com/seleniumbase/SeleniumBase">'
|
2351
|
+
'SeleniumBase</a>'
|
2352
|
+
)
|
2353
|
+
the_html_r = the_html_r.replace(
|
2354
|
+
ph_link, "%s and %s" % (sb_link, ph_link)
|
2355
|
+
)
|
2356
|
+
the_html_r = the_html_r.replace(
|
2357
|
+
"mediaName.innerText", "//mediaName.innerText"
|
2358
|
+
)
|
2359
|
+
the_html_r = the_html_r.replace(
|
2360
|
+
"counter.innerText", "//counter.innerText"
|
2361
|
+
)
|
2362
|
+
run_count = '<p class="run-count">'
|
2363
|
+
run_c_loc = the_html_r.find(run_count)
|
2364
|
+
rc_loc = the_html_r.find(" took ", run_c_loc)
|
2365
|
+
end_rc_loc = the_html_r.find(".</p>", rc_loc)
|
2366
|
+
run_time = "%.2f" % duration
|
2367
|
+
new_time = " ran in %s seconds" % run_time
|
2368
|
+
the_html_r = (
|
2369
|
+
the_html_r[:rc_loc] + new_time + the_html_r[end_rc_loc:]
|
2370
|
+
)
|
2250
2371
|
with open(html_report_path, "w", encoding="utf-8") as f:
|
2251
2372
|
f.write(the_html_r) # Finalize the HTML report
|
2373
|
+
with open(html_report_path_copy, "w", encoding="utf-8") as f:
|
2374
|
+
f.write(the_html_r) # Finalize the HTML report
|
2252
2375
|
except KeyboardInterrupt:
|
2253
2376
|
pass
|
2254
2377
|
except Exception:
|
@@ -2281,19 +2404,19 @@ def pytest_unconfigure(config):
|
|
2281
2404
|
with open(dashboard_path, "w", encoding="utf-8") as f:
|
2282
2405
|
f.write(sb_config._dash_html)
|
2283
2406
|
# Dashboard Multithreaded
|
2284
|
-
_perform_pytest_unconfigure_()
|
2407
|
+
_perform_pytest_unconfigure_(config)
|
2285
2408
|
return
|
2286
2409
|
else:
|
2287
2410
|
# Dash Lock is missing
|
2288
|
-
_perform_pytest_unconfigure_()
|
2411
|
+
_perform_pytest_unconfigure_(config)
|
2289
2412
|
return
|
2290
2413
|
with dash_lock:
|
2291
2414
|
# Multi-threaded tests
|
2292
|
-
_perform_pytest_unconfigure_()
|
2415
|
+
_perform_pytest_unconfigure_(config)
|
2293
2416
|
return
|
2294
2417
|
else:
|
2295
2418
|
# Single-threaded tests
|
2296
|
-
_perform_pytest_unconfigure_()
|
2419
|
+
_perform_pytest_unconfigure_(config)
|
2297
2420
|
return
|
2298
2421
|
|
2299
2422
|
|
@@ -2442,7 +2565,7 @@ def pytest_runtest_makereport(item, call):
|
|
2442
2565
|
return
|
2443
2566
|
extra = getattr(report, "extra", [])
|
2444
2567
|
if len(extra_report) > 1 and extra_report[1]["content"]:
|
2445
|
-
report.
|
2568
|
+
report.extras = extra + extra_report
|
2446
2569
|
if sb_config._dash_is_html_report:
|
2447
2570
|
# If the Dashboard URL is the same as the HTML Report URL,
|
2448
2571
|
# have the html report refresh back to a dashboard on update.
|
@@ -2450,4 +2573,4 @@ def pytest_runtest_makereport(item, call):
|
|
2450
2573
|
'<script type="text/javascript" src="%s">'
|
2451
2574
|
"</script>" % constants.Dashboard.LIVE_JS
|
2452
2575
|
)
|
2453
|
-
report.
|
2576
|
+
report.extras.append(pytest_html.extras.html(refresh_updates))
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: seleniumbase
|
3
|
-
Version: 4.33.
|
3
|
+
Version: 4.33.5
|
4
4
|
Summary: A complete web automation framework for end-to-end testing.
|
5
5
|
Home-page: https://github.com/seleniumbase/SeleniumBase
|
6
6
|
Author: Michael Mintz
|
@@ -76,7 +76,7 @@ Requires-Dist: pynose>=1.5.3
|
|
76
76
|
Requires-Dist: platformdirs>=4.3.6
|
77
77
|
Requires-Dist: typing-extensions>=4.12.2
|
78
78
|
Requires-Dist: sbvirtualdisplay>=1.3.0
|
79
|
-
Requires-Dist: six>=1.
|
79
|
+
Requires-Dist: six>=1.17.0
|
80
80
|
Requires-Dist: parse>=1.20.2
|
81
81
|
Requires-Dist: parse-type>=0.6.4
|
82
82
|
Requires-Dist: colorama>=0.4.6
|
@@ -104,9 +104,8 @@ Requires-Dist: sortedcontainers==2.4.0
|
|
104
104
|
Requires-Dist: execnet==2.1.1
|
105
105
|
Requires-Dist: iniconfig==2.0.0
|
106
106
|
Requires-Dist: pluggy==1.5.0
|
107
|
-
Requires-Dist: py==1.11.0
|
108
107
|
Requires-Dist: pytest==8.3.4
|
109
|
-
Requires-Dist: pytest-html==
|
108
|
+
Requires-Dist: pytest-html==4.0.2
|
110
109
|
Requires-Dist: pytest-metadata==3.1.1
|
111
110
|
Requires-Dist: pytest-ordering==0.6
|
112
111
|
Requires-Dist: pytest-rerunfailures==14.0; python_version < "3.9"
|
@@ -3,7 +3,7 @@ sbase/__main__.py,sha256=G0bVB1-DM4PGwQ1KyOupaWCs4ePbChZNNWuX2htim5U,647
|
|
3
3
|
sbase/steps.py,sha256=_WvAjydKqZfTdnZW9LPKkRty-g-lfdUPmLqnZj6ulcs,43013
|
4
4
|
seleniumbase/__init__.py,sha256=OtJh8nGKL4xtZpw8KPqmn7Q6R-86t4cWUDyVF5MbMTo,2398
|
5
5
|
seleniumbase/__main__.py,sha256=dn1p6dgCchmcH1zzTzzQvFwwdQQqnTGH6ULV9m4hv24,654
|
6
|
-
seleniumbase/__version__.py,sha256=
|
6
|
+
seleniumbase/__version__.py,sha256=0yzphBzPKyJTvl0mwJ0ISMXG0RNjbnOoBiyWcsdGWqw,46
|
7
7
|
seleniumbase/behave/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
8
|
seleniumbase/behave/behave_helper.py,sha256=elkl8P9eLulRAioLstE9baYNM9N_PHBmAOcajX-pH_Y,24198
|
9
9
|
seleniumbase/behave/behave_sb.py,sha256=-hza7Nx2U41mSObYiPMi48v3JlPh3sJO3yzP0kqZ1Gk,59174
|
@@ -27,7 +27,7 @@ seleniumbase/console_scripts/sb_caseplans.py,sha256=qlmvjQ49bOBE1Q29fVmabimkVibC
|
|
27
27
|
seleniumbase/console_scripts/sb_commander.py,sha256=yqoAK211OE6x5AWL2IAo8WojHtdkVj0AWqfoJ-ewmyo,13329
|
28
28
|
seleniumbase/console_scripts/sb_install.py,sha256=y84Zk-rcp554kcF_g97Xwl0Rn38pyH9wO5OKHX879RI,45831
|
29
29
|
seleniumbase/console_scripts/sb_mkchart.py,sha256=ep9g-9CSIwaOJKVxhB3xjRQpfsuApyN8-Dr129cNXwQ,10941
|
30
|
-
seleniumbase/console_scripts/sb_mkdir.py,sha256=
|
30
|
+
seleniumbase/console_scripts/sb_mkdir.py,sha256=SaI2wnjE5eQLxX8RPdjFjM_ghBbMm4r_vBUzU5t5dzY,29819
|
31
31
|
seleniumbase/console_scripts/sb_mkfile.py,sha256=OWYd4yFccmjrd-gNn1t1una-HDRU2_N2-r4Tg3nHsj0,17744
|
32
32
|
seleniumbase/console_scripts/sb_mkpres.py,sha256=EWFRVacjYTX49y-fEiYTZacM9_01IxuuaO4nMjHrIGo,11015
|
33
33
|
seleniumbase/console_scripts/sb_mkrec.py,sha256=PrizjTmyrROYPO0yDm-zQS3QSfsZNeAmcJKKUvfgLhc,11966
|
@@ -36,7 +36,7 @@ seleniumbase/console_scripts/sb_print.py,sha256=tNy-bMDgwHJO3bZxMpmo9weSE8uhbH0C
|
|
36
36
|
seleniumbase/console_scripts/sb_recorder.py,sha256=fnHb5-kh11Hit-E9Ha-e4QXzqLcZvtij6mb5qNd4B1Q,11032
|
37
37
|
seleniumbase/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
38
38
|
seleniumbase/core/application_manager.py,sha256=e_0sjtI8cjY5BNyZj1QBR0j6_oCScxGmSXYEpcYwuZE,576
|
39
|
-
seleniumbase/core/browser_launcher.py,sha256=
|
39
|
+
seleniumbase/core/browser_launcher.py,sha256=AX1kLcURKVPcZPYG30PSB1Q49revm-9PA_aelPP4Hok,221596
|
40
40
|
seleniumbase/core/capabilities_parser.py,sha256=meIS2uHapTCq2ldfNAToC7r0cKmZDRXuYNKExM1GHDY,6038
|
41
41
|
seleniumbase/core/colored_traceback.py,sha256=DrRWfg7XEnKcgY59Xj7Jdk09H-XqHYBSUpB-DiZt6iY,2020
|
42
42
|
seleniumbase/core/create_db_tables.sql,sha256=VWPtrdiW_HQ6yETHjqTu-VIrTwvd8I8o1NfBeaVSHpU,972
|
@@ -65,7 +65,7 @@ seleniumbase/extensions/disable_csp.zip,sha256=YMifIIgEBiLrEFrS1sfW4Exh4br1V4oK1
|
|
65
65
|
seleniumbase/extensions/recorder.zip,sha256=OOyzF-Ize2cSRu1CqhzSAq5vusI9hqLLd2OIApUHesI,11918
|
66
66
|
seleniumbase/extensions/sbase_ext.zip,sha256=3s1N8zrVaMz8RQEOIoBzC3KDjtmHwVZRvVsX25Odr_s,8175
|
67
67
|
seleniumbase/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
68
|
-
seleniumbase/fixtures/base_case.py,sha256=
|
68
|
+
seleniumbase/fixtures/base_case.py,sha256=XsqsffZcEJfnA323DfgrFy-nRKIsRJ6r6ebylELaiLo,717662
|
69
69
|
seleniumbase/fixtures/constants.py,sha256=e1LppavlrAcI4XBJMq7u5j8SffaQ7SPQps1y0YvZYfY,13649
|
70
70
|
seleniumbase/fixtures/css_to_xpath.py,sha256=9ouDB1xl4MJ2os6JOgTIAyHKOQfuxtxvXC3O5hSnEKA,1954
|
71
71
|
seleniumbase/fixtures/errors.py,sha256=KyxuEVx_e3MPhVrJfNIa_3ltMpbCFxfy_jxK8RFNTns,555
|
@@ -88,7 +88,7 @@ seleniumbase/plugins/basic_test_info.py,sha256=8ov6n417gPbqqvrlT4zrch7l2XcRt-GF2
|
|
88
88
|
seleniumbase/plugins/db_reporting_plugin.py,sha256=En09qUCoojrk9-vbcnsoHdSELoGmag2GDIyu3jTiJas,7331
|
89
89
|
seleniumbase/plugins/driver_manager.py,sha256=s20s0pJYaNrG0WNwyIC04oUMRVFjtm6V_nS1-EvFm7g,34492
|
90
90
|
seleniumbase/plugins/page_source.py,sha256=loTnXxOj4kxEukuTZEiGyvKBhY3KDVDMnNlHHheTBDE,1889
|
91
|
-
seleniumbase/plugins/pytest_plugin.py,sha256=
|
91
|
+
seleniumbase/plugins/pytest_plugin.py,sha256=p8KTnx-xMuo2uLU-pXBj0d0EJYE_9Eb9jMeHC-zwyw8,102988
|
92
92
|
seleniumbase/plugins/s3_logging_plugin.py,sha256=WDfertQgGOW_SRJpFMaekYD6vBVW9VO62POtXXy2HCM,2319
|
93
93
|
seleniumbase/plugins/sb_manager.py,sha256=qCf6RAkAfziLTGgiJvB3V416RxWoTbRLm9wc-KsB8g8,54419
|
94
94
|
seleniumbase/plugins/screen_shots.py,sha256=1hrXw-hzuZ1BR6Yh7AyWX2ABnvnP73-RCbwdz958gj4,1127
|
@@ -135,9 +135,9 @@ seleniumbase/utilities/selenium_grid/start-grid-hub.bat,sha256=Ftq-GrAKRYH2ssDPr
|
|
135
135
|
seleniumbase/utilities/selenium_grid/start-grid-hub.sh,sha256=KADv0RUHONLL2_I443QFK8PryBpDmKn5Gy0s4o0vDSM,106
|
136
136
|
seleniumbase/utilities/selenium_ide/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
137
137
|
seleniumbase/utilities/selenium_ide/convert_ide.py,sha256=pZFnqEJQEKZPyNFjkLD29s2HPQgCrWW9XJWpCPhWOoM,31691
|
138
|
-
seleniumbase-4.33.
|
139
|
-
seleniumbase-4.33.
|
140
|
-
seleniumbase-4.33.
|
141
|
-
seleniumbase-4.33.
|
142
|
-
seleniumbase-4.33.
|
143
|
-
seleniumbase-4.33.
|
138
|
+
seleniumbase-4.33.5.dist-info/LICENSE,sha256=odSYtWibXBnQ1gBg6CnDZ82n8kLF_if5-2nbqnEyD8k,1085
|
139
|
+
seleniumbase-4.33.5.dist-info/METADATA,sha256=D84rG0Bm0fkB2p5-CFUNlUUL8KvU5INS56CzgXjSVX4,86528
|
140
|
+
seleniumbase-4.33.5.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
141
|
+
seleniumbase-4.33.5.dist-info/entry_points.txt,sha256=CNrh2EKNaHYEhO6pP1RJyVLB99LkDDYX7TnUK8xfjqk,623
|
142
|
+
seleniumbase-4.33.5.dist-info/top_level.txt,sha256=4N97aBOQ8ETCnDnokBsWb07lJfTaq3C1ZzYRxvLMxqU,19
|
143
|
+
seleniumbase-4.33.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|