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_actions # noqa
from seleniumbase import page_utils # noqa from seleniumbase import page_utils # noqa
from seleniumbase import SB # 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.__version__ import __version__
from seleniumbase.common import decorators # noqa from seleniumbase.common import decorators # noqa
from seleniumbase.common import encryption # 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.core.browser_launcher import get_driver # noqa
from seleniumbase.fixtures import js_utils # noqa from seleniumbase.fixtures import js_utils # noqa
from seleniumbase.fixtures import page_actions # 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 pdb.DefaultConfig.sticky_by_default = True
colored_traceback.add_hook() colored_traceback.add_hook()
os.environ["SE_AVOID_STATS"] = "true" # Disable Selenium Manager stats 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): if sys.version_info >= (3, 10):
collections.Callable = collections.abc.Callable # Lifeline for nosetests collections.Callable = collections.abc.Callable # Lifeline for nosetests
del collections # Undo "import collections" / Simplify "dir(seleniumbase)" 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 headless2 (Use the new headless mode, which supports extensions.)
-D headed (Run tests in headed/GUI mode on Linux OS, where not default.) -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 (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 locale=LOCALE_CODE (Set the Language Locale Code for the web browser.)
-D pdb (Activate Post Mortem Debug Mode if a test fails.) -D pdb (Activate Post Mortem Debug Mode if a test fails.)
-D interval=SECONDS (The autoplay interval for presentations & tour steps) -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 rcs | -D reuse-class-session (Reuse session for tests in class/feature)
-D crumbs (Delete all cookies between tests reusing a session.) -D crumbs (Delete all cookies between tests reusing a session.)
-D disable-beforeunload (Disable the "beforeunload" event on Chrome.) -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 window-size=WIDTH,HEIGHT (Set the browser's starting window size.)
-D maximize (Start tests with the browser window maximized.) -D maximize (Start tests with the browser window maximized.)
-D screenshot (Save a screenshot at the end of each test.) -D screenshot (Save a screenshot at the end of each test.)
@ -104,6 +106,7 @@ import colorama
import os import os
import re import re
import sys import sys
from contextlib import suppress
from seleniumbase import config as sb_config from seleniumbase import config as sb_config
from seleniumbase.config import settings from seleniumbase.config import settings
from seleniumbase.core import download_helper from seleniumbase.core import download_helper
@ -145,6 +148,7 @@ def get_configured_sb(context):
sb.headless_active = False sb.headless_active = False
sb.headed = False sb.headed = False
sb.xvfb = False sb.xvfb = False
sb.xvfb_metrics = None
sb.start_page = None sb.start_page = None
sb.locale_code = None sb.locale_code = None
sb.pdb_option = False sb.pdb_option = False
@ -193,6 +197,7 @@ def get_configured_sb(context):
sb._disable_beforeunload = False sb._disable_beforeunload = False
sb.visual_baseline = False sb.visual_baseline = False
sb.use_wire = False sb.use_wire = False
sb.window_position = None
sb.window_size = None sb.window_size = None
sb.maximize_option = False sb.maximize_option = False
sb.is_context_manager = False sb.is_context_manager = False
@ -302,6 +307,13 @@ def get_configured_sb(context):
if low_key == "xvfb": if low_key == "xvfb":
sb.xvfb = True sb.xvfb = True
continue 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 # Handle: -D start-page=URL / start_page=URL / url=URL
if low_key in ["start-page", "start_page", "url"]: if low_key in ["start-page", "start_page", "url"]:
start_page = userdata[key] start_page = userdata[key]
@ -601,6 +613,13 @@ def get_configured_sb(context):
if low_key == "wire": if low_key == "wire":
sb.use_wire = True sb.use_wire = True
continue 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 # Handle: -D window-size=Width,Height / window_size=Width,Height
if low_key in ["window-size", "window_size"]: if low_key in ["window-size", "window_size"]:
window_size = userdata[key] window_size = userdata[key]
@ -904,6 +923,29 @@ def get_configured_sb(context):
else: else:
sb.enable_ws = False sb.enable_ws = False
sb.disable_ws = True 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: if sb.window_size:
window_size = sb.window_size window_size = sb.window_size
if window_size.count(",") != 1: if window_size.count(",") != 1:
@ -938,9 +980,11 @@ def get_configured_sb(context):
sb_config.is_pytest = False sb_config.is_pytest = False
sb_config.is_nosetest = False sb_config.is_nosetest = False
sb_config.is_context_manager = False sb_config.is_context_manager = False
sb_config.window_position = sb.window_position
sb_config.window_size = sb.window_size sb_config.window_size = sb.window_size
sb_config.maximize_option = sb.maximize_option sb_config.maximize_option = sb.maximize_option
sb_config.xvfb = sb.xvfb sb_config.xvfb = sb.xvfb
sb_config.xvfb_metrics = sb.xvfb_metrics
sb_config.reuse_class_session = sb._reuse_class_session sb_config.reuse_class_session = sb._reuse_class_session
sb_config.save_screenshot = sb.save_screenshot_after_test sb_config.save_screenshot = sb.save_screenshot_after_test
sb_config.no_screenshot = sb.no_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 sb_config.item_count_untested = sb_config.item_count
dash_path = os.path.join(os.getcwd(), "dashboard.html") dash_path = os.path.join(os.getcwd(), "dashboard.html")
star_len = len("Dashboard: ") + len(dash_path) star_len = len("Dashboard: ") + len(dash_path)
try: with suppress(Exception):
terminal_size = os.get_terminal_size().columns terminal_size = os.get_terminal_size().columns
if terminal_size > 30 and star_len > terminal_size: if terminal_size > 30 and star_len > terminal_size:
star_len = terminal_size star_len = terminal_size
except Exception:
pass
stars = "*" * star_len stars = "*" * star_len
c1 = "" c1 = ""
cr = "" cr = ""
@ -1263,7 +1305,7 @@ def _perform_behave_unconfigure_():
def do_final_driver_cleanup_as_needed(): def do_final_driver_cleanup_as_needed():
try: with suppress(Exception):
if hasattr(sb_config, "last_driver") and sb_config.last_driver: if hasattr(sb_config, "last_driver") and sb_config.last_driver:
if ( if (
not is_windows not is_windows
@ -1271,8 +1313,6 @@ def do_final_driver_cleanup_as_needed():
or sb_config.last_driver.service.process or sb_config.last_driver.service.process
): ):
sb_config.last_driver.quit() sb_config.last_driver.quit()
except Exception:
pass
def _perform_behave_terminal_summary_(): def _perform_behave_terminal_summary_():
@ -1281,12 +1321,10 @@ def _perform_behave_terminal_summary_():
) )
dash_path = os.path.join(os.getcwd(), "dashboard.html") dash_path = os.path.join(os.getcwd(), "dashboard.html")
equals_len = len("Dashboard: ") + len(dash_path) equals_len = len("Dashboard: ") + len(dash_path)
try: with suppress(Exception):
terminal_size = os.get_terminal_size().columns terminal_size = os.get_terminal_size().columns
if terminal_size > 30 and equals_len > terminal_size: if terminal_size > 30 and equals_len > terminal_size:
equals_len = terminal_size equals_len = terminal_size
except Exception:
pass
equals = "=" * (equals_len + 2) equals = "=" * (equals_len + 2)
c2 = "" c2 = ""
cr = "" cr = ""

View File

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

View File

@ -16,16 +16,16 @@ Output:
import colorama import colorama
import subprocess import subprocess
import sys 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]) current_version = ".".join(str(ver) for ver in sys.version_info[:3])
raise Exception( 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 "\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): def set_colors(use_colors):

View File

@ -20,17 +20,17 @@ import colorama
import os import os
import subprocess import subprocess
import sys 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]) current_version = ".".join(str(ver) for ver in sys.version_info[:3])
raise Exception( 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 "\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): def set_colors(use_colors):

View File

@ -21,16 +21,16 @@ import colorama
import os import os
import subprocess import subprocess
import sys 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]) current_version = ".".join(str(ver) for ver in sys.version_info[:3])
raise Exception( 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 "\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): def set_colors(use_colors):

View File

@ -18,23 +18,23 @@ import colorama
import os import os
import subprocess import subprocess
import sys import sys
import tkinter as tk
from seleniumbase import config as sb_config from seleniumbase import config as sb_config
from seleniumbase.fixtures import page_utils from seleniumbase.fixtures import page_utils
from seleniumbase.fixtures import shared_utils from seleniumbase.fixtures import shared_utils
from tkinter import messagebox
sb_config.rec_subprocess_p = None sb_config.rec_subprocess_p = None
sb_config.rec_subprocess_used = False sb_config.rec_subprocess_used = False
sys_executable = sys.executable sys_executable = sys.executable
if " " in sys_executable: if " " in sys_executable:
sys_executable = "python" 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]) current_version = ".".join(str(ver) for ver in sys.version_info[:3])
raise Exception( 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 "\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): def set_colors(use_colors):

View File

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

View File

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

View File

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

View File

@ -1,4 +1,5 @@
"""Add new methods to extend the driver""" """Add new methods to extend the driver"""
from contextlib import suppress
from selenium.webdriver.remote.webelement import WebElement from selenium.webdriver.remote.webelement import WebElement
from seleniumbase.fixtures import js_utils from seleniumbase.fixtures import js_utils
from seleniumbase.fixtures import page_actions from seleniumbase.fixtures import page_actions
@ -36,10 +37,8 @@ class DriverMethods():
selector, by = page_utils.swap_selector_and_by_if_reversed( selector, by = page_utils.swap_selector_and_by_if_reversed(
selector, by selector, by
) )
try: with suppress(Exception):
return self.driver.default_find_element(by=by, value=selector) return self.driver.default_find_element(by=by, value=selector)
except Exception:
pass
raise Exception('No such Element: {%s} (by="%s")!' % (selector, by)) raise Exception('No such Element: {%s} (by="%s")!' % (selector, by))
def get_attribute(self, selector, attribute, by="css selector"): 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 re
import requests import requests
import time import time
from contextlib import suppress
from selenium.common.exceptions import NoSuchElementException from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import WebDriverException from selenium.common.exceptions import WebDriverException
from selenium.webdriver.common.by import By 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): def wait_for_angularjs(driver, timeout=settings.LARGE_TIMEOUT, **kwargs):
if hasattr(settings, "SKIP_JS_WAITS") and settings.SKIP_JS_WAITS: if hasattr(settings, "SKIP_JS_WAITS") and settings.SKIP_JS_WAITS:
return return
try: with suppress(Exception):
# This closes pop-up alerts # This closes pop-up alerts
driver.execute_script("") driver.execute_script("")
except Exception:
pass
if ( if (
(hasattr(driver, "_is_using_uc") and driver._is_using_uc) (hasattr(driver, "_is_using_uc") and driver._is_using_uc)
or not settings.WAIT_FOR_ANGULARJS or not settings.WAIT_FOR_ANGULARJS
@ -92,10 +91,8 @@ def wait_for_angularjs(driver, timeout=settings.LARGE_TIMEOUT, **kwargs):
"handler": handler, "handler": handler,
"suffix": suffix, "suffix": suffix,
} }
try: with suppress(Exception):
execute_async_script(driver, script, timeout=timeout) execute_async_script(driver, script, timeout=timeout)
except Exception:
pass
def convert_to_css_selector(selector, by=By.CSS_SELECTOR): 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): def activate_jquery(driver):
# If "jQuery is not defined" on a website, use this method to activate it. # 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. # 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. # Let's first find out if jQuery is already defined.
driver.execute_script("jQuery('html');") driver.execute_script("jQuery('html');")
# Since that command worked, jQuery is defined. Let's return. # Since that command worked, jQuery is defined. Let's return.
return return
except Exception: # jQuery is not defined. It will be loaded in the next part.
# jQuery is not currently defined. Let's proceed by defining it.
pass
jquery_js = constants.JQuery.MIN_JS jquery_js = constants.JQuery.MIN_JS
add_js_link(driver, jquery_js) add_js_link(driver, jquery_js)
for x in range(36): 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=""): def highlight_with_js(driver, selector, loops=4, o_bs=""):
try: with suppress(Exception):
# This closes any pop-up alerts # This closes any pop-up alerts
driver.execute_script("") driver.execute_script("")
except Exception:
pass
if selector == "html": if selector == "html":
selector = "body" selector = "body"
selector_no_spaces = selector.replace(" ", "") 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=""): def highlight_element_with_js(driver, element, loops=4, o_bs=""):
try: with suppress(Exception):
# This closes any pop-up alerts # This closes any pop-up alerts
driver.execute_script("") driver.execute_script("")
except Exception:
pass
script = ( script = (
"""arguments[0].style.boxShadow = """arguments[0].style.boxShadow =
'0px 0px 6px 6px rgba(128, 128, 128, 0.5)';""" '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=""): def highlight_with_jquery(driver, selector, loops=4, o_bs=""):
try: with suppress(Exception):
# This closes any pop-up alerts # This closes any pop-up alerts
driver.execute_script("") driver.execute_script("")
except Exception:
pass
if selector == "html": if selector == "html":
selector = "body" selector = "body"
selector_no_spaces = selector.replace(" ", "") selector_no_spaces = selector.replace(" ", "")
@ -908,11 +897,9 @@ def set_messenger_theme(
time.sleep(0.03) time.sleep(0.03)
activate_messenger(driver) activate_messenger(driver)
time.sleep(0.15) time.sleep(0.15)
try: with suppress(Exception):
driver.execute_script(msg_style) driver.execute_script(msg_style)
time.sleep(0.02) time.sleep(0.02)
except Exception:
pass
time.sleep(0.05) time.sleep(0.05)
@ -949,7 +936,7 @@ def post_messenger_success_message(driver, message, msg_dur=None):
if not msg_dur: if not msg_dur:
msg_dur = settings.DEFAULT_MESSAGE_DURATION msg_dur = settings.DEFAULT_MESSAGE_DURATION
msg_dur = float(msg_dur) msg_dur = float(msg_dur)
try: with suppress(Exception):
theme = "future" theme = "future"
location = "bottom_right" location = "bottom_right"
if hasattr(sb_config, "mobile_emulator") and sb_config.mobile_emulator: 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) set_messenger_theme(driver, theme=theme, location=location)
post_message(driver, message, msg_dur, style="success") post_message(driver, message, msg_dur, style="success")
time.sleep(msg_dur + 0.07) time.sleep(msg_dur + 0.07)
except Exception:
pass
def post_messenger_error_message(driver, message, msg_dur=None): def post_messenger_error_message(driver, message, msg_dur=None):
if not msg_dur: if not msg_dur:
msg_dur = settings.DEFAULT_MESSAGE_DURATION msg_dur = settings.DEFAULT_MESSAGE_DURATION
msg_dur = float(msg_dur) msg_dur = float(msg_dur)
try: with suppress(Exception):
set_messenger_theme(driver, theme="block", location="top_center") set_messenger_theme(driver, theme="block", location="top_center")
post_message(driver, message, msg_dur, style="error") post_message(driver, message, msg_dur, style="error")
time.sleep(msg_dur + 0.07) time.sleep(msg_dur + 0.07)
except Exception:
pass
def highlight_with_js_2(driver, message, selector, o_bs, msg_dur): def highlight_with_js_2(driver, message, selector, o_bs, msg_dur):
try: with suppress(Exception):
# This closes any pop-up alerts # This closes any pop-up alerts
driver.execute_script("") driver.execute_script("")
except Exception:
pass
if selector == "html": if selector == "html":
selector = "body" selector = "body"
selector_no_spaces = selector.replace(" ", "") selector_no_spaces = selector.replace(" ", "")
@ -991,11 +972,9 @@ def highlight_with_js_2(driver, message, selector, o_bs, msg_dur):
else: else:
early_exit = True # Changing the box-shadow changes the selector early_exit = True # Changing the box-shadow changes the selector
if early_exit: if early_exit:
try: with suppress(Exception):
activate_jquery(driver) activate_jquery(driver)
post_messenger_success_message(driver, message, msg_dur) post_messenger_success_message(driver, message, msg_dur)
except Exception:
pass
return return
script = ( script = (
"""document.querySelector('%s').style.boxShadow = """document.querySelector('%s').style.boxShadow =
@ -1047,11 +1026,9 @@ def highlight_with_js_2(driver, message, selector, o_bs, msg_dur):
except Exception: except Exception:
return return
time.sleep(0.0181) time.sleep(0.0181)
try: with suppress(Exception):
activate_jquery(driver) activate_jquery(driver)
post_messenger_success_message(driver, message, msg_dur) post_messenger_success_message(driver, message, msg_dur)
except Exception:
pass
script = """document.querySelector('%s').style.boxShadow = '%s';""" % ( script = """document.querySelector('%s').style.boxShadow = '%s';""" % (
selector, selector,
o_bs, 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): def highlight_element_with_js_2(driver, message, element, o_bs, msg_dur):
try: with suppress(Exception):
# This closes any pop-up alerts # This closes any pop-up alerts
driver.execute_script("") driver.execute_script("")
except Exception:
pass
script = ( script = (
"""arguments[0].style.boxShadow = """arguments[0].style.boxShadow =
'0px 0px 6px 6px rgba(128, 128, 128, 0.5)';""" '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: except Exception:
return return
time.sleep(0.0181) time.sleep(0.0181)
try: with suppress(Exception):
activate_jquery(driver) activate_jquery(driver)
post_messenger_success_message(driver, message, msg_dur) post_messenger_success_message(driver, message, msg_dur)
except Exception:
pass
script = """arguments[0].style.boxShadow = '%s';""" % (o_bs) script = """arguments[0].style.boxShadow = '%s';""" % (o_bs)
try: try:
driver.execute_script(script, element) driver.execute_script(script, element)
@ -1138,11 +1111,9 @@ def highlight_with_jquery_2(driver, message, selector, o_bs, msg_dur):
else: else:
early_exit = True # Changing the box-shadow changes the selector early_exit = True # Changing the box-shadow changes the selector
if early_exit: if early_exit:
try: with suppress(Exception):
activate_jquery(driver) activate_jquery(driver)
post_messenger_success_message(driver, message, msg_dur) post_messenger_success_message(driver, message, msg_dur)
except Exception:
pass
return return
script = ( script = (
"""jQuery('%s').css('box-shadow', """jQuery('%s').css('box-shadow',
@ -1195,11 +1166,9 @@ def highlight_with_jquery_2(driver, message, selector, o_bs, msg_dur):
return return
time.sleep(0.0181) time.sleep(0.0181)
try: with suppress(Exception):
activate_jquery(driver) activate_jquery(driver)
post_messenger_success_message(driver, message, msg_dur) post_messenger_success_message(driver, message, msg_dur)
except Exception:
pass
script = """jQuery('%s').css('box-shadow', '%s');""" % (selector, o_bs) script = """jQuery('%s').css('box-shadow', '%s');""" % (selector, o_bs)
try: try:
@ -1484,12 +1453,10 @@ def get_drag_and_drop_with_offset_script(selector, x, y):
def clear_out_console_logs(driver): def clear_out_console_logs(driver):
try: with suppress(Exception):
# Clear out the current page log before navigating to a new page # Clear out the current page log before navigating to a new page
# (To make sure that assert_no_js_errors() uses current results) # (To make sure that assert_no_js_errors() uses current results)
driver.get_log("browser") driver.get_log("browser")
except Exception:
pass
def _jq_format(code): def _jq_format(code):

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@ Usage --> ``with DriverContext() as driver:``
Example --> Example -->
``` ```python
from seleniumbase import DriverContext from seleniumbase import DriverContext
with DriverContext() as driver: with DriverContext() as driver:
@ -27,7 +27,7 @@ Usage --> ``driver = Driver()``
Example --> Example -->
``` ```python
from seleniumbase import Driver from seleniumbase import Driver
driver = Driver() driver = Driver()
@ -75,7 +75,7 @@ def Driver(
proxy=None, # Use proxy. Format: "SERVER:PORT" or "USER:PASS@SERVER:PORT". proxy=None, # Use proxy. Format: "SERVER:PORT" or "USER:PASS@SERVER:PORT".
proxy_bypass_list=None, # Skip proxy when using the listed domains. proxy_bypass_list=None, # Skip proxy when using the listed domains.
proxy_pac_url=None, # Use PAC file. (Format: URL or USERNAME:PASSWORD@URL) 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. agent=None, # Modify the web browser's User-Agent string.
cap_file=None, # The desired capabilities to use with a Selenium Grid. cap_file=None, # The desired capabilities to use with a Selenium Grid.
cap_string=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". wire=None, # Shortcut / Duplicate of "use_wire".
pls=None, # Shortcut / Duplicate of "page_load_strategy". 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 import config as sb_config
from seleniumbase.config import settings
from seleniumbase.fixtures import constants from seleniumbase.fixtures import constants
from seleniumbase.fixtures import shared_utils from seleniumbase.fixtures import shared_utils

View File

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

View File

@ -7,7 +7,7 @@ Usage --> ``with SB() as sb:``
Example --> Example -->
``` ```python
from seleniumbase import SB from seleniumbase import SB
with SB() as sb: # Many args! Eg. SB(browser="edge") 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=None, # Use proxy. Format: "SERVER:PORT" or "USER:PASS@SERVER:PORT".
proxy_bypass_list=None, # Skip proxy when using the listed domains. proxy_bypass_list=None, # Skip proxy when using the listed domains.
proxy_pac_url=None, # Use PAC file. (Format: URL or USERNAME:PASSWORD@URL) 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. agent=None, # Modify the web browser's User-Agent string.
cap_file=None, # The desired capabilities to use with a Selenium Grid. cap_file=None, # The desired capabilities to use with a Selenium Grid.
cap_string=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.) interval=None, # SECONDS (Autoplay interval for SB Slides & Tour steps.)
time_limit=None, # SECONDS (Safely fail tests that exceed the time limit.) 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 os
import sys import sys
import time import time

View File

@ -1,5 +1,6 @@
"""Selenium Plugin for SeleniumBase tests that run with pynose / nosetests""" """Selenium Plugin for SeleniumBase tests that run with pynose / nosetests"""
import sys import sys
from contextlib import suppress
from nose.plugins import Plugin from nose.plugins import Plugin
from seleniumbase import config as sb_config from seleniumbase import config as sb_config
from seleniumbase.config import settings from seleniumbase.config import settings
@ -1308,7 +1309,7 @@ class SeleniumBrowser(Plugin):
): ):
width = settings.HEADLESS_START_WIDTH width = settings.HEADLESS_START_WIDTH
height = settings.HEADLESS_START_HEIGHT height = settings.HEADLESS_START_HEIGHT
try: with suppress(Exception):
from sbvirtualdisplay import Display from sbvirtualdisplay import Display
self._xvfb_display = Display(visible=0, size=(width, height)) self._xvfb_display = Display(visible=0, size=(width, height))
@ -1316,8 +1317,6 @@ class SeleniumBrowser(Plugin):
sb_config._virtual_display = self._xvfb_display sb_config._virtual_display = self._xvfb_display
self.headless_active = True self.headless_active = True
sb_config.headless_active = True sb_config.headless_active = True
except Exception:
pass
sb_config._is_timeout_changed = False sb_config._is_timeout_changed = False
sb_config._SMALL_TIMEOUT = settings.SMALL_TIMEOUT sb_config._SMALL_TIMEOUT = settings.SMALL_TIMEOUT
sb_config._LARGE_TIMEOUT = settings.LARGE_TIMEOUT sb_config._LARGE_TIMEOUT = settings.LARGE_TIMEOUT
@ -1350,7 +1349,7 @@ class SeleniumBrowser(Plugin):
pass pass
except Exception: except Exception:
pass pass
try: with suppress(Exception):
if ( if (
hasattr(self, "_xvfb_display") hasattr(self, "_xvfb_display")
and self._xvfb_display and self._xvfb_display
@ -1367,5 +1366,3 @@ class SeleniumBrowser(Plugin):
): ):
sb_config._virtual_display.stop() sb_config._virtual_display.stop()
sb_config._virtual_display = None 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.chrome.webdriver
import selenium.webdriver.common.service import selenium.webdriver.common.service
import selenium.webdriver.remote.command import selenium.webdriver.remote.command
from contextlib import suppress
from .cdp import CDP from .cdp import CDP
from .cdp import PageElement from .cdp import PageElement
from .dprocess import start_detached 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. # Create a temporary folder for the user-data profile.
options.add_argument(arg) options.add_argument(arg)
if not language: if not language:
try: with suppress(Exception):
import locale import locale
language = locale.getlocale()[0].replace("_", "-") language = locale.getlocale()[0].replace("_", "-")
except Exception:
pass
if ( if (
not language not language
or "English" in language or "English" in language
@ -242,7 +241,7 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
) )
if hasattr(options, 'handle_prefs'): if hasattr(options, 'handle_prefs'):
options.handle_prefs(user_data_dir) options.handle_prefs(user_data_dir)
try: with suppress(Exception):
import json import json
with open( with open(
os.path.join( os.path.join(
@ -263,8 +262,6 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
fs.seek(0, 0) fs.seek(0, 0)
fs.truncate() fs.truncate()
json.dump(config, fs) json.dump(config, fs)
except Exception:
pass
creationflags = 0 creationflags = 0
if "win32" in sys.platform: if "win32" in sys.platform:
creationflags = subprocess.CREATE_NO_WINDOW creationflags = subprocess.CREATE_NO_WINDOW
@ -293,8 +290,6 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
self.browser_pid = browser.pid self.browser_pid = browser.pid
service_ = None service_ = None
log_output = subprocess.PIPE log_output = subprocess.PIPE
if sys.version_info < (3, 8):
log_output = os.devnull
if patch_driver: if patch_driver:
service_ = selenium.webdriver.chrome.service.Service( service_ = selenium.webdriver.chrome.service.Service(
executable_path=self.patcher.executable_path, executable_path=self.patcher.executable_path,
@ -342,7 +337,7 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
def _get_cdc_props(self): def _get_cdc_props(self):
cdc_props = [] cdc_props = []
try: with suppress(Exception):
cdc_props = self.execute_script( cdc_props = self.execute_script(
""" """
let objectToInspect = window, 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)) return result.filter(i => i.match(/^[a-z]{3}_[a-z]{22}_.*/i))
""" """
) )
except Exception:
pass
return cdc_props return cdc_props
def _hook_remove_cdc_props(self, 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. - Starts the chromedriver service that runs in the background.
- Recreates the session.""" - Recreates the session."""
if hasattr(self, "service"): if hasattr(self, "service"):
try: with suppress(Exception):
self.service.stop() self.service.stop()
except Exception:
pass
if isinstance(timeout, str): if isinstance(timeout, str):
if timeout.lower() == "breakpoint": if timeout.lower() == "breakpoint":
breakpoint() # To continue: breakpoint() # To continue:
pass # Type "c" & press ENTER! pass # Type "c" & press ENTER!
else: else:
time.sleep(timeout) time.sleep(timeout)
try: with suppress(Exception):
self.service.start() self.service.start()
except Exception:
pass
time.sleep(0.012) time.sleep(0.012)
try: with suppress(Exception):
self.start_session() self.start_session()
except Exception:
pass
time.sleep(0.012) time.sleep(0.012)
def disconnect(self): def disconnect(self):
"""Stops the chromedriver service that runs in the background. """Stops the chromedriver service that runs in the background.
To use driver methods again, you MUST call driver.connect()""" To use driver methods again, you MUST call driver.connect()"""
if hasattr(self, "service"): if hasattr(self, "service"):
try: with suppress(Exception):
self.service.stop() self.service.stop()
except Exception:
pass
time.sleep(0.012) time.sleep(0.012)
def connect(self): def connect(self):
"""Starts the chromedriver service that runs in the background """Starts the chromedriver service that runs in the background
and recreates the session.""" and recreates the session."""
if hasattr(self, "service"): if hasattr(self, "service"):
try: with suppress(Exception):
self.service.start() self.service.start()
except Exception:
pass
time.sleep(0.012) time.sleep(0.012)
try: with suppress(Exception):
self.start_session() self.start_session()
except Exception:
pass
time.sleep(0.012) time.sleep(0.012)
def start_session(self, capabilities=None): 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): if hasattr(self, "service") and getattr(self.service, "process", None):
logger.debug("Stopping webdriver service") logger.debug("Stopping webdriver service")
self.service.stop() self.service.stop()
try: with suppress(Exception):
if self.reactor and isinstance(self.reactor, Reactor): if self.reactor and isinstance(self.reactor, Reactor):
logger.debug("Shutting down Reactor") logger.debug("Shutting down Reactor")
self.reactor.event.set() self.reactor.event.set()
except Exception:
pass
if ( if (
hasattr(self, "keep_user_data_dir") hasattr(self, "keep_user_data_dir")
and hasattr(self, "user_data_dir") and hasattr(self, "user_data_dir")
@ -530,18 +509,14 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
self.patcher = None self.patcher = None
def __del__(self): def __del__(self):
try: with suppress(Exception):
if "win32" in sys.platform: if "win32" in sys.platform:
self.stop_client() self.stop_client()
self.command_executor.close() self.command_executor.close()
else: else:
super().quit() super().quit()
except Exception: with suppress(Exception):
pass
try:
self.quit() self.quit()
except Exception:
pass
def __enter__(self): def __enter__(self):
return self return self

View File

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

View File

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

View File

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

View File

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