Skip to content

Commit 893b129

Browse files
committed
Add support for a SeleniumBase Context Manager
1 parent 732667d commit 893b129

File tree

9 files changed

+926
-9
lines changed

9 files changed

+926
-9
lines changed

seleniumbase/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
from seleniumbase.core.browser_launcher import get_driver # noqa
88
from seleniumbase.fixtures import js_utils # noqa
99
from seleniumbase.fixtures import page_actions # noqa
10+
from seleniumbase.fixtures import page_utils # noqa
1011
from seleniumbase.fixtures.base_case import BaseCase # noqa
1112
from seleniumbase.masterqa.master_qa import MasterQA # noqa
13+
from seleniumbase.plugins.sb_manager import SB # noqa
14+
from seleniumbase.plugins.driver_manager import Driver # noqa
1215

1316
if sys.version_info[0] >= 3:
1417
from seleniumbase import translate # noqa

seleniumbase/behave/behave_sb.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ def get_configured_sb(context):
180180
sb.visual_baseline = False
181181
sb.window_size = None
182182
sb.maximize_option = False
183+
sb.is_context_manager = False
183184
sb.save_screenshot_after_test = False
184185
sb.timeout_multiplier = None
185186
sb.pytest_html_report = None
@@ -215,6 +216,7 @@ def get_configured_sb(context):
215216
sb.proxy_pac_url = None
216217
sb.swiftshader = False
217218
sb.ad_block_on = False
219+
sb.is_nosetest = False
218220
sb.highlights = None
219221
sb.interval = None
220222
sb.cap_file = None
@@ -826,6 +828,10 @@ def get_configured_sb(context):
826828
sb_config.headless = sb.headless
827829
sb_config.headless_active = False
828830
sb_config.headed = sb.headed
831+
sb_config.is_behave = True
832+
sb_config.is_pytest = False
833+
sb_config.is_nosetest = False
834+
sb_config.is_context_manager = False
829835
sb_config.window_size = sb.window_size
830836
sb_config.maximize_option = sb.maximize_option
831837
sb_config.xvfb = sb.xvfb

seleniumbase/core/browser_launcher.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,7 @@ def validate_proxy_string(proxy_string):
876876

877877

878878
def get_driver(
879-
browser_name,
879+
browser_name=None,
880880
headless=False,
881881
locale_code=None,
882882
use_grid=False,
@@ -921,7 +921,19 @@ def get_driver(
921921
device_width=None,
922922
device_height=None,
923923
device_pixel_ratio=None,
924+
browser=None, # A duplicate of browser_name to avoid confusion
924925
):
926+
if not browser_name:
927+
if browser:
928+
browser_name = browser
929+
else:
930+
browser_name = "chrome" # The default if not specified
931+
browser_name = browser_name.lower()
932+
if headless2 and browser_name == constants.Browser.FIREFOX:
933+
headless2 = False # Only for Chromium
934+
headless = True
935+
if uc_subprocess and not undetectable:
936+
undetectable = True
925937
proxy_auth = False
926938
proxy_user = None
927939
proxy_pass = None

seleniumbase/core/log_helper.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,24 @@ def get_test_id(test):
330330
scenario_name = scenario_name.split(" -- @")[0]
331331
test_id = "%s:%s => %s" % (file_name, line_num, scenario_name)
332332
return test_id
333+
elif hasattr(test, "is_context_manager") and test.is_context_manager:
334+
filename = test.__class__.__module__.split(".")[-1] + ".py"
335+
classname = test.__class__.__name__
336+
methodname = test._testMethodName
337+
context_id = None
338+
if filename == "base_case.py" or methodname == "runTest":
339+
import traceback
340+
341+
stack_base = traceback.format_stack()[0].split(", in ")[0]
342+
test_base = stack_base.split(", in ")[0].split(os.sep)[-1]
343+
if hasattr(test, "cm_filename") and test.cm_filename:
344+
filename = test.cm_filename
345+
else:
346+
filename = test_base.split('"')[0]
347+
classname = "SB"
348+
methodname = ".py:" + test_base.split(", line ")[-1]
349+
context_id = filename.split(".")[0] + methodname + ":" + classname
350+
return context_id
333351
test_id = None
334352
try:
335353
test_id = get_test_name(test)

seleniumbase/fixtures/base_case.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3433,6 +3433,7 @@ def get_new_driver(
34333433
device_width=d_width,
34343434
device_height=d_height,
34353435
device_pixel_ratio=d_p_r,
3436+
browser=browser_name,
34363437
)
34373438
self._drivers_list.append(new_driver)
34383439
self._drivers_browser_map[new_driver] = browser_name
@@ -4571,6 +4572,23 @@ def __process_recorded_actions(self):
45714572
filename = self.__get_filename()
45724573
classname = self.__class__.__name__
45734574
methodname = self._testMethodName
4575+
context_filename = None
4576+
if (
4577+
hasattr(sb_config, "is_context_manager")
4578+
and sb_config.is_context_manager
4579+
and (filename == "base_case.py" or methodname == "runTest")
4580+
):
4581+
import traceback
4582+
4583+
stack_base = traceback.format_stack()[0].split(os.sep)[-1]
4584+
test_base = stack_base.split(", in ")[0]
4585+
if hasattr(self, "cm_filename") and self.cm_filename:
4586+
filename = self.cm_filename
4587+
else:
4588+
filename = test_base.split('"')[0]
4589+
classname = "SB"
4590+
methodname = "test_line_" + test_base.split(", line ")[-1]
4591+
context_filename = filename.split(".")[0] + "_rec.py"
45744592
if hasattr(self, "is_behave") and self.is_behave:
45754593
classname = sb_config.behave_feature.name
45764594
classname = classname.replace("/", " ").replace(" & ", " ")
@@ -4627,6 +4645,8 @@ def __process_recorded_actions(self):
46274645
file_name = sb_config.behave_scenario.filename.replace(".", "_")
46284646
file_name = file_name.split("/")[-1].split("\\")[-1]
46294647
file_name = file_name + "_rec.py"
4648+
elif context_filename:
4649+
file_name = context_filename
46304650
file_path = os.path.join(recordings_folder, file_name)
46314651
out_file = codecs.open(file_path, "w+", "utf-8")
46324652
out_file.writelines("\r\n".join(data))
@@ -13245,6 +13265,11 @@ def __has_exception(self):
1324513265
has_exception = False
1324613266
if hasattr(sys, "last_traceback") and sys.last_traceback is not None:
1324713267
has_exception = True
13268+
elif hasattr(self, "is_context_manager") and self.is_context_manager:
13269+
if self.with_testing_base and self._has_failure:
13270+
return True
13271+
else:
13272+
return False
1324813273
elif python3 and hasattr(self, "_outcome"):
1324913274
if hasattr(self._outcome, "errors") and self._outcome.errors:
1325013275
has_exception = True
@@ -13277,6 +13302,22 @@ def __get_test_id(self):
1327713302
scenario_name = scenario_name.replace(" ", "_")
1327813303
test_id = "%s.%s" % (file_name, scenario_name)
1327913304
return test_id
13305+
elif hasattr(self, "is_context_manager") and self.is_context_manager:
13306+
filename = self.__class__.__module__.split(".")[-1] + ".py"
13307+
methodname = self._testMethodName
13308+
context_id = None
13309+
if filename == "base_case.py" or methodname == "runTest":
13310+
import traceback
13311+
13312+
stack_base = traceback.format_stack()[0].split(", in ")[0]
13313+
test_base = stack_base.split(", in ")[0].split(os.sep)[-1]
13314+
if hasattr(self, "cm_filename") and self.cm_filename:
13315+
filename = self.cm_filename
13316+
else:
13317+
filename = test_base.split('"')[0]
13318+
methodname = ".line_" + test_base.split(", line ")[-1]
13319+
context_id = filename.split(".")[0] + methodname
13320+
return context_id
1328013321
test_id = "%s.%s.%s" % (
1328113322
self.__class__.__module__,
1328213323
self.__class__.__name__,

seleniumbase/plugins/base_plugin.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import sys
88
import time
99
from nose.plugins import Plugin
10+
from seleniumbase import config as sb_config
1011
from seleniumbase.config import settings
1112
from seleniumbase.core import download_helper
1213
from seleniumbase.core import log_helper
@@ -200,10 +201,12 @@ def configure(self, options, conf):
200201
archive_logs = options.archive_logs
201202
log_helper.log_folder_setup(log_path, archive_logs)
202203
download_helper.reset_downloads_folder()
204+
sb_config.is_nosetest = True
203205
if self.report_on:
204206
report_helper.clear_out_old_report_logs(archive_past_runs=False)
205207

206208
def beforeTest(self, test):
209+
sb_config._context_of_runner = False # Context Manager Compatibility
207210
variables = self.options.variables
208211
if variables and type(variables) is str and len(variables) > 0:
209212
bad_input = False

seleniumbase/plugins/pytest_plugin.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,9 @@ def pytest_configure(config):
12851285
sb_config.item_count_skipped = 0
12861286
sb_config.item_count_untested = 0
12871287
sb_config.is_pytest = True
1288+
sb_config.is_behave = False
1289+
sb_config.is_nosetest = False
1290+
sb_config.is_context_manager = False
12881291
sb_config.pytest_config = config
12891292
sb_config.browser = config.getoption("browser")
12901293
if sb_config._browser_shortcut:
@@ -1302,7 +1305,10 @@ def pytest_configure(config):
13021305
sb_config.device_metrics = config.getoption("device_metrics")
13031306
sb_config.headless = config.getoption("headless")
13041307
sb_config.headless2 = config.getoption("headless2")
1305-
if sb_config.browser not in ["chrome", "edge"]:
1308+
if sb_config.headless2 and sb_config.browser == "firefox":
1309+
sb_config.headless2 = False # Only for Chromium browsers
1310+
sb_config.headless = True # Firefox has regular headless
1311+
elif sb_config.browser not in ["chrome", "edge"]:
13061312
sb_config.headless2 = False # Only for Chromium browsers
13071313
sb_config.headed = config.getoption("headed")
13081314
sb_config.xvfb = config.getoption("xvfb")
@@ -1624,6 +1630,7 @@ def pytest_collection_finish(session):
16241630
"""This runs after item collection is finalized.
16251631
https://docs.pytest.org/en/stable/reference.html
16261632
"""
1633+
sb_config._context_of_runner = False # Context Manager Compatibility
16271634
if "--co" in sys_argv or "--collect-only" in sys_argv:
16281635
return
16291636
if len(session.items) > 0 and not sb_config._multithreaded:
@@ -1713,14 +1720,20 @@ def pytest_runtest_teardown(item):
17131720
if hasattr(self, "xvfb") and self.xvfb:
17141721
if self.headless_active and "--pdb" not in sys_argv:
17151722
if hasattr(self, "display") and self.display:
1723+
self.headless_active = False
1724+
sb_config.headless_active = False
17161725
self.display.stop()
17171726
elif hasattr(self, "headless") and self.headless:
17181727
if self.headless_active and "--pdb" not in sys_argv:
17191728
if hasattr(self, "display") and self.display:
1729+
self.headless_active = False
1730+
sb_config.headless_active = False
17201731
self.display.stop()
17211732
elif hasattr(self, "headless2") and self.headless2:
17221733
if self.headless_active and "--pdb" not in sys_argv:
17231734
if hasattr(self, "display") and self.display:
1735+
self.headless_active = False
1736+
sb_config.headless_active = False
17241737
self.display.stop()
17251738
except Exception:
17261739
pass

0 commit comments

Comments
 (0)