Make multiple updates

This commit is contained in:
Michael Mintz 2024-09-23 00:49:23 -04:00
parent bc9de47290
commit d65c52cd18
26 changed files with 648 additions and 797 deletions

View File

@ -11,3 +11,4 @@ from seleniumbase import MasterQA # noqa
from seleniumbase import page_actions # noqa
from seleniumbase import page_utils # noqa
from seleniumbase import SB # noqa
from seleniumbase import translate # noqa

View File

@ -10,7 +10,7 @@ from selenium import webdriver
from seleniumbase.__version__ import __version__
from seleniumbase.common import decorators # noqa
from seleniumbase.common import encryption # noqa
from seleniumbase.core import colored_traceback
from seleniumbase.core import colored_traceback # noqa
from seleniumbase.core.browser_launcher import get_driver # noqa
from seleniumbase.fixtures import js_utils # noqa
from seleniumbase.fixtures import page_actions # noqa
@ -36,8 +36,7 @@ if sys.version_info[0] < 3 and "pdbp" in locals():
pdb.DefaultConfig.sticky_by_default = True
colored_traceback.add_hook()
os.environ["SE_AVOID_STATS"] = "true" # Disable Selenium Manager stats
if sys.version_info >= (3, 7):
webdriver.TouchActions = None # Lifeline for past selenium-wire versions
webdriver.TouchActions = None # Lifeline for past selenium-wire versions
if sys.version_info >= (3, 10):
collections.Callable = collections.abc.Callable # Lifeline for nosetests
del collections # Undo "import collections" / Simplify "dir(seleniumbase)"

View File

@ -48,6 +48,7 @@ behave -D agent="User Agent String" -D demo
-D headless2 (Use the new headless mode, which supports extensions.)
-D headed (Run tests in headed/GUI mode on Linux OS, where not default.)
-D xvfb (Run tests using the Xvfb virtual display server on Linux OS.)
-D xvfb-metrics=STRING (Set Xvfb display size on Linux: "Width,Height".)
-D locale=LOCALE_CODE (Set the Language Locale Code for the web browser.)
-D pdb (Activate Post Mortem Debug Mode if a test fails.)
-D interval=SECONDS (The autoplay interval for presentations & tour steps)
@ -90,6 +91,7 @@ behave -D agent="User Agent String" -D demo
-D rcs | -D reuse-class-session (Reuse session for tests in class/feature)
-D crumbs (Delete all cookies between tests reusing a session.)
-D disable-beforeunload (Disable the "beforeunload" event on Chrome.)
-D window-position=X,Y (Set the browser's starting window position.)
-D window-size=WIDTH,HEIGHT (Set the browser's starting window size.)
-D maximize (Start tests with the browser window maximized.)
-D screenshot (Save a screenshot at the end of each test.)
@ -104,6 +106,7 @@ import colorama
import os
import re
import sys
from contextlib import suppress
from seleniumbase import config as sb_config
from seleniumbase.config import settings
from seleniumbase.core import download_helper
@ -145,6 +148,7 @@ def get_configured_sb(context):
sb.headless_active = False
sb.headed = False
sb.xvfb = False
sb.xvfb_metrics = None
sb.start_page = None
sb.locale_code = None
sb.pdb_option = False
@ -193,6 +197,7 @@ def get_configured_sb(context):
sb._disable_beforeunload = False
sb.visual_baseline = False
sb.use_wire = False
sb.window_position = None
sb.window_size = None
sb.maximize_option = False
sb.is_context_manager = False
@ -302,6 +307,13 @@ def get_configured_sb(context):
if low_key == "xvfb":
sb.xvfb = True
continue
# Handle: -D xvfb-metrics=STR / xvfb_metrics=STR
if low_key in ["xvfb-metrics", "xvfb_metrics"]:
xvfb_metrics = userdata[key]
if xvfb_metrics == "true":
xvfb_metrics = sb.xvfb_metrics # revert to default
sb.xvfb_metrics = xvfb_metrics
continue
# Handle: -D start-page=URL / start_page=URL / url=URL
if low_key in ["start-page", "start_page", "url"]:
start_page = userdata[key]
@ -601,6 +613,13 @@ def get_configured_sb(context):
if low_key == "wire":
sb.use_wire = True
continue
# Handle: -D window-position=X,Y / window_position=X,Y
if low_key in ["window-position", "window_position"]:
window_position = userdata[key]
if window_position == "true":
window_position = sb.window_position # revert to default
sb.window_position = window_position
continue
# Handle: -D window-size=Width,Height / window_size=Width,Height
if low_key in ["window-size", "window_size"]:
window_size = userdata[key]
@ -904,6 +923,29 @@ def get_configured_sb(context):
else:
sb.enable_ws = False
sb.disable_ws = True
if sb.window_position:
window_position = sb.window_position
if window_position.count(",") != 1:
message = (
'\n\n window_position expects an "x,y" string!'
'\n (Your input was: "%s")\n' % window_position
)
raise Exception(message)
window_position = window_position.replace(" ", "")
win_x = None
win_y = None
try:
win_x = int(window_position.split(",")[0])
win_y = int(window_position.split(",")[1])
except Exception:
message = (
'\n\n Expecting integer values for "x,y"!'
'\n (window_position input was: "%s")\n'
% window_position
)
raise Exception(message)
settings.WINDOW_START_X = win_x
settings.WINDOW_START_Y = win_y
if sb.window_size:
window_size = sb.window_size
if window_size.count(",") != 1:
@ -938,9 +980,11 @@ def get_configured_sb(context):
sb_config.is_pytest = False
sb_config.is_nosetest = False
sb_config.is_context_manager = False
sb_config.window_position = sb.window_position
sb_config.window_size = sb.window_size
sb_config.maximize_option = sb.maximize_option
sb_config.xvfb = sb.xvfb
sb_config.xvfb_metrics = sb.xvfb_metrics
sb_config.reuse_class_session = sb._reuse_class_session
sb_config.save_screenshot = sb.save_screenshot_after_test
sb_config.no_screenshot = sb.no_screenshot_after_test
@ -1162,12 +1206,10 @@ def behave_dashboard_prepare():
sb_config.item_count_untested = sb_config.item_count
dash_path = os.path.join(os.getcwd(), "dashboard.html")
star_len = len("Dashboard: ") + len(dash_path)
try:
with suppress(Exception):
terminal_size = os.get_terminal_size().columns
if terminal_size > 30 and star_len > terminal_size:
star_len = terminal_size
except Exception:
pass
stars = "*" * star_len
c1 = ""
cr = ""
@ -1263,7 +1305,7 @@ def _perform_behave_unconfigure_():
def do_final_driver_cleanup_as_needed():
try:
with suppress(Exception):
if hasattr(sb_config, "last_driver") and sb_config.last_driver:
if (
not is_windows
@ -1271,8 +1313,6 @@ def do_final_driver_cleanup_as_needed():
or sb_config.last_driver.service.process
):
sb_config.last_driver.quit()
except Exception:
pass
def _perform_behave_terminal_summary_():
@ -1281,12 +1321,10 @@ def _perform_behave_terminal_summary_():
)
dash_path = os.path.join(os.getcwd(), "dashboard.html")
equals_len = len("Dashboard: ") + len(dash_path)
try:
with suppress(Exception):
terminal_size = os.get_terminal_size().columns
if terminal_size > 30 and equals_len > terminal_size:
equals_len = terminal_size
except Exception:
pass
equals = "=" * (equals_len + 2)
c2 = ""
cr = ""

View File

@ -110,6 +110,10 @@ DISABLE_CSP_ON_CHROME = False
# (This applies when using --proxy=[PROXY_STRING] for using a proxy server.)
RAISE_INVALID_PROXY_STRING_EXCEPTION = True
# Default browser coordinates when opening new windows for tests.
WINDOW_START_X = 20
WINDOW_START_Y = 54
# Default browser resolutions when opening new windows for tests.
# (Headless resolutions take priority, and include all browsers.)
# (Firefox starts maximized by default when running in GUI Mode.)

View File

@ -16,16 +16,16 @@ Output:
import colorama
import subprocess
import sys
import tkinter as tk
from seleniumbase.fixtures import shared_utils
from tkinter.scrolledtext import ScrolledText
if sys.version_info <= (3, 7):
if sys.version_info <= (3, 8):
current_version = ".".join(str(ver) for ver in sys.version_info[:3])
raise Exception(
"\n* SBase Commander requires Python 3.7 or newer!"
"\n* SBase Commander requires Python 3.8 or newer!"
"\n** You are currently using Python %s" % current_version
)
from seleniumbase.fixtures import shared_utils
import tkinter as tk # noqa: E402
from tkinter.scrolledtext import ScrolledText # noqa: E402
def set_colors(use_colors):

View File

@ -20,17 +20,17 @@ import colorama
import os
import subprocess
import sys
import tkinter as tk
from seleniumbase.fixtures import shared_utils
from tkinter import messagebox
from tkinter.scrolledtext import ScrolledText
if sys.version_info <= (3, 7):
if sys.version_info <= (3, 8):
current_version = ".".join(str(ver) for ver in sys.version_info[:3])
raise Exception(
"\n* SBase Case Plans Generator requires Python 3.7 or newer!"
"\n* SBase Case Plans Generator requires Python 3.8 or newer!"
"\n** You are currently using Python %s" % current_version
)
from seleniumbase.fixtures import shared_utils
import tkinter as tk # noqa: E402
from tkinter import messagebox # noqa: E402
from tkinter.scrolledtext import ScrolledText # noqa: E402
def set_colors(use_colors):

View File

@ -21,16 +21,16 @@ import colorama
import os
import subprocess
import sys
import tkinter as tk
from seleniumbase.fixtures import shared_utils
from tkinter.scrolledtext import ScrolledText
if sys.version_info <= (3, 7):
if sys.version_info <= (3, 8):
current_version = ".".join(str(ver) for ver in sys.version_info[:3])
raise Exception(
"\n* SBase Commander requires Python 3.7 or newer!"
"\n* SBase Commander requires Python 3.8 or newer!"
"\n** You are currently using Python %s" % current_version
)
from seleniumbase.fixtures import shared_utils
import tkinter as tk # noqa: E402
from tkinter.scrolledtext import ScrolledText # noqa: E402
def set_colors(use_colors):

View File

@ -18,23 +18,23 @@ import colorama
import os
import subprocess
import sys
import tkinter as tk
from seleniumbase import config as sb_config
from seleniumbase.fixtures import page_utils
from seleniumbase.fixtures import shared_utils
from tkinter import messagebox
sb_config.rec_subprocess_p = None
sb_config.rec_subprocess_used = False
sys_executable = sys.executable
if " " in sys_executable:
sys_executable = "python"
if sys.version_info <= (3, 7):
if sys.version_info <= (3, 8):
current_version = ".".join(str(ver) for ver in sys.version_info[:3])
raise Exception(
"\n* Recorder Desktop requires Python 3.7 or newer!"
"\n* Recorder Desktop requires Python 3.8 or newer!"
"\n*** You are currently using Python %s" % current_version
)
import tkinter as tk # noqa: E402
from tkinter import messagebox # noqa: E402
def set_colors(use_colors):

View File

@ -9,6 +9,7 @@ import time
import types
import urllib3
import warnings
from contextlib import suppress
from selenium import webdriver
from selenium.common.exceptions import ElementClickInterceptedException
from selenium.common.exceptions import InvalidSessionIdException
@ -277,7 +278,7 @@ def chromedriver_on_path():
def get_uc_driver_version(full=False):
uc_driver_version = None
if os.path.exists(LOCAL_UC_DRIVER):
try:
with suppress(Exception):
output = subprocess.check_output(
'"%s" --version' % LOCAL_UC_DRIVER, shell=True
)
@ -292,8 +293,6 @@ def get_uc_driver_version(full=False):
uc_driver_version = full_version
else:
uc_driver_version = output
except Exception:
pass
return uc_driver_version
@ -372,7 +371,7 @@ def uc_special_open_if_cf(
):
if url.startswith("http:") or url.startswith("https:"):
special = False
try:
with suppress(Exception):
req_get = requests_get(url, proxy_string)
status_str = str(req_get.status_code)
if (
@ -384,8 +383,6 @@ def uc_special_open_if_cf(
special = True
if status_str == "403" or status_str == "429":
time.sleep(0.06) # Forbidden / Blocked! (Wait first!)
except Exception:
pass
if special:
time.sleep(0.05)
with driver:
@ -416,13 +413,11 @@ def uc_special_open_if_cf(
"mobile": True
}
)
try:
with suppress(Exception):
driver.execute_cdp_cmd(
'Emulation.setDeviceMetricsOverride',
set_device_metrics_override
)
except Exception:
pass
if not mobile_emulator:
page_actions.switch_to_window(
driver, driver.window_handles[-1], 2
@ -529,13 +524,11 @@ def uc_click(
timeout=settings.SMALL_TIMEOUT,
reconnect_time=None,
):
try:
with suppress(Exception):
rct = float(by) # Add shortcut: driver.uc_click(selector, RCT)
if not reconnect_time:
reconnect_time = rct
by = "css selector"
except Exception:
pass
element = driver.wait_for_selector(selector, by=by, timeout=timeout)
tag_name = element.tag_name
if not tag_name == "span" and not tag_name == "input": # Must be "visible"
@ -574,7 +567,7 @@ def install_pyautogui_if_missing(driver):
with pip_find_lock: # Prevent issues with multiple processes
try:
import pyautogui
try:
with suppress(Exception):
use_pyautogui_ver = constants.PyAutoGUI.VER
if pyautogui.__version__ != use_pyautogui_ver:
del pyautogui
@ -582,8 +575,6 @@ def install_pyautogui_if_missing(driver):
"pyautogui", version=use_pyautogui_ver
)
import pyautogui
except Exception:
pass
except Exception:
print("\nPyAutoGUI required! Installing now...")
shared_utils.pip_install(
@ -794,12 +785,10 @@ def uc_gui_click_x_y(driver, x, y, timeframe=0.25):
y = y * width_ratio
_uc_gui_click_x_y(driver, x, y, timeframe=timeframe, uc_lock=False)
return
try:
with suppress(Exception):
page_actions.switch_to_window(
driver, driver.current_window_handle, 2, uc_lock=False
)
except Exception:
pass
_uc_gui_click_x_y(driver, x, y, timeframe=timeframe, uc_lock=False)
@ -1002,10 +991,8 @@ def _uc_gui_click_captcha(
driver.uc_open_with_disconnect(driver.current_url, 3.8)
else:
driver.disconnect()
try:
_uc_gui_click_x_y(driver, x, y, timeframe=0.54321)
except Exception:
pass
with suppress(Exception):
_uc_gui_click_x_y(driver, x, y, timeframe=0.32)
reconnect_time = (float(constants.UC.RECONNECT_TIME) / 2.0) + 0.6
if IS_LINUX:
reconnect_time = constants.UC.RECONNECT_TIME + 0.2
@ -1047,12 +1034,12 @@ def _uc_gui_click_captcha(
return
if blind:
driver.uc_open_with_disconnect(driver.current_url, 3.8)
_uc_gui_click_x_y(driver, x, y, timeframe=1.05)
_uc_gui_click_x_y(driver, x, y, timeframe=0.32)
else:
driver.uc_open_with_reconnect(driver.current_url, 3.8)
if _on_a_captcha_page(driver):
driver.disconnect()
_uc_gui_click_x_y(driver, x, y, timeframe=1.05)
_uc_gui_click_x_y(driver, x, y, timeframe=0.32)
driver.reconnect(reconnect_time)
@ -1232,13 +1219,11 @@ def _uc_gui_handle_captcha_(driver, frame="iframe", ctype=None):
and sb_config._saved_cf_tab_count
):
driver.uc_open_with_disconnect(driver.current_url, 3.8)
try:
with suppress(Exception):
for i in range(sb_config._saved_cf_tab_count):
pyautogui.press("\t")
time.sleep(0.027)
pyautogui.press(" ")
except Exception:
pass
else:
driver.disconnect()
pyautogui.press(" ")
@ -1919,13 +1904,11 @@ def _set_chrome_options(
else:
chromium_arg_item = "--" + chromium_arg_item
if "remote-debugging-port=" in chromium_arg_item:
try:
with suppress(Exception):
# Extra processing for UC Mode
chrome_options._remote_debugging_port = int(
chromium_arg_item.split("remote-debugging-port=")[1]
)
except Exception:
pass
if "set-binary" in chromium_arg_item and not binary_location:
br_app = "google-chrome"
binary_loc = detect_b_ver.get_binary_location(
@ -2577,14 +2560,12 @@ def get_remote_driver(
try:
from seleniumwire import webdriver
import blinker
try:
with suppress(Exception):
use_blinker_ver = constants.SeleniumWire.BLINKER_VER
if blinker.__version__ != use_blinker_ver:
shared_utils.pip_install(
"blinker", version=use_blinker_ver
)
except Exception:
pass
del blinker
except Exception:
shared_utils.pip_install(
@ -3008,14 +2989,12 @@ def get_local_driver(
try:
from seleniumwire import webdriver
import blinker
try:
with suppress(Exception):
use_blinker_ver = constants.SeleniumWire.BLINKER_VER
if blinker.__version__ != use_blinker_ver:
shared_utils.pip_install(
"blinker", version=use_blinker_ver
)
except Exception:
pass
del blinker
except Exception:
shared_utils.pip_install(
@ -3306,7 +3285,7 @@ def get_local_driver(
edge_driver_version = None
edgedriver_upgrade_needed = False
if os.path.exists(LOCAL_EDGEDRIVER):
try:
with suppress(Exception):
output = subprocess.check_output(
'"%s" --version' % LOCAL_EDGEDRIVER, shell=True
)
@ -3332,8 +3311,6 @@ def get_local_driver(
edge_driver_version = output
if driver_version == "keep":
driver_version = edge_driver_version
except Exception:
pass
use_version = find_edgedriver_version_to_use(
use_version, driver_version
)
@ -3437,7 +3414,7 @@ def get_local_driver(
edge_options.add_argument("--headless=new")
elif headless and undetectable:
# (For later: UC Mode doesn't support Edge now)
try:
with suppress(Exception):
if int(use_version) >= 109:
edge_options.add_argument("--headless=new")
elif (
@ -3447,8 +3424,6 @@ def get_local_driver(
edge_options.add_argument("--headless=chrome")
else:
pass # Will need Xvfb on Linux
except Exception:
pass
elif headless:
if "--headless" not in edge_options.arguments:
edge_options.add_argument("--headless")
@ -3748,19 +3723,15 @@ def get_local_driver(
constants.MultiBrowser.DRIVER_FIXING_LOCK
)
with edgedriver_fixing_lock:
try:
with suppress(Exception):
if not _was_driver_repaired():
_repair_edgedriver(edge_version)
_mark_driver_repaired()
except Exception:
pass
else:
try:
with suppress(Exception):
if not _was_driver_repaired():
_repair_edgedriver(edge_version)
_mark_driver_repaired()
except Exception:
pass
driver = Edge(service=service, options=edge_options)
return extend_driver(driver)
elif browser_name == constants.Browser.SAFARI:
@ -3912,7 +3883,7 @@ def get_local_driver(
ch_driver_version = None
path_chromedriver = chromedriver_on_path()
if os.path.exists(LOCAL_CHROMEDRIVER):
try:
with suppress(Exception):
output = subprocess.check_output(
'"%s" --version' % LOCAL_CHROMEDRIVER, shell=True
)
@ -3926,8 +3897,6 @@ def get_local_driver(
ch_driver_version = output
if driver_version == "keep":
driver_version = ch_driver_version
except Exception:
pass
elif path_chromedriver:
try:
make_driver_executable_if_not(path_chromedriver)
@ -3936,7 +3905,7 @@ def get_local_driver(
"\nWarning: Could not make chromedriver"
" executable: %s" % e
)
try:
with suppress(Exception):
output = subprocess.check_output(
'"%s" --version' % path_chromedriver, shell=True
)
@ -3950,8 +3919,6 @@ def get_local_driver(
ch_driver_version = output
if driver_version == "keep":
use_version = ch_driver_version
except Exception:
pass
disable_build_check = True
uc_driver_version = None
if is_using_uc(undetectable, browser_name):
@ -4144,7 +4111,7 @@ def get_local_driver(
if IS_ARM_MAC and use_uc:
intel_for_uc = True # Use Intel driver for UC Mode
if os.path.exists(LOCAL_CHROMEDRIVER):
try:
with suppress(Exception):
output = subprocess.check_output(
'"%s" --version' % LOCAL_CHROMEDRIVER,
shell=True,
@ -4157,8 +4124,6 @@ def get_local_driver(
output = full_ch_driver_version.split(".")[0]
if int(output) >= 2:
ch_driver_version = output
except Exception:
pass
if (
(
not use_uc
@ -4296,7 +4261,7 @@ def get_local_driver(
chrome_options.add_argument(
"--user-agent=%s" % user_agent
)
try:
with suppress(Exception):
if (
(
not user_agent
@ -4402,7 +4367,7 @@ def get_local_driver(
service=service,
options=headless_options,
)
try:
with suppress(Exception):
user_agent = driver.execute_script(
"return navigator.userAgent;"
)
@ -4424,11 +4389,7 @@ def get_local_driver(
"--user-agent=%s" % user_agent
)
sb_config.uc_agent_cache = user_agent
except Exception:
pass
driver.quit()
except Exception:
pass
uc_path = None
if os.path.exists(LOCAL_UC_DRIVER):
uc_path = LOCAL_UC_DRIVER
@ -4751,13 +4712,11 @@ def get_local_driver(
"mobile": True
}
)
try:
with suppress(Exception):
driver.execute_cdp_cmd(
'Emulation.setDeviceMetricsOverride',
set_device_metrics_override
)
except Exception:
pass
return extend_driver(driver)
else: # Running headless on Linux (and not using --uc)
try:
@ -4803,23 +4762,19 @@ def get_local_driver(
)
with chromedr_fixing_lock:
if not _was_driver_repaired():
try:
with suppress(Exception):
_repair_chromedriver(
chrome_options, chrome_options, mcv
)
_mark_driver_repaired()
except Exception:
pass
else:
if not _was_driver_repaired():
try:
with suppress(Exception):
_repair_chromedriver(
chrome_options, chrome_options, mcv
)
except Exception:
pass
_mark_driver_repaired()
try:
with suppress(Exception):
service = ChromeService(
log_output=os.devnull,
service_args=["--disable-build-check"],
@ -4829,8 +4784,6 @@ def get_local_driver(
options=chrome_options,
)
return extend_driver(driver)
except Exception:
pass
# Use the virtual display on Linux during headless errors
logging.debug(
"\nWarning: Chrome failed to launch in"
@ -4851,14 +4804,12 @@ def get_local_driver(
if is_using_uc(undetectable, browser_name):
raise
# Try again if Chrome didn't launch
try:
with suppress(Exception):
service = ChromeService(service_args=["--disable-build-check"])
driver = webdriver.Chrome(
service=service, options=chrome_options
)
return extend_driver(driver)
except Exception:
pass
if user_data_dir:
print("\nUnable to set user_data_dir while starting Chrome!\n")
raise

View File

@ -35,10 +35,7 @@ class DatabaseManager:
import cryptography # noqa: F401
import pymysql
except Exception:
if sys.version_info < (3, 7):
shared_utils.pip_install("PyMySQL[rsa]", version="1.0.2")
else:
shared_utils.pip_install("PyMySQL[rsa]", version="1.1.0")
shared_utils.pip_install("PyMySQL[rsa]", version="1.1.1")
import pymysql
db_server = settings.DB_HOST
db_port = settings.DB_PORT

View File

@ -422,9 +422,14 @@ def generate_sbase_code(srt_actions):
):
import unicodedata
action[1][0] = unicodedata.normalize("NFKC", action[1][0])
action[1][0] = action[1][0].replace("\n", "\\n")
action[1][0] = action[1][0].replace("\u00B6", "")
text_list = False
try:
action[1][0] = unicodedata.normalize("NFKC", action[1][0])
action[1][0] = action[1][0].replace("\n", "\\n")
action[1][0] = action[1][0].replace("\u00B6", "")
except Exception:
text_list = True
method = "assert_text"
if action[0] == "as_et":
method = "assert_exact_text"
@ -437,7 +442,17 @@ def generate_sbase_code(srt_actions):
elif action[0] == "da_et":
method = "deferred_assert_exact_text"
if action[1][1] != "html":
if '"' not in action[1][0] and '"' not in action[1][1]:
if text_list and '"' not in action[1][1]:
sb_actions.append(
'self.%s(%s, "%s")'
% (method, action[1][0], action[1][1])
)
elif text_list and "'" not in action[1][1]:
sb_actions.append(
"self.%s(%s, '%s')"
% (method, action[1][0], action[1][1])
)
elif '"' not in action[1][0] and '"' not in action[1][1]:
sb_actions.append(
'self.%s("%s", "%s")'
% (method, action[1][0], action[1][1])
@ -458,7 +473,11 @@ def generate_sbase_code(srt_actions):
% (method, action[1][0], action[1][1])
)
else:
if '"' not in action[1][0]:
if text_list:
sb_actions.append(
'self.%s(%s)' % (method, action[1][0])
)
elif '"' not in action[1][0]:
sb_actions.append(
'self.%s("%s")' % (method, action[1][0])
)

View File

@ -1,4 +1,5 @@
"""Add new methods to extend the driver"""
from contextlib import suppress
from selenium.webdriver.remote.webelement import WebElement
from seleniumbase.fixtures import js_utils
from seleniumbase.fixtures import page_actions
@ -36,10 +37,8 @@ class DriverMethods():
selector, by = page_utils.swap_selector_and_by_if_reversed(
selector, by
)
try:
with suppress(Exception):
return self.driver.default_find_element(by=by, value=selector)
except Exception:
pass
raise Exception('No such Element: {%s} (by="%s")!' % (selector, by))
def get_attribute(self, selector, attribute, by="css selector"):

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
import re
import requests
import time
from contextlib import suppress
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.common.by import By
@ -56,11 +57,9 @@ def execute_async_script(driver, script, timeout=settings.LARGE_TIMEOUT):
def wait_for_angularjs(driver, timeout=settings.LARGE_TIMEOUT, **kwargs):
if hasattr(settings, "SKIP_JS_WAITS") and settings.SKIP_JS_WAITS:
return
try:
with suppress(Exception):
# This closes pop-up alerts
driver.execute_script("")
except Exception:
pass
if (
(hasattr(driver, "_is_using_uc") and driver._is_using_uc)
or not settings.WAIT_FOR_ANGULARJS
@ -92,10 +91,8 @@ def wait_for_angularjs(driver, timeout=settings.LARGE_TIMEOUT, **kwargs):
"handler": handler,
"suffix": suffix,
}
try:
with suppress(Exception):
execute_async_script(driver, script, timeout=timeout)
except Exception:
pass
def convert_to_css_selector(selector, by=By.CSS_SELECTOR):
@ -191,14 +188,12 @@ def raise_unable_to_load_jquery_exception(driver):
def activate_jquery(driver):
# If "jQuery is not defined" on a website, use this method to activate it.
# This method is needed because jQuery is not always defined on web sites.
try:
with suppress(Exception):
# Let's first find out if jQuery is already defined.
driver.execute_script("jQuery('html');")
# Since that command worked, jQuery is defined. Let's return.
return
except Exception:
# jQuery is not currently defined. Let's proceed by defining it.
pass
# jQuery is not defined. It will be loaded in the next part.
jquery_js = constants.JQuery.MIN_JS
add_js_link(driver, jquery_js)
for x in range(36):
@ -390,11 +385,9 @@ def highlight(driver, selector, by="css selector", loops=4):
def highlight_with_js(driver, selector, loops=4, o_bs=""):
try:
with suppress(Exception):
# This closes any pop-up alerts
driver.execute_script("")
except Exception:
pass
if selector == "html":
selector = "body"
selector_no_spaces = selector.replace(" ", "")
@ -490,11 +483,9 @@ def highlight_with_js(driver, selector, loops=4, o_bs=""):
def highlight_element_with_js(driver, element, loops=4, o_bs=""):
try:
with suppress(Exception):
# This closes any pop-up alerts
driver.execute_script("")
except Exception:
pass
script = (
"""arguments[0].style.boxShadow =
'0px 0px 6px 6px rgba(128, 128, 128, 0.5)';"""
@ -566,11 +557,9 @@ def highlight_element_with_js(driver, element, loops=4, o_bs=""):
def highlight_with_jquery(driver, selector, loops=4, o_bs=""):
try:
with suppress(Exception):
# This closes any pop-up alerts
driver.execute_script("")
except Exception:
pass
if selector == "html":
selector = "body"
selector_no_spaces = selector.replace(" ", "")
@ -908,11 +897,9 @@ def set_messenger_theme(
time.sleep(0.03)
activate_messenger(driver)
time.sleep(0.15)
try:
with suppress(Exception):
driver.execute_script(msg_style)
time.sleep(0.02)
except Exception:
pass
time.sleep(0.05)
@ -949,7 +936,7 @@ def post_messenger_success_message(driver, message, msg_dur=None):
if not msg_dur:
msg_dur = settings.DEFAULT_MESSAGE_DURATION
msg_dur = float(msg_dur)
try:
with suppress(Exception):
theme = "future"
location = "bottom_right"
if hasattr(sb_config, "mobile_emulator") and sb_config.mobile_emulator:
@ -957,28 +944,22 @@ def post_messenger_success_message(driver, message, msg_dur=None):
set_messenger_theme(driver, theme=theme, location=location)
post_message(driver, message, msg_dur, style="success")
time.sleep(msg_dur + 0.07)
except Exception:
pass
def post_messenger_error_message(driver, message, msg_dur=None):
if not msg_dur:
msg_dur = settings.DEFAULT_MESSAGE_DURATION
msg_dur = float(msg_dur)
try:
with suppress(Exception):
set_messenger_theme(driver, theme="block", location="top_center")
post_message(driver, message, msg_dur, style="error")
time.sleep(msg_dur + 0.07)
except Exception:
pass
def highlight_with_js_2(driver, message, selector, o_bs, msg_dur):
try:
with suppress(Exception):
# This closes any pop-up alerts
driver.execute_script("")
except Exception:
pass
if selector == "html":
selector = "body"
selector_no_spaces = selector.replace(" ", "")
@ -991,11 +972,9 @@ def highlight_with_js_2(driver, message, selector, o_bs, msg_dur):
else:
early_exit = True # Changing the box-shadow changes the selector
if early_exit:
try:
with suppress(Exception):
activate_jquery(driver)
post_messenger_success_message(driver, message, msg_dur)
except Exception:
pass
return
script = (
"""document.querySelector('%s').style.boxShadow =
@ -1047,11 +1026,9 @@ def highlight_with_js_2(driver, message, selector, o_bs, msg_dur):
except Exception:
return
time.sleep(0.0181)
try:
with suppress(Exception):
activate_jquery(driver)
post_messenger_success_message(driver, message, msg_dur)
except Exception:
pass
script = """document.querySelector('%s').style.boxShadow = '%s';""" % (
selector,
o_bs,
@ -1063,11 +1040,9 @@ def highlight_with_js_2(driver, message, selector, o_bs, msg_dur):
def highlight_element_with_js_2(driver, message, element, o_bs, msg_dur):
try:
with suppress(Exception):
# This closes any pop-up alerts
driver.execute_script("")
except Exception:
pass
script = (
"""arguments[0].style.boxShadow =
'0px 0px 6px 6px rgba(128, 128, 128, 0.5)';"""
@ -1113,11 +1088,9 @@ def highlight_element_with_js_2(driver, message, element, o_bs, msg_dur):
except Exception:
return
time.sleep(0.0181)
try:
with suppress(Exception):
activate_jquery(driver)
post_messenger_success_message(driver, message, msg_dur)
except Exception:
pass
script = """arguments[0].style.boxShadow = '%s';""" % (o_bs)
try:
driver.execute_script(script, element)
@ -1138,11 +1111,9 @@ def highlight_with_jquery_2(driver, message, selector, o_bs, msg_dur):
else:
early_exit = True # Changing the box-shadow changes the selector
if early_exit:
try:
with suppress(Exception):
activate_jquery(driver)
post_messenger_success_message(driver, message, msg_dur)
except Exception:
pass
return
script = (
"""jQuery('%s').css('box-shadow',
@ -1195,11 +1166,9 @@ def highlight_with_jquery_2(driver, message, selector, o_bs, msg_dur):
return
time.sleep(0.0181)
try:
with suppress(Exception):
activate_jquery(driver)
post_messenger_success_message(driver, message, msg_dur)
except Exception:
pass
script = """jQuery('%s').css('box-shadow', '%s');""" % (selector, o_bs)
try:
@ -1484,12 +1453,10 @@ def get_drag_and_drop_with_offset_script(selector, x, y):
def clear_out_console_logs(driver):
try:
with suppress(Exception):
# Clear out the current page log before navigating to a new page
# (To make sure that assert_no_js_errors() uses current results)
driver.get_log("browser")
except Exception:
pass
def _jq_format(code):

View File

@ -21,6 +21,7 @@ import codecs
import fasteners
import os
import time
from contextlib import suppress
from selenium.common.exceptions import ElementNotInteractableException
from selenium.common.exceptions import ElementNotVisibleException
from selenium.common.exceptions import NoAlertPresentException
@ -1409,12 +1410,10 @@ def switch_to_frame(driver, frame, timeout=settings.SMALL_TIMEOUT):
else:
by = "css selector"
if is_element_visible(driver, frame, by=by):
try:
with suppress(Exception):
element = driver.find_element(by=by, value=frame)
driver.switch_to.frame(element)
return True
except Exception:
pass
now_ms = time.time() * 1000.0
if now_ms >= stop_ms:
break
@ -1548,12 +1547,10 @@ def click_if_visible(
if is_element_visible(driver, selector, by=by):
click(driver, selector, by=by, timeout=1)
elif timeout > 0:
try:
with suppress(Exception):
wait_for_element_visible(
driver, selector, by=by, timeout=timeout
)
except Exception:
pass
if is_element_visible(driver, selector, by=by):
click(driver, selector, by=by, timeout=1)

View File

@ -16,7 +16,7 @@ def get_domain_url(url):
Into this:
https://blog.xkcd.com
"""
if not url.startswith("http://") and not url.startswith("https://"):
if not url.startswith(("http://", "https://")):
return url
url_header = url.split("://")[0]
simple_url = url.split("://")[1]
@ -40,45 +40,25 @@ def swap_selector_and_by_if_reversed(selector, by):
def is_xpath_selector(selector):
"""Determine if a selector is an xpath selector."""
if (
selector.startswith("/")
or selector.startswith("./")
or selector.startswith("(")
):
return True
return False
return selector.startswith(("/", "./", "("))
def is_link_text_selector(selector):
"""Determine if a selector is a link text selector."""
if (
selector.startswith("link=")
or selector.startswith("link_text=")
or selector.startswith("text=")
):
return True
return False
return selector.startswith(("link=", "link_text=", "text="))
def is_partial_link_text_selector(selector):
"""Determine if a selector is a partial link text selector."""
if (
selector.startswith("partial_link=")
or selector.startswith("partial_link_text=")
or selector.startswith("partial_text=")
or selector.startswith("p_link=")
or selector.startswith("p_link_text=")
or selector.startswith("p_text=")
):
return True
return False
return selector.startswith((
"partial_link=", "partial_link_text=", "partial_text=",
"p_link=", "p_link_text=", "p_text="
))
def is_name_selector(selector):
"""Determine if a selector is a name selector."""
if selector.startswith("name=") or selector.startswith("&"):
return True
return False
return selector.startswith(("name=", "&"))
def recalculate_selector(selector, by, xp_ok=True):
@ -108,10 +88,9 @@ def recalculate_selector(selector, by, xp_ok=True):
name = get_name_from_selector(selector)
selector = '[name="%s"]' % name
by = By.CSS_SELECTOR
if xp_ok:
if ":contains(" in selector and by == By.CSS_SELECTOR:
selector = css_to_xpath.convert_css_to_xpath(selector)
by = By.XPATH
if xp_ok and ":contains(" in selector and by == By.CSS_SELECTOR:
selector = css_to_xpath.convert_css_to_xpath(selector)
by = By.XPATH
if by == "":
by = By.CSS_SELECTOR
if not is_valid_by(by):
@ -130,21 +109,10 @@ def looks_like_a_page_url(url):
possible typos when calling self.get(url), which will try to
navigate to the page if a URL is detected, but will instead call
self.get_element(URL_AS_A_SELECTOR) if the input is not a URL."""
if (
url.startswith("http:")
or url.startswith("https:")
or url.startswith("://")
or url.startswith("about:")
or url.startswith("blob:")
or url.startswith("chrome:")
or url.startswith("data:")
or url.startswith("edge:")
or url.startswith("file:")
or url.startswith("view-source:")
):
return True
else:
return False
return url.startswith((
"http:", "https:", "://", "about:", "blob:", "chrome:",
"data:", "edge:", "file:", "view-source:"
))
def get_link_text_from_selector(selector):
@ -195,18 +163,12 @@ def is_valid_url(url):
r"(?:/?|[/?]\S+)$",
re.IGNORECASE,
)
if (
return (
regex.match(url)
or url.startswith("about:")
or url.startswith("blob:")
or url.startswith("chrome:")
or url.startswith("data:")
or url.startswith("edge:")
or url.startswith("file:")
):
return True
else:
return False
or url.startswith((
"about:", "blob:", "chrome:", "data:", "edge:", "file:"
))
)
def _get_unique_links(page_url, soup):

View File

@ -2,6 +2,7 @@
import ast
import sys
import time
from contextlib import suppress
from nose.plugins import Plugin
from seleniumbase import config as sb_config
from seleniumbase.config import settings
@ -305,14 +306,12 @@ class Base(Plugin):
if python3_11_or_newer and py311_patch2:
# Handle a bug on Python 3.11 where exceptions aren't seen
sb_config._browser_version = None
try:
with suppress(Exception):
test._BaseCase__set_last_page_screenshot()
test._BaseCase__set_last_page_url()
test._BaseCase__set_last_page_source()
sb_config._browser_version = test._get_browser_version()
test._log_fail_data()
except Exception:
pass
sb_config._excinfo_tb = err
log_path = None
if hasattr(sb_config, "_test_logpath"):

View File

@ -7,7 +7,7 @@ Usage --> ``with DriverContext() as driver:``
Example -->
```
```python
from seleniumbase import DriverContext
with DriverContext() as driver:
@ -27,7 +27,7 @@ Usage --> ``driver = Driver()``
Example -->
```
```python
from seleniumbase import Driver
driver = Driver()
@ -75,7 +75,7 @@ def Driver(
proxy=None, # Use proxy. Format: "SERVER:PORT" or "USER:PASS@SERVER:PORT".
proxy_bypass_list=None, # Skip proxy when using the listed domains.
proxy_pac_url=None, # Use PAC file. (Format: URL or USERNAME:PASSWORD@URL)
multi_proxy=False, # Allow multiple proxies with auth when multi-threaded.
multi_proxy=None, # Allow multiple proxies with auth when multi-threaded.
agent=None, # Modify the web browser's User-Agent string.
cap_file=None, # The desired capabilities to use with a Selenium Grid.
cap_string=None, # The desired capabilities to use with a Selenium Grid.
@ -133,7 +133,98 @@ def Driver(
wire=None, # Shortcut / Duplicate of "use_wire".
pls=None, # Shortcut / Duplicate of "page_load_strategy".
):
"""
* SeleniumBase Driver as a Python Context Manager or a returnable object. *
Example 1: (context manager format)
-----------------------------------
.. code-block:: python
from seleniumbase import DriverContext
with DriverContext() as driver:
driver.get("https://google.com/ncr")
Example 2: (as a Python returnable)
-----------------------------------
.. code-block:: python
from seleniumbase import Driver
driver = Driver()
driver.get("https://google.com/ncr")
Optional Parameters:
--------------------
browser: # Choose from "chrome", "edge", "firefox", or "safari".
headless: # The original headless mode for Chromium and Firefox.
headless2: # Chromium's new headless mode. (Has more features)
headed: # Run tests in headed/GUI mode on Linux, where not default.
locale_code: # Set the Language Locale Code for the web browser.
protocol: # The Selenium Grid protocol: "http" or "https".
servername: # The Selenium Grid server/IP used for tests.
port: # The Selenium Grid port used by the test server.
proxy: # Use proxy. Format: "SERVER:PORT" or "USER:PASS@SERVER:PORT".
proxy_bypass_list: # Skip proxy when using the listed domains.
proxy_pac_url: # Use PAC file. (Format: URL or USERNAME:PASSWORD@URL)
multi_proxy: # Allow multiple proxies with auth when multi-threaded.
agent: # Modify the web browser's User-Agent string.
cap_file: # The desired capabilities to use with a Selenium Grid.
cap_string: # The desired capabilities to use with a Selenium Grid.
recorder_ext: # Enables the SeleniumBase Recorder Chromium extension.
disable_js: # Disable JavaScript on websites. Pages might break!
disable_csp: # Disable the Content Security Policy of websites.
enable_ws: # Enable Web Security on Chromium-based browsers.
disable_ws: # Reverse of "enable_ws". (None and False are different)
enable_sync: # Enable "Chrome Sync" on websites.
use_auto_ext: # Use Chrome's automation extension.
undetectable: # Use undetected-chromedriver to evade bot-detection.
uc_cdp_events: # Capture CDP events in undetected-chromedriver mode.
uc_subprocess: # Use undetected-chromedriver as a subprocess.
log_cdp_events: # Capture {"performance": "ALL", "browser": "ALL"}
no_sandbox: # (DEPRECATED) - "--no-sandbox" is always used now.
disable_gpu: # (DEPRECATED) - GPU is disabled if not "swiftshader".
incognito: # Enable Chromium's Incognito mode.
guest_mode: # Enable Chromium's Guest mode.
dark_mode: # Enable Chromium's Dark mode.
devtools: # Open Chromium's DevTools when the browser opens.
remote_debug: # Enable Chrome's Debugger on "http://localhost:9222".
enable_3d_apis: # Enable WebGL and 3D APIs.
swiftshader: # Chrome: --use-gl=angle / --use-angle=swiftshader-webgl
ad_block_on: # Block some types of display ads from loading.
host_resolver_rules: # Set host-resolver-rules, comma-separated.
block_images: # Block images from loading during tests.
do_not_track: # Tell websites that you don't want to be tracked.
chromium_arg: # "ARG=N,ARG2" (Set Chromium args, ","-separated.)
firefox_arg: # "ARG=N,ARG2" (Set Firefox args, comma-separated.)
firefox_pref: # SET (Set Firefox PREFERENCE:VALUE set, ","-separated)
user_data_dir: # Set the Chrome user data directory to use.
extension_zip: # Load a Chrome Extension .zip|.crx, comma-separated.
extension_dir: # Load a Chrome Extension directory, comma-separated.
disable_features: # "F1,F2" (Disable Chrome features, ","-separated.)
binary_location: # Set path of the Chromium browser binary to use.
driver_version: # Set the chromedriver or uc_driver version to use.
page_load_strategy: # Set Chrome PLS to "normal", "eager", or "none".
use_wire: # Use selenium-wire's webdriver over selenium webdriver.
external_pdf: # Set Chrome "plugins.always_open_pdf_externally":True.
window_position: # Set the browser's starting window position: "X,Y"
window_size: # Set the browser's starting window size: "Width,Height"
is_mobile: # Use the mobile device emulator while running tests.
mobile: # Shortcut / Duplicate of "is_mobile".
d_width: # Set device width
d_height: # Set device height
d_p_r: # Set device pixel ratio
uc: # Shortcut / Duplicate of "undetectable".
undetected: # Shortcut / Duplicate of "undetectable".
uc_cdp: # Shortcut / Duplicate of "uc_cdp_events".
uc_sub: # Shortcut / Duplicate of "uc_subprocess".
log_cdp: # Shortcut / Duplicate of "log_cdp_events".
ad_block: # Shortcut / Duplicate of "ad_block_on".
server: # Shortcut / Duplicate of "servername".
guest: # Shortcut / Duplicate of "guest_mode".
wire: # Shortcut / Duplicate of "use_wire".
pls: # Shortcut / Duplicate of "page_load_strategy".
"""
from seleniumbase import config as sb_config
from seleniumbase.config import settings
from seleniumbase.fixtures import constants
from seleniumbase.fixtures import shared_utils

View File

@ -4,6 +4,7 @@ import os
import pytest
import sys
import time
from contextlib import suppress
from seleniumbase import config as sb_config
from seleniumbase.config import settings
from seleniumbase.core import log_helper
@ -1848,10 +1849,8 @@ def _create_dashboard_assets_():
abs_path = os.path.abspath(".")
assets_folder = os.path.join(abs_path, "assets")
if not os.path.exists(assets_folder):
try:
with suppress(Exception):
os.makedirs(assets_folder, exist_ok=True)
except Exception:
pass
pytest_style_css = os.path.join(assets_folder, "pytest_style.css")
add_pytest_style_css = True
if os.path.exists(pytest_style_css):
@ -1923,12 +1922,10 @@ def pytest_collection_finish(session):
dash_path = os.path.join(os.getcwd(), "dashboard.html")
dash_url = "file://" + dash_path.replace("\\", "/")
star_len = len("Dashboard: ") + len(dash_url)
try:
with suppress(Exception):
terminal_size = os.get_terminal_size().columns
if terminal_size > 30 and star_len > terminal_size:
star_len = terminal_size
except Exception:
pass
stars = "*" * star_len
c1 = ""
cr = ""
@ -1970,11 +1967,11 @@ def pytest_runtest_teardown(item):
(Has zero effect on tests using --reuse-session / --rs)"""
if "--co" in sys_argv or "--collect-only" in sys_argv:
return
try:
with suppress(Exception):
if hasattr(item, "_testcase") or hasattr(sb_config, "_sb_pdb_driver"):
if hasattr(item, "_testcase"):
self = item._testcase
try:
with suppress(Exception):
if (
hasattr(self, "driver")
and self.driver
@ -1982,22 +1979,18 @@ def pytest_runtest_teardown(item):
):
if not (is_windows or self.driver.service.process):
self.driver.quit()
except Exception:
pass
elif (
hasattr(sb_config, "_sb_pdb_driver")
and sb_config._sb_pdb_driver
):
try:
with suppress(Exception):
if (
not is_windows
or sb_config._sb_pdb_driver.service.process
):
sb_config._sb_pdb_driver.quit()
sb_config._sb_pdb_driver = None
except Exception:
pass
try:
with suppress(Exception):
if (
hasattr(self, "_xvfb_display")
and self._xvfb_display
@ -2014,10 +2007,6 @@ def pytest_runtest_teardown(item):
):
sb_config._virtual_display.stop()
sb_config._virtual_display = None
except Exception:
pass
except Exception:
pass
if (
(
sb_config._has_exception
@ -2398,7 +2387,7 @@ def pytest_runtest_makereport(item, call):
)
if log_path:
sb_config._log_fail_data()
try:
with suppress(Exception):
extra_report = None
if hasattr(item, "_testcase"):
extra_report = item._testcase._html_report_extra
@ -2443,5 +2432,3 @@ def pytest_runtest_makereport(item, call):
"</script>" % constants.Dashboard.LIVE_JS
)
report.extra.append(pytest_html.extras.html(refresh_updates))
except Exception:
pass

View File

@ -7,7 +7,7 @@ Usage --> ``with SB() as sb:``
Example -->
```
```python
from seleniumbase import SB
with SB() as sb: # Many args! Eg. SB(browser="edge")
@ -41,7 +41,7 @@ def SB(
proxy=None, # Use proxy. Format: "SERVER:PORT" or "USER:PASS@SERVER:PORT".
proxy_bypass_list=None, # Skip proxy when using the listed domains.
proxy_pac_url=None, # Use PAC file. (Format: URL or USERNAME:PASSWORD@URL)
multi_proxy=False, # Allow multiple proxies with auth when multi-threaded.
multi_proxy=None, # Allow multiple proxies with auth when multi-threaded.
agent=None, # Modify the web browser's User-Agent string.
cap_file=None, # The desired capabilities to use with a Selenium Grid.
cap_string=None, # The desired capabilities to use with a Selenium Grid.
@ -127,6 +127,124 @@ def SB(
interval=None, # SECONDS (Autoplay interval for SB Slides & Tour steps.)
time_limit=None, # SECONDS (Safely fail tests that exceed the time limit.)
):
"""
* SeleniumBase as a Python Context Manager *
Example:
--------
.. code-block:: python
from seleniumbase import SB
with SB() as sb: # Many args! Eg. SB(browser="edge")
sb.open("https://google.com/ncr")
sb.type('[name="q"]', "SeleniumBase on GitHub")
sb.submit('[name="q"]')
sb.click('a[href*="github.com/seleniumbase"]')
sb.highlight("div.Layout-main")
sb.highlight("div.Layout-sidebar")
sb.sleep(0.5)
Optional Parameters:
--------------------
test: Test Mode: Output, Logging, Continue on failure unless "rtf".
rtf: Shortcut / Duplicate of "raise_test_failure".
raise_test_failure: If "test" mode, raise Exception on 1st failure.
browser: Choose from "chrome", "edge", "firefox", or "safari".
headless: The original headless mode for Chromium and Firefox.
headless2: Chromium's new headless mode. (Has more features)
locale_code: Set the Language Locale Code for the web browser.
protocol: The Selenium Grid protocol: "http" or "https".
servername: The Selenium Grid server/IP used for tests.
port: The Selenium Grid port used by the test server.
proxy: Use proxy. Format: "SERVER:PORT" or "USER:PASS@SERVER:PORT".
proxy_bypass_list: Skip proxy when using the listed domains.
proxy_pac_url: Use PAC file. (Format: URL or USERNAME:PASSWORD@URL)
multi_proxy: # Allow multiple proxies with auth when multi-threaded.
agent: Modify the web browser's User-Agent string.
cap_file: The desired capabilities to use with a Selenium Grid.
cap_string: The desired capabilities to use with a Selenium Grid.
recorder_ext: Enables the SeleniumBase Recorder Chromium extension.
disable_js: Disable JavaScript on websites. Pages might break!
disable_csp: Disable the Content Security Policy of websites.
enable_ws: Enable Web Security on Chromium-based browsers.
enable_sync: Enable "Chrome Sync" on websites.
use_auto_ext: Use Chrome's automation extension.
undetectable: Use undetected-chromedriver to evade bot-detection.
uc_cdp_events: Capture CDP events in undetected-chromedriver mode.
uc_subprocess: Use undetected-chromedriver as a subprocess.
log_cdp_events: Capture {"performance": "ALL", "browser": "ALL"}
incognito: Enable Chromium's Incognito mode.
guest_mode: Enable Chromium's Guest mode.
dark_mode: Enable Chromium's Dark mode.
devtools: Open Chromium's DevTools when the browser opens.
remote_debug: Enable Chrome's Debugger on "http://localhost:9222".
enable_3d_apis: Enable WebGL and 3D APIs.
swiftshader: Chrome: --use-gl=angle / --use-angle=swiftshader-webgl
ad_block_on: Block some types of display ads from loading.
host_resolver_rules: Set host-resolver-rules, comma-separated.
block_images: Block images from loading during tests.
do_not_track: Tell websites that you don't want to be tracked.
chromium_arg: "ARG=N,ARG2" (Set Chromium args, ","-separated.)
firefox_arg: "ARG=N,ARG2" (Set Firefox args, comma-separated.)
firefox_pref: SET (Set Firefox PREFERENCE:VALUE set, ","-separated)
user_data_dir: Set the Chrome user data directory to use.
extension_zip: Load a Chrome Extension .zip|.crx, comma-separated.
extension_dir: Load a Chrome Extension directory, comma-separated.
disable_features: "F1,F2" (Disable Chrome features, ","-separated.)
binary_location: Set path of the Chromium browser binary to use.
driver_version: Set the chromedriver or uc_driver version to use.
skip_js_waits: Skip JS Waits (readyState=="complete" and Angular).
wait_for_angularjs: Wait for AngularJS to load after some actions.
use_wire: Use selenium-wire's webdriver over selenium webdriver.
external_pdf: Set Chrome "plugins.always_open_pdf_externally":True.
window_position: Set the browser's starting window position: "X,Y"
window_size: Set the browser's starting window size: "Width,Height"
is_mobile: Use the mobile device emulator while running tests.
mobile: Shortcut / Duplicate of "is_mobile".
device_metrics: Set mobile metrics: "CSSWidth,CSSHeight,PixelRatio"
xvfb: Run tests using the Xvfb virtual display server on Linux OS.
xvfb_metrics: Set Xvfb display size on Linux: "Width,Height".
start_page: The starting URL for the web browser when tests begin.
rec_print: If Recorder is enabled, prints output after tests end.
rec_behave: Like Recorder Mode, but also generates behave-gherkin.
record_sleep: If Recorder enabled, also records self.sleep calls.
data: Extra test data. Access with "self.data" in tests.
var1: Extra test data. Access with "self.var1" in tests.
var2: Extra test data. Access with "self.var2" in tests.
var3: Extra test data. Access with "self.var3" in tests.
variables: DICT (Extra test data. Access with "self.variables")
account: Set account. Access with "self.account" in tests.
environment: Set the test env. Access with "self.env" in tests.
headed: Run tests in headed/GUI mode on Linux, where not default.
maximize: Start tests with the browser window maximized.
disable_ws: Reverse of "enable_ws". (None and False are different)
disable_beforeunload: Disable the "beforeunload" event on Chromium.
settings_file: A file for overriding default SeleniumBase settings.
uc: Shortcut / Duplicate of "undetectable".
undetected: Shortcut / Duplicate of "undetectable".
uc_cdp: Shortcut / Duplicate of "uc_cdp_events".
uc_sub: Shortcut / Duplicate of "uc_subprocess".
log_cdp: Shortcut / Duplicate of "log_cdp_events".
ad_block: Shortcut / Duplicate of "ad_block_on".
server: Shortcut / Duplicate of "servername".
guest: Shortcut / Duplicate of "guest_mode".
wire: Shortcut / Duplicate of "use_wire".
pls: Shortcut / Duplicate of "page_load_strategy".
sjw: Shortcut / Duplicate of "skip_js_waits".
wfa: Shortcut / Duplicate of "wait_for_angularjs".
save_screenshot: Save a screenshot at the end of each test.
no_screenshot: No screenshots saved unless tests directly ask it.
page_load_strategy: Set Chrome PLS to "normal", "eager", or "none".
timeout_multiplier: Multiplies the default timeout values.
js_checking_on: Check for JavaScript errors after page loads.
slow: Slow down the automation. Faster than using Demo Mode.
demo: Slow down and visually see test actions as they occur.
demo_sleep: SECONDS (Set wait time after Slow & Demo Mode actions.)
message_duration: SECONDS (The time length for Messenger alerts.)
highlights: Number of highlight animations for Demo Mode actions.
interval: SECONDS (Autoplay interval for SB Slides & Tour steps.)
time_limit: SECONDS (Safely fail tests that exceed the time limit.)
"""
import os
import sys
import time

View File

@ -1,5 +1,6 @@
"""Selenium Plugin for SeleniumBase tests that run with pynose / nosetests"""
import sys
from contextlib import suppress
from nose.plugins import Plugin
from seleniumbase import config as sb_config
from seleniumbase.config import settings
@ -1308,7 +1309,7 @@ class SeleniumBrowser(Plugin):
):
width = settings.HEADLESS_START_WIDTH
height = settings.HEADLESS_START_HEIGHT
try:
with suppress(Exception):
from sbvirtualdisplay import Display
self._xvfb_display = Display(visible=0, size=(width, height))
@ -1316,8 +1317,6 @@ class SeleniumBrowser(Plugin):
sb_config._virtual_display = self._xvfb_display
self.headless_active = True
sb_config.headless_active = True
except Exception:
pass
sb_config._is_timeout_changed = False
sb_config._SMALL_TIMEOUT = settings.SMALL_TIMEOUT
sb_config._LARGE_TIMEOUT = settings.LARGE_TIMEOUT
@ -1350,7 +1349,7 @@ class SeleniumBrowser(Plugin):
pass
except Exception:
pass
try:
with suppress(Exception):
if (
hasattr(self, "_xvfb_display")
and self._xvfb_display
@ -1367,5 +1366,3 @@ class SeleniumBrowser(Plugin):
):
sb_config._virtual_display.stop()
sb_config._virtual_display = None
except Exception:
pass

View File

@ -10,6 +10,7 @@ import selenium.webdriver.chrome.service
import selenium.webdriver.chrome.webdriver
import selenium.webdriver.common.service
import selenium.webdriver.remote.command
from contextlib import suppress
from .cdp import CDP
from .cdp import PageElement
from .dprocess import start_detached
@ -201,11 +202,9 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
# Create a temporary folder for the user-data profile.
options.add_argument(arg)
if not language:
try:
with suppress(Exception):
import locale
language = locale.getlocale()[0].replace("_", "-")
except Exception:
pass
if (
not language
or "English" in language
@ -242,7 +241,7 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
)
if hasattr(options, 'handle_prefs'):
options.handle_prefs(user_data_dir)
try:
with suppress(Exception):
import json
with open(
os.path.join(
@ -263,8 +262,6 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
fs.seek(0, 0)
fs.truncate()
json.dump(config, fs)
except Exception:
pass
creationflags = 0
if "win32" in sys.platform:
creationflags = subprocess.CREATE_NO_WINDOW
@ -293,8 +290,6 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
self.browser_pid = browser.pid
service_ = None
log_output = subprocess.PIPE
if sys.version_info < (3, 8):
log_output = os.devnull
if patch_driver:
service_ = selenium.webdriver.chrome.service.Service(
executable_path=self.patcher.executable_path,
@ -342,7 +337,7 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
def _get_cdc_props(self):
cdc_props = []
try:
with suppress(Exception):
cdc_props = self.execute_script(
"""
let objectToInspect = window,
@ -355,8 +350,6 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
return result.filter(i => i.match(/^[a-z]{3}_[a-z]{22}_.*/i))
"""
)
except Exception:
pass
return cdc_props
def _hook_remove_cdc_props(self, cdc_props):
@ -427,50 +420,38 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
- Starts the chromedriver service that runs in the background.
- Recreates the session."""
if hasattr(self, "service"):
try:
with suppress(Exception):
self.service.stop()
except Exception:
pass
if isinstance(timeout, str):
if timeout.lower() == "breakpoint":
breakpoint() # To continue:
pass # Type "c" & press ENTER!
else:
time.sleep(timeout)
try:
with suppress(Exception):
self.service.start()
except Exception:
pass
time.sleep(0.012)
try:
with suppress(Exception):
self.start_session()
except Exception:
pass
time.sleep(0.012)
def disconnect(self):
"""Stops the chromedriver service that runs in the background.
To use driver methods again, you MUST call driver.connect()"""
if hasattr(self, "service"):
try:
with suppress(Exception):
self.service.stop()
except Exception:
pass
time.sleep(0.012)
def connect(self):
"""Starts the chromedriver service that runs in the background
and recreates the session."""
if hasattr(self, "service"):
try:
with suppress(Exception):
self.service.start()
except Exception:
pass
time.sleep(0.012)
try:
with suppress(Exception):
self.start_session()
except Exception:
pass
time.sleep(0.012)
def start_session(self, capabilities=None):
@ -496,12 +477,10 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
if hasattr(self, "service") and getattr(self.service, "process", None):
logger.debug("Stopping webdriver service")
self.service.stop()
try:
with suppress(Exception):
if self.reactor and isinstance(self.reactor, Reactor):
logger.debug("Shutting down Reactor")
self.reactor.event.set()
except Exception:
pass
if (
hasattr(self, "keep_user_data_dir")
and hasattr(self, "user_data_dir")
@ -530,18 +509,14 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
self.patcher = None
def __del__(self):
try:
with suppress(Exception):
if "win32" in sys.platform:
self.stop_client()
self.command_executor.close()
else:
super().quit()
except Exception:
pass
try:
with suppress(Exception):
self.quit()
except Exception:
pass
def __enter__(self):
return self

View File

@ -3,7 +3,10 @@ import os
import sys
import atexit
import logging
import platform
from contextlib import suppress
from subprocess import PIPE
from subprocess import Popen
CREATE_NEW_PROCESS_GROUP = 0x00000200
DETACHED_PROCESS = 0x00000008
@ -37,9 +40,6 @@ def start_detached(executable, *args):
def _start_detached(executable, *args, writer=None):
# Configure Launch
kwargs = {}
import platform
from subprocess import Popen
if platform.system() == "Windows":
kwargs.update(
creationflags=DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP
@ -58,11 +58,9 @@ def _cleanup():
import signal
for pid in REGISTERED:
try:
with suppress(Exception):
logging.getLogger(__name__).debug("cleaning up pid %d " % pid)
os.kill(pid, signal.SIGTERM)
except Exception:
pass
atexit.register(_cleanup)

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3
import json
import os
from contextlib import suppress
from selenium.webdriver.chromium.options import ChromiumOptions
@ -49,7 +50,7 @@ class ChromeOptions(ChromiumOptions):
undot_prefs, self._undot_key(key, value)
)
prefs_file = os.path.join(default_path, "Preferences")
try:
with suppress(Exception):
if os.path.exists(prefs_file):
with open(
prefs_file, encoding="utf-8", mode="r", errors="ignore"
@ -57,13 +58,9 @@ class ChromeOptions(ChromiumOptions):
undot_prefs = self._merge_nested(
json.load(f), undot_prefs
)
except Exception:
pass
try:
with suppress(Exception):
with open(prefs_file, encoding="utf-8", mode="w") as f:
json.dump(undot_prefs, f)
except Exception:
pass
# Remove experimental_options to avoid errors
del self._experimental_options["prefs"]
exclude_switches = self.experimental_options.get("excludeSwitches")

View File

@ -8,6 +8,7 @@ import string
import sys
import time
import zipfile
from contextlib import suppress
logger = logging.getLogger(__name__)
IS_POSIX = sys.platform.startswith(("darwin", "cygwin", "linux"))
@ -53,10 +54,8 @@ class Patcher(object):
self.executable_path = None
prefix = "undetected"
if not os.path.exists(self.data_path):
try:
with suppress(Exception):
os.makedirs(self.data_path, exist_ok=True)
except Exception:
pass
if not executable_path:
self.executable_path = os.path.join(
self.data_path, "_".join([prefix, self.exe_name])

View File

@ -1,5 +1,5 @@
"""Setup steps for installing SeleniumBase dependencies and plugins.
(Uses selenium 4.x and is compatible with Python 3.7+)"""
(Uses selenium 4.x and is compatible with Python 3.8+)"""
from setuptools import setup, find_packages # noqa: F401
import os
import sys
@ -47,7 +47,7 @@ if sys.argv[-1] == "publish":
print("\n*** Installing build: *** (Required for PyPI uploads)\n")
os.system("python -m pip install --upgrade 'build'")
print("\n*** Installing pkginfo: *** (Required for PyPI uploads)\n")
os.system("python -m pip install --upgrade 'pkginfo'")
os.system("python -m pip install 'pkginfo'")
print("\n*** Installing readme-renderer: *** (For PyPI uploads)\n")
os.system("python -m pip install --upgrade 'readme-renderer'")
print("\n*** Installing jaraco.classes: *** (For PyPI uploads)\n")
@ -79,12 +79,14 @@ setup(
long_description_content_type="text/markdown",
url="https://github.com/seleniumbase/SeleniumBase",
project_urls={
"Homepage": "https://github.com/seleniumbase/SeleniumBase",
"Changelog": "https://github.com/seleniumbase/SeleniumBase/releases",
"Download": "https://pypi.org/project/seleniumbase/#files",
"Gitter": "https://gitter.im/seleniumbase/SeleniumBase",
"Blog": "https://seleniumbase.com/",
"Discord": "https://discord.gg/EdhQTn3EyE",
"PyPI": "https://pypi.org/project/seleniumbase/",
"Source": "https://github.com/seleniumbase/SeleniumBase",
"Repository": "https://github.com/seleniumbase/SeleniumBase",
"Documentation": "https://seleniumbase.io/",
},
platforms=["Windows", "Linux", "Mac OS-X"],
@ -120,7 +122,6 @@ setup(
"Operating System :: POSIX :: Linux",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",