seleniumbase 4.33.3__py3-none-any.whl → 4.33.5__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.
- 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
|