Merge pull request #3124 from seleniumbase/refactor-uc-mode-and-js-waits
Refactor UC Mode and JS waits
This commit is contained in:
commit
6a057913b4
|
@ -651,6 +651,7 @@ pytest test_coffee_cart.py --trace
|
|||
--binary-location=PATH # (Set path of the Chromium browser binary to use.)
|
||||
--driver-version=VER # (Set the chromedriver or uc_driver version to use.)
|
||||
--sjw # (Skip JS Waits for readyState to be "complete" or Angular to load.)
|
||||
--wfa # (Wait for AngularJS to be done loading after specific web actions.)
|
||||
--pls=PLS # (Set pageLoadStrategy on Chrome: "normal", "eager", or "none".)
|
||||
--headless # (Run tests in headless mode. The default arg on Linux OS.)
|
||||
--headless2 # (Use the new headless mode, which supports extensions.)
|
||||
|
|
|
@ -48,7 +48,7 @@ WAIT_FOR_RSC_ON_PAGE_LOADS = True
|
|||
# Called after self.click(selector), NOT element.click()
|
||||
WAIT_FOR_RSC_ON_CLICKS = False
|
||||
# Wait for AngularJS calls to complete after various browser actions.
|
||||
WAIT_FOR_ANGULARJS = True
|
||||
WAIT_FOR_ANGULARJS = False
|
||||
# Skip ALL calls to wait_for_ready_state_complete() and wait_for_angularjs().
|
||||
SKIP_JS_WAITS = False
|
||||
|
||||
|
|
|
@ -131,10 +131,11 @@ class HackTests(BaseCase):
|
|||
self.highlight("section.crayons-card", loops=7, scroll=False)
|
||||
|
||||
self.open("https://azure.microsoft.com/en-us/services/playfab/")
|
||||
self.remove_elements('div[role="dialog"]')
|
||||
self.set_text_content("h1", aybabtu)
|
||||
self.set_text_content('a[aria-label*="Try Azure"]', ayb)
|
||||
self.set_text_content('a[aria-label*="Sign in to"]', abtu)
|
||||
self.remove_elements('div[role="dialog"]')
|
||||
self.remove_elements('[aria-label*="Microsoft Survey"]')
|
||||
self.highlight("h1", loops=6, scroll=False)
|
||||
self.highlight('a[aria-label*="Try Azure"]', loops=4, scroll=False)
|
||||
self.highlight('a[aria-label*="Sign in to"]', loops=6, scroll=False)
|
||||
|
@ -308,15 +309,6 @@ class HackTests(BaseCase):
|
|||
self.highlight("h1", loops=6, scroll=False)
|
||||
self.highlight("input#search", loops=8, scroll=False)
|
||||
|
||||
self.open("https://www.atlassian.com/software/jira")
|
||||
self.set_text_content('a[href*="jira/pricing"]', ayb)
|
||||
self.set_text_content('a[href*="jira/enterprise"]', abtu)
|
||||
self.set_text_content('a[href="/software/jira/features"]', "")
|
||||
self.set_text_content("h1", aybabtu)
|
||||
self.highlight('a[href*="jira/pricing"]', loops=5, scroll=False)
|
||||
self.highlight('a[href*="jira/enterprise"]', loops=6, scroll=False)
|
||||
self.highlight("h1", loops=8, scroll=False)
|
||||
|
||||
self.open("https://status.iboss.com/ibcloud/app/cloudStatus.html")
|
||||
self.wait_for_element_clickable('div[translate*="cloudStatus"]')
|
||||
self.set_text_content('div[translate*="cloudStatus"]', ayb)
|
||||
|
|
|
@ -7,9 +7,9 @@ with SB(uc=True, test=True, incognito=True, locale_code="en") as sb:
|
|||
sb.uc_open_with_reconnect(url) # The bot-check is later
|
||||
sb.type(input_field, "github.com/seleniumbase/SeleniumBase")
|
||||
sb.reconnect(0.1)
|
||||
sb.uc_click(submit_button, reconnect_time=4)
|
||||
sb.uc_click(submit_button, reconnect_time=3.25)
|
||||
sb.uc_gui_click_captcha()
|
||||
sb.wait_for_text_not_visible("Checking", timeout=12)
|
||||
sb.wait_for_text_not_visible("Checking", timeout=11.5)
|
||||
sb.highlight('p:contains("github.com/seleniumbase/SeleniumBase")')
|
||||
sb.highlight('a:contains("Top 100 backlinks")')
|
||||
sb.set_messenger_theme(location="bottom_center")
|
||||
|
|
|
@ -2,6 +2,7 @@ from seleniumbase import SB
|
|||
|
||||
with SB(uc=True, test=True) as sb:
|
||||
sb.uc_open_with_reconnect("nopecha.com/demo/turnstile", 3.2)
|
||||
sb.uc_gui_click_captcha("#example-container0")
|
||||
if sb.is_element_visible("#example-container0"):
|
||||
sb.uc_gui_click_captcha("#example-container0")
|
||||
sb.uc_gui_click_captcha("#example-container5")
|
||||
sb.sleep(3)
|
||||
|
|
|
@ -39,7 +39,7 @@ class TestGeolocation(BaseCase):
|
|||
)
|
||||
self.open("https://www.openstreetmap.org/")
|
||||
self.click("span.geolocate")
|
||||
self.assert_url_contains("48.87645/2.26340")
|
||||
self.assert_url_contains("48.876450/2.263400")
|
||||
self.save_screenshot_to_logs()
|
||||
if self.headed:
|
||||
self.sleep(4)
|
||||
|
|
|
@ -142,6 +142,7 @@ pytest my_first_test.py --settings-file=custom_settings.py
|
|||
--binary-location=PATH # (Set path of the Chromium browser binary to use.)
|
||||
--driver-version=VER # (Set the chromedriver or uc_driver version to use.)
|
||||
--sjw # (Skip JS Waits for readyState to be "complete" or Angular to load.)
|
||||
--wfa # (Wait for AngularJS to be done loading after specific web actions.)
|
||||
--pls=PLS # (Set pageLoadStrategy on Chrome: "normal", "eager", or "none".)
|
||||
--headless # (Run tests in headless mode. The default arg on Linux OS.)
|
||||
--headless2 # (Use the new headless mode, which supports extensions.)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# mkdocs dependencies for generating the seleniumbase.io website
|
||||
# Minimum Python version: 3.8 (for generating docs only)
|
||||
|
||||
regex>=2024.7.24
|
||||
regex>=2024.9.11
|
||||
pymdown-extensions>=10.9
|
||||
pipdeptree>=2.23.3
|
||||
python-dateutil>=2.8.2
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
# seleniumbase package
|
||||
__version__ = "4.30.4"
|
||||
__version__ = "4.30.5"
|
||||
|
|
|
@ -42,6 +42,7 @@ behave -D agent="User Agent String" -D demo
|
|||
-D binary-location=PATH (Set path of the Chromium browser binary to use.)
|
||||
-D driver-version=VER (Set the chromedriver or uc_driver version to use.)
|
||||
-D sjw (Skip JS Waits for readyState to be "complete" or Angular to load.)
|
||||
-D wfa (Wait for AngularJS to be done loading after specific web actions.)
|
||||
-D pls=PLS (Set pageLoadStrategy on Chrome: "normal", "eager", or "none".)
|
||||
-D headless (Run tests in headless mode. The default arg on Linux OS.)
|
||||
-D headless2 (Use the new headless mode, which supports extensions.)
|
||||
|
@ -588,6 +589,10 @@ def get_configured_sb(context):
|
|||
if low_key in ["sjw", "skip-js-waits", "skip_js_waits"]:
|
||||
settings.SKIP_JS_WAITS = True
|
||||
continue
|
||||
# Handle: -D wfa / wait-for-angularjs / wait_for_angularjs
|
||||
if low_key in ["wfa", "wait-for-angularjs", "wait_for_angularjs"]:
|
||||
settings.WAIT_FOR_ANGULARJS = True
|
||||
continue
|
||||
# Handle: -D visual-baseline / visual_baseline
|
||||
if low_key in ["visual-baseline", "visual_baseline"]:
|
||||
sb.visual_baseline = True
|
||||
|
@ -889,6 +894,16 @@ def get_configured_sb(context):
|
|||
# If the port is "443", the protocol is "https"
|
||||
if str(sb.port) == "443":
|
||||
sb.protocol = "https"
|
||||
if (
|
||||
(sb.enable_ws is None and sb.disable_ws is None)
|
||||
or (sb.disable_ws is not None and not sb.disable_ws)
|
||||
or (sb.enable_ws is not None and sb.enable_ws)
|
||||
):
|
||||
sb.enable_ws = True
|
||||
sb.disable_ws = False
|
||||
else:
|
||||
sb.enable_ws = False
|
||||
sb.disable_ws = True
|
||||
if sb.window_size:
|
||||
window_size = sb.window_size
|
||||
if window_size.count(",") != 1:
|
||||
|
|
|
@ -75,7 +75,7 @@ WAIT_FOR_RSC_ON_PAGE_LOADS = True
|
|||
# Called after self.click(selector), NOT element.click()
|
||||
WAIT_FOR_RSC_ON_CLICKS = False
|
||||
# Wait for AngularJS calls to complete after various browser actions.
|
||||
WAIT_FOR_ANGULARJS = True
|
||||
WAIT_FOR_ANGULARJS = False
|
||||
# Skip all calls to wait_for_ready_state_complete() and wait_for_angularjs().
|
||||
SKIP_JS_WAITS = False
|
||||
|
||||
|
|
|
@ -982,16 +982,19 @@ def _uc_gui_click_captcha(
|
|||
_uc_gui_click_x_y(driver, x, y, timeframe=0.95)
|
||||
except Exception:
|
||||
pass
|
||||
reconnect_time = (float(constants.UC.RECONNECT_TIME) / 2.0) + 0.5
|
||||
reconnect_time = (float(constants.UC.RECONNECT_TIME) / 2.0) + 0.6
|
||||
if IS_LINUX:
|
||||
reconnect_time = constants.UC.RECONNECT_TIME + 0.2
|
||||
if not x or not y:
|
||||
reconnect_time = 1 # Make it quick (it already failed)
|
||||
driver.reconnect(reconnect_time)
|
||||
if blind or (IS_LINUX and "Just a moment" in driver.title):
|
||||
retry = True
|
||||
caught = False
|
||||
if driver.is_element_present(".footer .clearfix .ray-id"):
|
||||
blind = True
|
||||
if retry and x and y and _on_a_captcha_page(driver):
|
||||
caught = True
|
||||
if blind:
|
||||
retry = True
|
||||
if retry and x and y and (caught or _on_a_captcha_page(driver)):
|
||||
with gui_lock: # Prevent issues with multiple processes
|
||||
# Make sure the window is on top
|
||||
page_actions.switch_to_window(
|
||||
|
@ -1056,11 +1059,7 @@ def uc_gui_click_cf(driver, frame="iframe", retry=False, blind=False):
|
|||
)
|
||||
|
||||
|
||||
def _uc_gui_handle_captcha(
|
||||
driver,
|
||||
frame="iframe",
|
||||
ctype=None,
|
||||
):
|
||||
def _uc_gui_handle_captcha_(driver, frame="iframe", ctype=None):
|
||||
if ctype == "cf_t":
|
||||
if not _on_a_cf_turnstile_page(driver):
|
||||
return
|
||||
|
@ -1202,12 +1201,19 @@ def _uc_gui_handle_captcha(
|
|||
pyautogui.press(" ")
|
||||
except Exception:
|
||||
pass
|
||||
reconnect_time = (float(constants.UC.RECONNECT_TIME) / 2.0) + 0.5
|
||||
reconnect_time = (float(constants.UC.RECONNECT_TIME) / 2.0) + 0.6
|
||||
if IS_LINUX:
|
||||
reconnect_time = constants.UC.RECONNECT_TIME + 0.2
|
||||
driver.reconnect(reconnect_time)
|
||||
|
||||
|
||||
def _uc_gui_handle_captcha(driver, frame="iframe", ctype=None):
|
||||
_uc_gui_handle_captcha_(driver, frame=frame, ctype=ctype)
|
||||
if driver.is_element_present(".footer .clearfix .ray-id"):
|
||||
driver.uc_open_with_reconnect(driver.current_url, 3.8)
|
||||
_uc_gui_handle_captcha_(driver, frame=frame, ctype=ctype)
|
||||
|
||||
|
||||
def uc_gui_handle_captcha(driver, frame="iframe"):
|
||||
_uc_gui_handle_captcha(driver, frame=frame, ctype=None)
|
||||
|
||||
|
|
|
@ -16071,7 +16071,10 @@ class BaseCase(unittest.TestCase):
|
|||
try:
|
||||
self.driver.window_handles
|
||||
except Exception:
|
||||
self.driver.connect()
|
||||
try:
|
||||
self.driver.connect()
|
||||
except Exception:
|
||||
pass
|
||||
self.__slow_mode_pause_if_active()
|
||||
has_exception = self.__has_exception()
|
||||
sb_config._has_exception = has_exception
|
||||
|
|
|
@ -48,7 +48,7 @@ def wait_for_ready_state_complete(driver, timeout=settings.LARGE_TIMEOUT):
|
|||
return False # readyState stayed "interactive" (Not "complete")
|
||||
|
||||
|
||||
def execute_async_script(driver, script, timeout=settings.EXTREME_TIMEOUT):
|
||||
def execute_async_script(driver, script, timeout=settings.LARGE_TIMEOUT):
|
||||
driver.set_script_timeout(timeout)
|
||||
return driver.execute_async_script(script)
|
||||
|
||||
|
@ -56,11 +56,20 @@ def execute_async_script(driver, script, timeout=settings.EXTREME_TIMEOUT):
|
|||
def wait_for_angularjs(driver, timeout=settings.LARGE_TIMEOUT, **kwargs):
|
||||
if hasattr(settings, "SKIP_JS_WAITS") and settings.SKIP_JS_WAITS:
|
||||
return
|
||||
try:
|
||||
# This closes pop-up alerts
|
||||
driver.execute_script("")
|
||||
except Exception:
|
||||
pass
|
||||
if hasattr(driver, "_is_using_uc") and driver._is_using_uc:
|
||||
# Calling AngularJS waits may make UC Mode detectable.
|
||||
# Instead, pause for a brief moment, and then return.
|
||||
time.sleep(0.007)
|
||||
return
|
||||
if not settings.WAIT_FOR_ANGULARJS:
|
||||
return
|
||||
if timeout == settings.MINI_TIMEOUT:
|
||||
timeout = settings.MINI_TIMEOUT / 2.0
|
||||
|
||||
timeout = settings.MINI_TIMEOUT / 4.0
|
||||
NG_WRAPPER = (
|
||||
"%(prefix)s"
|
||||
"var $elm=document.querySelector("
|
||||
|
@ -84,15 +93,10 @@ def wait_for_angularjs(driver, timeout=settings.LARGE_TIMEOUT, **kwargs):
|
|||
"handler": handler,
|
||||
"suffix": suffix,
|
||||
}
|
||||
try:
|
||||
# This closes any pop-up alerts (otherwise the next part fails)
|
||||
driver.execute_script("")
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
execute_async_script(driver, script, timeout=timeout)
|
||||
except Exception:
|
||||
time.sleep(0.05)
|
||||
time.sleep(0.0456)
|
||||
|
||||
|
||||
def convert_to_css_selector(selector, by=By.CSS_SELECTOR):
|
||||
|
|
|
@ -59,6 +59,7 @@ def pytest_addoption(parser):
|
|||
--binary-location=PATH (Set path of the Chromium browser binary to use.)
|
||||
--driver-version=VER (Set the chromedriver or uc_driver version to use.)
|
||||
--sjw (Skip JS Waits for readyState to be "complete" or Angular to load.)
|
||||
--wfa (Wait for AngularJS to be done loading after specific web actions.)
|
||||
--pls=PLS (Set pageLoadStrategy on Chrome: "normal", "eager", or "none".)
|
||||
--headless (Run tests in headless mode. The default arg on Linux OS.)
|
||||
--headless2 (Use the new headless mode, which supports extensions.)
|
||||
|
@ -358,6 +359,17 @@ def pytest_addoption(parser):
|
|||
and wait_for_angularjs(), which are part of many
|
||||
SeleniumBase methods for improving reliability.""",
|
||||
)
|
||||
parser.addoption(
|
||||
"--wfa",
|
||||
"--wait_for_angularjs",
|
||||
"--wait-for-angularjs",
|
||||
action="store_true",
|
||||
dest="wait_for_angularjs",
|
||||
default=False,
|
||||
help="""Add waiting for AngularJS. (The default setting
|
||||
was changed to no longer wait for AngularJS to
|
||||
finish loading as an extra JavaScript call.)""",
|
||||
)
|
||||
parser.addoption(
|
||||
"--with-db_reporting",
|
||||
"--with-db-reporting",
|
||||
|
@ -1546,6 +1558,8 @@ def pytest_configure(config):
|
|||
settings.ARCHIVE_EXISTING_DOWNLOADS = True
|
||||
if config.getoption("skip_js_waits"):
|
||||
settings.SKIP_JS_WAITS = True
|
||||
if config.getoption("wait_for_angularjs"):
|
||||
settings.WAIT_FOR_ANGULARJS = True
|
||||
sb_config.all_scripts = config.getoption("all_scripts")
|
||||
sb_config._time_limit = config.getoption("time_limit")
|
||||
sb_config.time_limit = config.getoption("time_limit")
|
||||
|
|
|
@ -76,6 +76,7 @@ def SB(
|
|||
binary_location=None, # Set path of the Chromium browser binary to use.
|
||||
driver_version=None, # Set the chromedriver or uc_driver version to use.
|
||||
skip_js_waits=None, # Skip JS Waits (readyState=="complete" and Angular).
|
||||
wait_for_angularjs=None, # Wait for AngularJS to load after some actions.
|
||||
use_wire=None, # Use selenium-wire's webdriver over selenium webdriver.
|
||||
external_pdf=None, # Set Chrome "plugins.always_open_pdf_externally":True.
|
||||
is_mobile=None, # Use the mobile device emulator while running tests.
|
||||
|
@ -109,6 +110,7 @@ def SB(
|
|||
wire=None, # Shortcut / Duplicate of "use_wire".
|
||||
pls=None, # Shortcut / Duplicate of "page_load_strategy".
|
||||
sjw=None, # Shortcut / Duplicate of "skip_js_waits".
|
||||
wfa=None, # Shortcut / Duplicate of "wait_for_angularjs".
|
||||
save_screenshot=None, # Save a screenshot at the end of each test.
|
||||
no_screenshot=None, # No screenshots saved unless tests directly ask it.
|
||||
page_load_strategy=None, # Set Chrome PLS to "normal", "eager", or "none".
|
||||
|
@ -607,6 +609,17 @@ def SB(
|
|||
settings.SKIP_JS_WAITS = True
|
||||
elif skip_js_waits:
|
||||
settings.SKIP_JS_WAITS = skip_js_waits
|
||||
if wfa is not None and wait_for_angularjs is None:
|
||||
wait_for_angularjs = wfa
|
||||
if wait_for_angularjs is None:
|
||||
if (
|
||||
"--wfa" in sys_argv
|
||||
or "--wait_for_angularjs" in sys_argv
|
||||
or "--wait-for-angularjs" in sys_argv
|
||||
):
|
||||
settings.WAIT_FOR_ANGULARJS = True
|
||||
elif wait_for_angularjs:
|
||||
settings.WAIT_FOR_ANGULARJS = wait_for_angularjs
|
||||
if save_screenshot is None:
|
||||
if (
|
||||
"--screenshot" in sys_argv
|
||||
|
|
|
@ -40,6 +40,7 @@ class SeleniumBrowser(Plugin):
|
|||
--binary-location=PATH (Set path of the Chromium browser binary to use.)
|
||||
--driver-version=VER (Set the chromedriver or uc_driver version to use.)
|
||||
--sjw (Skip JS Waits for readyState to be "complete" or Angular to load.)
|
||||
--wfa (Wait for AngularJS to be done loading after specific web actions.)
|
||||
--pls=PLS (Set pageLoadStrategy on Chrome: "normal", "eager", or "none".)
|
||||
--headless (Run tests in headless mode. The default arg on Linux OS.)
|
||||
--headless2 (Use the new headless mode, which supports extensions.)
|
||||
|
@ -178,6 +179,17 @@ class SeleniumBrowser(Plugin):
|
|||
and wait_for_angularjs(), which are part of many
|
||||
SeleniumBase methods for improving reliability.""",
|
||||
)
|
||||
parser.addoption(
|
||||
"--wfa",
|
||||
"--wait_for_angularjs",
|
||||
"--wait-for-angularjs",
|
||||
action="store_true",
|
||||
dest="wait_for_angularjs",
|
||||
default=False,
|
||||
help="""Add waiting for AngularJS. (The default setting
|
||||
was changed to no longer wait for AngularJS to
|
||||
finish loading as an extra JavaScript call.)""",
|
||||
)
|
||||
parser.addoption(
|
||||
"--protocol",
|
||||
action="store",
|
||||
|
@ -1105,6 +1117,8 @@ class SeleniumBrowser(Plugin):
|
|||
test.test.start_page = self.options.start_page
|
||||
if self.options.skip_js_waits:
|
||||
settings.SKIP_JS_WAITS = True
|
||||
if self.options.wait_for_angularjs:
|
||||
settings.WAIT_FOR_ANGULARJS = True
|
||||
test.test.protocol = self.options.protocol
|
||||
test.test.servername = self.options.servername
|
||||
test.test.port = self.options.port
|
||||
|
|
Loading…
Reference in New Issue