Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions examples/cdp_mode/raw_basic_async.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import asyncio
from seleniumbase import cdp_driver
from seleniumbase import decorators


async def main():
url = "seleniumbase.io/simple/login"
driver = await cdp_driver.start_async(incognito=True)
page = await driver.get(url)
driver = await cdp_driver.start_async()
page = await driver.get(url, lang="en")
print(await page.evaluate("document.title"))
element = await page.select("#username")
await element.send_keys_async("demo_user")
Expand All @@ -24,4 +25,5 @@ async def main():
if __name__ == "__main__":
# Call an async function with awaited methods
loop = asyncio.new_event_loop()
loop.run_until_complete(main())
with decorators.print_runtime("raw_basic_async.py"):
loop.run_until_complete(main())
4 changes: 3 additions & 1 deletion examples/cdp_mode/raw_cdp.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ def main():
sb.press_keys(where_to, location)
sb.sleep(1)
sb.gui_click_element(button)
sb.sleep(3)
sb.sleep(2)
sb.click_if_visible('button[aria-label="Close"]')
sb.sleep(1)
print(sb.get_title())
print("************")
for i in range(8):
Expand Down
10 changes: 6 additions & 4 deletions examples/cdp_mode/raw_multi_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from concurrent.futures import ThreadPoolExecutor
from random import randint
from seleniumbase import cdp_driver
from seleniumbase import decorators


async def main(url):
Expand All @@ -24,7 +25,8 @@ def set_up_loop(url):


if __name__ == "__main__":
urls = ["https://seleniumbase.io/demo_page" for i in range(4)]
with ThreadPoolExecutor(max_workers=len(urls)) as executor:
for url in urls:
executor.submit(set_up_loop, url)
urls = ["https://seleniumbase.io/demo_page" for i in range(5)]
with decorators.print_runtime("raw_multi_async.py"):
with ThreadPoolExecutor(max_workers=len(urls)) as executor:
for url in urls:
executor.submit(set_up_loop, url)
22 changes: 22 additions & 0 deletions examples/cdp_mode/raw_multi_captcha.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Testing multiple CDP drivers using the sync API
from concurrent.futures import ThreadPoolExecutor
from random import randint
from seleniumbase import decorators
from seleniumbase import sb_cdp


def main(url):
sb = sb_cdp.Chrome(url, lang="en")
sb.set_window_rect(randint(4, 680), randint(8, 380), 840, 520)
sb.sleep(2.2)
sb.gui_click_captcha()
sb.sleep(2)
sb.driver.quit()


if __name__ == "__main__":
urls = ["https://seleniumbase.io/apps/turnstile" for i in range(5)]
with decorators.print_runtime("raw_multi_captcha.py"):
with ThreadPoolExecutor(max_workers=len(urls)) as executor:
for url in urls:
executor.submit(main, url)
15 changes: 9 additions & 6 deletions examples/cdp_mode/raw_multi_cdp.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
# Testing multiple CDP drivers using the sync API
from concurrent.futures import ThreadPoolExecutor
from random import randint
from seleniumbase import decorators
from seleniumbase import sb_cdp


def main(url):
sb = sb_cdp.Chrome(url)
sb.set_window_rect(randint(4, 720), randint(8, 410), 800, 500)
sb = sb_cdp.Chrome(url, lang="en")
sb.set_window_rect(randint(4, 680), randint(8, 380), 840, 520)
sb.press_keys("input", "Text")
sb.highlight("button")
sb.click("button")
sb.sleep(2)
sb.driver.quit()


if __name__ == "__main__":
urls = ["https://seleniumbase.io/demo_page" for i in range(4)]
with ThreadPoolExecutor(max_workers=len(urls)) as executor:
for url in urls:
executor.submit(main, url)
urls = ["https://seleniumbase.io/demo_page" for i in range(5)]
with decorators.print_runtime("raw_multi_cdp.py"):
with ThreadPoolExecutor(max_workers=len(urls)) as executor:
for url in urls:
executor.submit(main, url)
21 changes: 4 additions & 17 deletions examples/hack_the_planet.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,25 +130,12 @@ def test_all_your_base_are_belong_to_us(self):
self.highlight("section.crayons-card", loops=7, scroll=False)

self.open("https://store.steampowered.com/")
self.set_text_content('a[href*="steamcommunity.com/"]', " ")
self.set_text_content('div.content a[href*="/about/"]', " ")
self.set_text_content('div.content a[href*="help.steam"]', aybabtu)
self.set_text_content("#foryou_tab a", "ALL")
self.set_text_content("#noteworthy_tab a", "YOUR BASE")
self.set_text_content("#genre_tab a", "ARE")
self.set_text_content('span:contains("Points Shop")', "BELONG")
self.set_text_content('span:contains("News")', "TO")
self.set_text_content('span:contains("Labs")', "US")
self.set_value("input#store_nav_search_term", ayb + " . . . .")
self.highlight('div.content a[href*="help.steam"]', loops=6)
self.highlight("#store_nav_area", loops=2, scroll=False)
self.highlight("#foryou_tab a", loops=1, scroll=False)
self.highlight("#noteworthy_tab a", loops=3, scroll=False)
self.highlight("#genre_tab a", loops=1, scroll=False)
self.highlight('span:contains("BELONG")', loops=1, scroll=False)
self.highlight('span:contains("TO")', loops=1, scroll=False)
self.highlight('span:contains("US")', loops=2, scroll=False)
self.js_click('input[id*="nav_search"]')
self.highlight('input[id*="nav_search"]', loops=6, scroll=False)
zoom_in = '[href*="help.steam"]{zoom: 1.5;-moz-transform: scale(1.5);}'
self.add_css_style(zoom_in)
self.highlight('div.content a[href*="help.steam"]', loops=12)

self.open("https://xkcd.com/286/")
self.set_text_content('a[href="/archive"]', "ALL")
Expand Down
29 changes: 10 additions & 19 deletions examples/visual_testing/layout_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,22 @@


class VisualLayoutTests(BaseCase):
def test_applitools_layout_change(self):
def test_xkcd_layout_change(self):
self.demo_mode = False # (It would interfere with html comparisons)
self.open("https://applitools.com/helloworld/?diff1")
self.wait_for_element('a[href="?diff1"]')
self.open("https://xkcd.com/1424/")
print('\nCreating baseline in "visual_baseline" folder.')
self.sleep(0.08)
self.check_window(name="helloworld", baseline=True)
# Click a button that changes the text of an element
# (Text changes do not impact visual comparisons)
self.sleep(0.06)
self.click('a[href="?diff1"]')
self.sleep(0.14)
self.check_window(name="xkcd", baseline=True)
# Go to a different comic
self.open("https://xkcd.com/1425/")
# Verify html tags match the baseline
self.check_window(name="helloworld", level=1)
self.check_window(name="xkcd", level=1)
# Verify html tags and attribute names match the baseline
self.check_window(name="helloworld", level=2)
# Verify html tags and attribute values match the baseline
self.check_window(name="helloworld", level=3)
# Click a button that makes a hidden element visible
self.click("button")
self.check_window(name="helloworld", level=1)
self.check_window(name="helloworld", level=2)
self.check_window(name="xkcd", level=2)
# Verify html tags and attribute values don't match the baseline
with self.assert_raises(Exception):
self.check_window(name="helloworld", level=3)
self.check_window(name="xkcd", level=3)
# Now that we know the Exception was raised as expected,
# let's print out the comparison results by running a Level-0 check.
# (NOTE: Running with level-0 will print but NOT raise an Exception.)
self.check_window(name="helloworld", level=0)
self.check_window(name="xkcd", level=0)
11 changes: 0 additions & 11 deletions examples/visual_testing/test_layout_fail.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,6 @@ def test_python_home_change(self, sb):


class VisualLayoutFailureTests(BaseCase):
def test_applitools_change(self):
self.open("https://applitools.com/helloworld/?diff1")
print('\nCreating baseline in "visual_baseline" folder.')
self.check_window(name="helloworld", baseline=True)
# Click a button that changes the text of an element
self.click('a[href="?diff1"]')
# Click a button that makes a hidden element visible
self.slow_click("button")
print("(This test should fail)") # due to image now seen
self.check_window(name="helloworld", level=3)

def test_xkcd_logo_change(self):
self.open("https://xkcd.com/554/")
print('\nCreating baseline in "visual_baseline" folder.')
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ rich>=14.1.0,<15
# ("pip install -r requirements.txt" also installs this, but "pip install -e ." won't.)

coverage>=7.6.1;python_version<"3.9"
coverage>=7.10.6;python_version>="3.9"
coverage>=7.10.7;python_version>="3.9"
pytest-cov>=5.0.0;python_version<"3.9"
pytest-cov>=7.0.0;python_version>="3.9"
flake8==5.0.4;python_version<"3.9"
Expand Down
2 changes: 1 addition & 1 deletion seleniumbase/__version__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# seleniumbase package
__version__ = "4.41.8"
__version__ = "4.41.9"
43 changes: 21 additions & 22 deletions seleniumbase/core/browser_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import urllib3
import warnings
from contextlib import suppress
from filelock import FileLock
from selenium import webdriver
from selenium.common.exceptions import ElementClickInterceptedException
from selenium.common.exceptions import InvalidSessionIdException
Expand Down Expand Up @@ -429,6 +430,12 @@ def __is_cdp_swap_needed(driver):
return shared_utils.is_cdp_swap_needed(driver)


def uc_execute_cdp_cmd(driver, *args, **kwargs):
if not driver.is_connected():
driver.connect()
return driver.default_execute_cdp_cmd(*args, **kwargs)


def uc_special_open_if_cf(
driver,
url,
Expand Down Expand Up @@ -641,7 +648,7 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs):
)
loop.run_until_complete(driver.cdp_base.wait(0))

gui_lock = fasteners.InterProcessLock(constants.MultiBrowser.PYAUTOGUILOCK)
gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)

if (
"chrome-extension://" in str(driver.cdp_base.main_tab)
Expand Down Expand Up @@ -1080,9 +1087,7 @@ def uc_gui_press_key(driver, key):
install_pyautogui_if_missing(driver)
import pyautogui
pyautogui = get_configured_pyautogui(pyautogui)
gui_lock = fasteners.InterProcessLock(
constants.MultiBrowser.PYAUTOGUILOCK
)
gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
with gui_lock:
pyautogui.press(key)

Expand All @@ -1091,9 +1096,7 @@ def uc_gui_press_keys(driver, keys):
install_pyautogui_if_missing(driver)
import pyautogui
pyautogui = get_configured_pyautogui(pyautogui)
gui_lock = fasteners.InterProcessLock(
constants.MultiBrowser.PYAUTOGUILOCK
)
gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
with gui_lock:
for key in keys:
pyautogui.press(key)
Expand All @@ -1103,9 +1106,7 @@ def uc_gui_write(driver, text):
install_pyautogui_if_missing(driver)
import pyautogui
pyautogui = get_configured_pyautogui(pyautogui)
gui_lock = fasteners.InterProcessLock(
constants.MultiBrowser.PYAUTOGUILOCK
)
gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
with gui_lock:
pyautogui.write(text)

Expand Down Expand Up @@ -1138,9 +1139,7 @@ def _uc_gui_click_x_y(driver, x, y, timeframe=0.25, uc_lock=False):
% (x, y, screen_width, screen_height)
)
if uc_lock:
gui_lock = fasteners.InterProcessLock(
constants.MultiBrowser.PYAUTOGUILOCK
)
gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
with gui_lock: # Prevent issues with multiple processes
pyautogui.moveTo(x, y, timeframe, pyautogui.easeOutQuad)
if timeframe >= 0.25:
Expand All @@ -1159,9 +1158,7 @@ def _uc_gui_click_x_y(driver, x, y, timeframe=0.25, uc_lock=False):


def uc_gui_click_x_y(driver, x, y, timeframe=0.25):
gui_lock = fasteners.InterProcessLock(
constants.MultiBrowser.PYAUTOGUILOCK
)
gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
with gui_lock: # Prevent issues with multiple processes
install_pyautogui_if_missing(driver)
import pyautogui
Expand Down Expand Up @@ -1280,9 +1277,7 @@ def _uc_gui_click_captcha(
x = None
y = None
visible_iframe = True
gui_lock = fasteners.InterProcessLock(
constants.MultiBrowser.PYAUTOGUILOCK
)
gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
with gui_lock: # Prevent issues with multiple processes
needs_switch = False
width_ratio = 1.0
Expand Down Expand Up @@ -1643,9 +1638,7 @@ def _uc_gui_handle_captcha_(driver, frame="iframe", ctype=None):
import pyautogui
pyautogui = get_configured_pyautogui(pyautogui)
visible_iframe = True
gui_lock = fasteners.InterProcessLock(
constants.MultiBrowser.PYAUTOGUILOCK
)
gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
with gui_lock: # Prevent issues with multiple processes
needs_switch = False
if not __is_cdp_swap_needed(driver):
Expand Down Expand Up @@ -5691,6 +5684,12 @@ def get_local_driver(
driver, *args, **kwargs
)
)
driver.default_execute_cdp_cmd = driver.execute_cdp_cmd
driver.execute_cdp_cmd = (
lambda *args, **kwargs: uc_execute_cdp_cmd(
driver, *args, **kwargs
)
)
driver._is_hidden = (headless or headless2)
driver._is_using_uc = True
with suppress(Exception):
Expand Down
Loading