seleniumbase 4.32.10a3__py3-none-any.whl → 4.32.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- seleniumbase/__version__.py +1 -1
- seleniumbase/core/browser_launcher.py +21 -5
- seleniumbase/core/log_helper.py +12 -18
- seleniumbase/core/sb_cdp.py +103 -18
- seleniumbase/core/sb_driver.py +5 -2
- seleniumbase/fixtures/base_case.py +40 -23
- seleniumbase/fixtures/constants.py +1 -0
- seleniumbase/fixtures/js_utils.py +1 -5
- seleniumbase/fixtures/page_actions.py +0 -2
- seleniumbase/fixtures/shared_utils.py +11 -0
- seleniumbase/plugins/sb_manager.py +2 -2
- {seleniumbase-4.32.10a3.dist-info → seleniumbase-4.32.11.dist-info}/METADATA +2 -2
- {seleniumbase-4.32.10a3.dist-info → seleniumbase-4.32.11.dist-info}/RECORD +17 -17
- {seleniumbase-4.32.10a3.dist-info → seleniumbase-4.32.11.dist-info}/LICENSE +0 -0
- {seleniumbase-4.32.10a3.dist-info → seleniumbase-4.32.11.dist-info}/WHEEL +0 -0
- {seleniumbase-4.32.10a3.dist-info → seleniumbase-4.32.11.dist-info}/entry_points.txt +0 -0
- {seleniumbase-4.32.10a3.dist-info → seleniumbase-4.32.11.dist-info}/top_level.txt +0 -0
seleniumbase/__version__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
# seleniumbase package
|
2
|
-
__version__ = "4.32.
|
2
|
+
__version__ = "4.32.11"
|
@@ -544,6 +544,8 @@ def uc_open_with_cdp_mode(driver, url=None):
|
|
544
544
|
)
|
545
545
|
loop.run_until_complete(driver.cdp_base.wait(0))
|
546
546
|
|
547
|
+
gui_lock = fasteners.InterProcessLock(constants.MultiBrowser.PYAUTOGUILOCK)
|
548
|
+
|
547
549
|
if (
|
548
550
|
"chrome-extension://" in str(driver.cdp_base.main_tab)
|
549
551
|
and len(driver.cdp_base.tabs) >= 2
|
@@ -553,7 +555,8 @@ def uc_open_with_cdp_mode(driver, url=None):
|
|
553
555
|
|
554
556
|
for tab in driver.cdp_base.tabs[-1::-1]:
|
555
557
|
if "chrome-extension://" not in str(tab):
|
556
|
-
|
558
|
+
with gui_lock:
|
559
|
+
loop.run_until_complete(tab.activate())
|
557
560
|
break
|
558
561
|
|
559
562
|
page_tab = None
|
@@ -566,14 +569,20 @@ def uc_open_with_cdp_mode(driver, url=None):
|
|
566
569
|
break
|
567
570
|
if page_tab:
|
568
571
|
loop.run_until_complete(page_tab.aopen())
|
569
|
-
|
572
|
+
with gui_lock:
|
573
|
+
loop.run_until_complete(page_tab.activate())
|
570
574
|
|
571
575
|
loop.run_until_complete(driver.cdp_base.update_targets())
|
572
576
|
page = loop.run_until_complete(driver.cdp_base.get(url))
|
573
|
-
|
577
|
+
with gui_lock:
|
578
|
+
loop.run_until_complete(page.activate())
|
574
579
|
loop.run_until_complete(page.wait())
|
575
580
|
if not safe_url:
|
576
581
|
time.sleep(constants.UC.CDP_MODE_OPEN_WAIT)
|
582
|
+
if IS_WINDOWS:
|
583
|
+
time.sleep(constants.UC.EXTRA_WINDOWS_WAIT)
|
584
|
+
else:
|
585
|
+
time.sleep(0.012)
|
577
586
|
cdp = types.SimpleNamespace()
|
578
587
|
CDPM = sb_cdp.CDPMethods(loop, page, driver)
|
579
588
|
cdp.get = CDPM.get
|
@@ -590,6 +599,9 @@ def uc_open_with_cdp_mode(driver, url=None):
|
|
590
599
|
cdp.select = CDPM.select
|
591
600
|
cdp.select_all = CDPM.select_all
|
592
601
|
cdp.find_elements = CDPM.find_elements
|
602
|
+
cdp.find_visible_elements = CDPM.find_visible_elements
|
603
|
+
cdp.click_nth_element = CDPM.click_nth_element
|
604
|
+
cdp.click_nth_visible_element = CDPM.click_nth_visible_element
|
593
605
|
cdp.click_link = CDPM.click_link
|
594
606
|
cdp.tile_windows = CDPM.tile_windows
|
595
607
|
cdp.get_all_cookies = CDPM.get_all_cookies
|
@@ -609,7 +621,6 @@ def uc_open_with_cdp_mode(driver, url=None):
|
|
609
621
|
cdp.remove_element = CDPM.remove_element
|
610
622
|
cdp.remove_from_dom = CDPM.remove_from_dom
|
611
623
|
cdp.remove_elements = CDPM.remove_elements
|
612
|
-
cdp.scroll_into_view = CDPM.scroll_into_view
|
613
624
|
cdp.send_keys = CDPM.send_keys
|
614
625
|
cdp.press_keys = CDPM.press_keys
|
615
626
|
cdp.type = CDPM.type
|
@@ -680,8 +691,12 @@ def uc_open_with_cdp_mode(driver, url=None):
|
|
680
691
|
cdp.assert_title = CDPM.assert_title
|
681
692
|
cdp.assert_text = CDPM.assert_text
|
682
693
|
cdp.assert_exact_text = CDPM.assert_exact_text
|
683
|
-
cdp.
|
694
|
+
cdp.scroll_into_view = CDPM.scroll_into_view
|
695
|
+
cdp.scroll_to_y = CDPM.scroll_to_y
|
696
|
+
cdp.scroll_to_top = CDPM.scroll_to_top
|
697
|
+
cdp.scroll_to_bottom = CDPM.scroll_to_bottom
|
684
698
|
cdp.scroll_up = CDPM.scroll_up
|
699
|
+
cdp.scroll_down = CDPM.scroll_down
|
685
700
|
cdp.save_screenshot = CDPM.save_screenshot
|
686
701
|
cdp.page = page # async world
|
687
702
|
cdp.driver = driver.cdp_base # async world
|
@@ -1255,6 +1270,7 @@ def _uc_gui_click_captcha(
|
|
1255
1270
|
with suppress(Exception):
|
1256
1271
|
_uc_gui_click_x_y(driver, x, y, timeframe=0.32)
|
1257
1272
|
if __is_cdp_swap_needed(driver):
|
1273
|
+
time.sleep(float(constants.UC.RECONNECT_TIME) / 2.0)
|
1258
1274
|
return
|
1259
1275
|
reconnect_time = (float(constants.UC.RECONNECT_TIME) / 2.0) + 0.6
|
1260
1276
|
if IS_LINUX:
|
seleniumbase/core/log_helper.py
CHANGED
@@ -3,6 +3,7 @@ import os
|
|
3
3
|
import shutil
|
4
4
|
import sys
|
5
5
|
import time
|
6
|
+
from contextlib import suppress
|
6
7
|
from seleniumbase import config as sb_config
|
7
8
|
from seleniumbase.config import settings
|
8
9
|
from seleniumbase.fixtures import constants
|
@@ -281,14 +282,13 @@ def log_test_failure_data(test, test_logpath, driver, browser, url=None):
|
|
281
282
|
sb_config._report_time = the_time
|
282
283
|
sb_config._report_traceback = traceback_message
|
283
284
|
sb_config._report_exception = exc_message
|
284
|
-
|
285
|
+
with suppress(Exception):
|
285
286
|
if not os.path.exists(test_logpath):
|
286
287
|
os.makedirs(test_logpath)
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
log_file.close()
|
288
|
+
with suppress(Exception):
|
289
|
+
log_file = codecs.open(basic_file_path, "w+", encoding="utf-8")
|
290
|
+
log_file.writelines("\r\n".join(data_to_save))
|
291
|
+
log_file.close()
|
292
292
|
|
293
293
|
|
294
294
|
def log_skipped_test_data(test, test_logpath, driver, browser, reason):
|
@@ -297,16 +297,12 @@ def log_skipped_test_data(test, test_logpath, driver, browser, reason):
|
|
297
297
|
browser_version = None
|
298
298
|
driver_version = None
|
299
299
|
driver_name = None
|
300
|
-
|
300
|
+
with suppress(Exception):
|
301
301
|
browser_version = get_browser_version(driver)
|
302
|
-
|
303
|
-
pass
|
304
|
-
try:
|
302
|
+
with suppress(Exception):
|
305
303
|
driver_name, driver_version = get_driver_name_and_version(
|
306
304
|
driver, browser
|
307
305
|
)
|
308
|
-
except Exception:
|
309
|
-
pass
|
310
306
|
if browser_version:
|
311
307
|
headless = ""
|
312
308
|
if test.headless and browser in ["chrome", "edge", "firefox"]:
|
@@ -368,13 +364,11 @@ def log_page_source(test_logpath, driver, source=None):
|
|
368
364
|
"unresponsive, or closed prematurely!</h4>"
|
369
365
|
)
|
370
366
|
)
|
371
|
-
|
367
|
+
with suppress(Exception):
|
372
368
|
if not os.path.exists(test_logpath):
|
373
369
|
os.makedirs(test_logpath)
|
374
|
-
except Exception:
|
375
|
-
pass
|
376
370
|
html_file_path = os.path.join(test_logpath, html_file_name)
|
377
|
-
html_file = codecs.open(html_file_path, "w+", "utf-8")
|
371
|
+
html_file = codecs.open(html_file_path, "w+", encoding="utf-8")
|
378
372
|
html_file.write(page_source)
|
379
373
|
html_file.close()
|
380
374
|
|
@@ -543,7 +537,7 @@ def log_folder_setup(log_path, archive_logs=False):
|
|
543
537
|
try:
|
544
538
|
os.makedirs(log_path)
|
545
539
|
except Exception:
|
546
|
-
pass #
|
540
|
+
pass # Only reachable during multi-threaded runs
|
547
541
|
else:
|
548
542
|
saved_folder = "%s/../%s/" % (log_path, constants.Logs.SAVED)
|
549
543
|
archived_folder = os.path.realpath(saved_folder) + "/"
|
@@ -551,7 +545,7 @@ def log_folder_setup(log_path, archive_logs=False):
|
|
551
545
|
try:
|
552
546
|
os.makedirs(archived_folder)
|
553
547
|
except Exception:
|
554
|
-
pass #
|
548
|
+
pass # Only reachable during multi-threaded runs
|
555
549
|
archived_logs = "%slogs_%s" % (archived_folder, int(time.time()))
|
556
550
|
if len(os.listdir(log_path)) > 0:
|
557
551
|
try:
|
seleniumbase/core/sb_cdp.py
CHANGED
@@ -89,6 +89,10 @@ class CDPMethods():
|
|
89
89
|
safe_url = False
|
90
90
|
if not safe_url:
|
91
91
|
time.sleep(constants.UC.CDP_MODE_OPEN_WAIT)
|
92
|
+
if shared_utils.is_windows():
|
93
|
+
time.sleep(constants.UC.EXTRA_WINDOWS_WAIT)
|
94
|
+
else:
|
95
|
+
time.sleep(0.012)
|
92
96
|
self.__slow_mode_pause_if_set()
|
93
97
|
self.loop.run_until_complete(self.page.wait())
|
94
98
|
|
@@ -248,6 +252,45 @@ class CDPMethods():
|
|
248
252
|
def find_elements(self, selector, timeout=settings.SMALL_TIMEOUT):
|
249
253
|
return self.select_all(selector, timeout=timeout)
|
250
254
|
|
255
|
+
def find_visible_elements(self, selector, timeout=settings.SMALL_TIMEOUT):
|
256
|
+
visible_elements = []
|
257
|
+
elements = self.select_all(selector, timeout=timeout)
|
258
|
+
for element in elements:
|
259
|
+
with suppress(Exception):
|
260
|
+
position = element.get_position()
|
261
|
+
if (position.width != 0 or position.height != 0):
|
262
|
+
visible_elements.append(element)
|
263
|
+
return visible_elements
|
264
|
+
|
265
|
+
def click_nth_element(self, selector, number):
|
266
|
+
elements = self.select_all(selector)
|
267
|
+
if len(elements) < number:
|
268
|
+
raise Exception(
|
269
|
+
"Not enough matching {%s} elements to "
|
270
|
+
"click number %s!" % (selector, number)
|
271
|
+
)
|
272
|
+
number = number - 1
|
273
|
+
if number < 0:
|
274
|
+
number = 0
|
275
|
+
element = elements[number]
|
276
|
+
element.click()
|
277
|
+
|
278
|
+
def click_nth_visible_element(self, selector, number):
|
279
|
+
"""Finds all matching page elements and clicks the nth visible one.
|
280
|
+
Example: self.click_nth_visible_element('[type="checkbox"]', 5)
|
281
|
+
(Clicks the 5th visible checkbox on the page.)"""
|
282
|
+
elements = self.find_visible_elements(selector)
|
283
|
+
if len(elements) < number:
|
284
|
+
raise Exception(
|
285
|
+
"Not enough matching {%s} elements to "
|
286
|
+
"click number %s!" % (selector, number)
|
287
|
+
)
|
288
|
+
number = number - 1
|
289
|
+
if number < 0:
|
290
|
+
number = 0
|
291
|
+
element = elements[number]
|
292
|
+
element.click()
|
293
|
+
|
251
294
|
def click_link(self, link_text):
|
252
295
|
self.find_elements_by_text(link_text, "a")[0].click()
|
253
296
|
|
@@ -475,18 +518,36 @@ class CDPMethods():
|
|
475
518
|
self.__slow_mode_pause_if_set()
|
476
519
|
self.loop.run_until_complete(self.page.wait())
|
477
520
|
|
478
|
-
def click_visible_elements(self, selector):
|
521
|
+
def click_visible_elements(self, selector, limit=0):
|
522
|
+
"""Finds all matching page elements and clicks visible ones in order.
|
523
|
+
If a click reloads or opens a new page, the clicking will stop.
|
524
|
+
If no matching elements appear, an Exception will be raised.
|
525
|
+
If "limit" is set and > 0, will only click that many elements.
|
526
|
+
Also clicks elements that become visible from previous clicks.
|
527
|
+
Works best for actions such as clicking all checkboxes on a page.
|
528
|
+
Example: self.click_visible_elements('input[type="checkbox"]')"""
|
479
529
|
elements = self.select_all(selector)
|
530
|
+
click_count = 0
|
480
531
|
for element in elements:
|
532
|
+
if limit and limit > 0 and click_count >= limit:
|
533
|
+
return
|
481
534
|
try:
|
482
|
-
|
483
|
-
|
535
|
+
width = 0
|
536
|
+
height = 0
|
537
|
+
try:
|
538
|
+
position = element.get_position()
|
539
|
+
width = position.width
|
540
|
+
height = position.height
|
541
|
+
except Exception:
|
542
|
+
continue
|
543
|
+
if (width != 0 or height != 0):
|
484
544
|
element.click()
|
545
|
+
click_count += 1
|
485
546
|
time.sleep(0.0375)
|
486
547
|
self.__slow_mode_pause_if_set()
|
487
548
|
self.loop.run_until_complete(self.page.wait())
|
488
549
|
except Exception:
|
489
|
-
|
550
|
+
break
|
490
551
|
|
491
552
|
def mouse_click(self, selector, timeout=settings.SMALL_TIMEOUT):
|
492
553
|
"""(Attempt simulating a mouse click)"""
|
@@ -578,9 +639,6 @@ class CDPMethods():
|
|
578
639
|
with suppress(Exception):
|
579
640
|
self.loop.run_until_complete(self.page.evaluate(js_code))
|
580
641
|
|
581
|
-
def scroll_into_view(self, selector):
|
582
|
-
self.find_element(selector).scroll_into_view()
|
583
|
-
|
584
642
|
def send_keys(self, selector, text, timeout=settings.SMALL_TIMEOUT):
|
585
643
|
self.__slow_mode_pause_if_set()
|
586
644
|
element = self.select(selector, timeout=timeout)
|
@@ -1237,6 +1295,7 @@ class CDPMethods():
|
|
1237
1295
|
|
1238
1296
|
def gui_drag_and_drop(self, drag_selector, drop_selector, timeframe=0.35):
|
1239
1297
|
self.__slow_mode_pause_if_set()
|
1298
|
+
self.bring_active_window_to_front()
|
1240
1299
|
x1, y1 = self.get_gui_element_center(drag_selector)
|
1241
1300
|
self.__add_light_pause()
|
1242
1301
|
x2, y2 = self.get_gui_element_center(drop_selector)
|
@@ -1326,10 +1385,14 @@ class CDPMethods():
|
|
1326
1385
|
|
1327
1386
|
def gui_hover_element(self, selector, timeframe=0.25):
|
1328
1387
|
self.__slow_mode_pause_if_set()
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1388
|
+
element_rect = self.get_gui_element_rect(selector)
|
1389
|
+
width = element_rect["width"]
|
1390
|
+
height = element_rect["height"]
|
1391
|
+
if width > 0 and height > 0:
|
1392
|
+
x, y = self.get_gui_element_center(selector)
|
1393
|
+
self.bring_active_window_to_front()
|
1394
|
+
self.__gui_hover_x_y(x, y, timeframe=timeframe)
|
1395
|
+
self.__slow_mode_pause_if_set()
|
1333
1396
|
self.loop.run_until_complete(self.page.wait())
|
1334
1397
|
|
1335
1398
|
def gui_hover_and_click(self, hover_selector, click_selector):
|
@@ -1337,6 +1400,7 @@ class CDPMethods():
|
|
1337
1400
|
constants.MultiBrowser.PYAUTOGUILOCK
|
1338
1401
|
)
|
1339
1402
|
with gui_lock:
|
1403
|
+
self.bring_active_window_to_front()
|
1340
1404
|
self.gui_hover_element(hover_selector)
|
1341
1405
|
time.sleep(0.15)
|
1342
1406
|
self.gui_hover_element(click_selector)
|
@@ -1521,15 +1585,36 @@ class CDPMethods():
|
|
1521
1585
|
% (text, element.text_all, selector)
|
1522
1586
|
)
|
1523
1587
|
|
1524
|
-
def
|
1525
|
-
self.
|
1526
|
-
|
1527
|
-
|
1588
|
+
def scroll_into_view(self, selector):
|
1589
|
+
self.find_element(selector).scroll_into_view()
|
1590
|
+
self.loop.run_until_complete(self.page.wait())
|
1591
|
+
|
1592
|
+
def scroll_to_y(self, y):
|
1593
|
+
y = int(y)
|
1594
|
+
js_code = "window.scrollTo(0, %s);" % y
|
1595
|
+
with suppress(Exception):
|
1596
|
+
self.loop.run_until_complete(self.page.evaluate(js_code))
|
1597
|
+
self.loop.run_until_complete(self.page.wait())
|
1598
|
+
|
1599
|
+
def scroll_to_top(self):
|
1600
|
+
js_code = "window.scrollTo(0, 0);"
|
1601
|
+
with suppress(Exception):
|
1602
|
+
self.loop.run_until_complete(self.page.evaluate(js_code))
|
1603
|
+
self.loop.run_until_complete(self.page.wait())
|
1604
|
+
|
1605
|
+
def scroll_to_bottom(self):
|
1606
|
+
js_code = "window.scrollTo(0, 10000);"
|
1607
|
+
with suppress(Exception):
|
1608
|
+
self.loop.run_until_complete(self.page.evaluate(js_code))
|
1609
|
+
self.loop.run_until_complete(self.page.wait())
|
1528
1610
|
|
1529
1611
|
def scroll_up(self, amount=25):
|
1530
|
-
self.loop.run_until_complete(
|
1531
|
-
|
1532
|
-
|
1612
|
+
self.loop.run_until_complete(self.page.scroll_up(amount))
|
1613
|
+
self.loop.run_until_complete(self.page.wait())
|
1614
|
+
|
1615
|
+
def scroll_down(self, amount=25):
|
1616
|
+
self.loop.run_until_complete(self.page.scroll_down(amount))
|
1617
|
+
self.loop.run_until_complete(self.page.wait())
|
1533
1618
|
|
1534
1619
|
def save_screenshot(self, name, folder=None, selector=None):
|
1535
1620
|
filename = name
|
seleniumbase/core/sb_driver.py
CHANGED
@@ -249,8 +249,11 @@ class DriverMethods():
|
|
249
249
|
selector = kwargs["selector"]
|
250
250
|
else:
|
251
251
|
selector = args[0]
|
252
|
-
|
253
|
-
|
252
|
+
if ":contains(" not in selector:
|
253
|
+
self.driver.cdp.highlight(selector)
|
254
|
+
return
|
255
|
+
else:
|
256
|
+
self.driver.connect()
|
254
257
|
if "scroll" in kwargs:
|
255
258
|
kwargs.pop("scroll")
|
256
259
|
w_args = kwargs.copy()
|
@@ -2166,7 +2166,6 @@ class BaseCase(unittest.TestCase):
|
|
2166
2166
|
if limit and limit > 0 and len(elements) > limit:
|
2167
2167
|
elements = elements[:limit]
|
2168
2168
|
return elements
|
2169
|
-
|
2170
2169
|
self.wait_for_ready_state_complete()
|
2171
2170
|
time.sleep(0.05)
|
2172
2171
|
elements = self.driver.find_elements(by=by, value=selector)
|
@@ -2178,6 +2177,11 @@ class BaseCase(unittest.TestCase):
|
|
2178
2177
|
"""Returns a list of matching WebElements that are visible.
|
2179
2178
|
If "limit" is set and > 0, will only return that many elements."""
|
2180
2179
|
selector, by = self.__recalculate_selector(selector, by)
|
2180
|
+
if self.__is_cdp_swap_needed():
|
2181
|
+
elements = self.cdp.find_visible_elements(selector)
|
2182
|
+
if limit and limit > 0 and len(elements) > limit:
|
2183
|
+
elements = elements[:limit]
|
2184
|
+
return elements
|
2181
2185
|
self.wait_for_ready_state_complete()
|
2182
2186
|
time.sleep(0.05)
|
2183
2187
|
return page_actions.find_visible_elements(
|
@@ -2201,7 +2205,7 @@ class BaseCase(unittest.TestCase):
|
|
2201
2205
|
timeout = self.__get_new_timeout(timeout)
|
2202
2206
|
selector, by = self.__recalculate_selector(selector, by)
|
2203
2207
|
if self.__is_cdp_swap_needed():
|
2204
|
-
self.cdp.click_visible_elements(selector)
|
2208
|
+
self.cdp.click_visible_elements(selector, limit)
|
2205
2209
|
return
|
2206
2210
|
self.wait_for_ready_state_complete()
|
2207
2211
|
if self.__needs_minimum_wait():
|
@@ -2283,13 +2287,16 @@ class BaseCase(unittest.TestCase):
|
|
2283
2287
|
):
|
2284
2288
|
"""Finds all matching page elements and clicks the nth visible one.
|
2285
2289
|
Example: self.click_nth_visible_element('[type="checkbox"]', 5)
|
2286
|
-
|
2290
|
+
(Clicks the 5th visible checkbox on the page.)"""
|
2287
2291
|
self.__check_scope()
|
2288
2292
|
if not timeout:
|
2289
2293
|
timeout = settings.SMALL_TIMEOUT
|
2290
2294
|
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
|
2291
2295
|
timeout = self.__get_new_timeout(timeout)
|
2292
2296
|
selector, by = self.__recalculate_selector(selector, by)
|
2297
|
+
if self.__is_cdp_swap_needed():
|
2298
|
+
self.cdp.click_nth_visible_element(selector, number)
|
2299
|
+
return
|
2293
2300
|
self.wait_for_ready_state_complete()
|
2294
2301
|
self.wait_for_element_present(selector, by=by, timeout=timeout)
|
2295
2302
|
elements = self.find_visible_elements(selector, by=by)
|
@@ -2897,6 +2904,9 @@ class BaseCase(unittest.TestCase):
|
|
2897
2904
|
drop_selector, drop_by = self.__recalculate_selector(
|
2898
2905
|
drop_selector, drop_by
|
2899
2906
|
)
|
2907
|
+
if self.__is_cdp_swap_needed():
|
2908
|
+
self.cdp.gui_drag_and_drop(drag_selector, drop_selector)
|
2909
|
+
return
|
2900
2910
|
drag_element = self.wait_for_element_clickable(
|
2901
2911
|
drag_selector, by=drag_by, timeout=timeout
|
2902
2912
|
)
|
@@ -6144,6 +6154,9 @@ class BaseCase(unittest.TestCase):
|
|
6144
6154
|
original_selector = selector
|
6145
6155
|
original_by = by
|
6146
6156
|
selector, by = self.__recalculate_selector(selector, by)
|
6157
|
+
if self.__is_cdp_swap_needed() and ":contains(" not in selector:
|
6158
|
+
self.cdp.scroll_into_view(selector)
|
6159
|
+
return
|
6147
6160
|
element = self.wait_for_element_visible(
|
6148
6161
|
original_selector, by=original_by, timeout=timeout
|
6149
6162
|
)
|
@@ -6190,24 +6203,36 @@ class BaseCase(unittest.TestCase):
|
|
6190
6203
|
def scroll_to_top(self):
|
6191
6204
|
"""Scroll to the top of the page."""
|
6192
6205
|
self.__check_scope()
|
6206
|
+
if self.__is_cdp_swap_needed():
|
6207
|
+
self.cdp.scroll_to_top()
|
6208
|
+
return
|
6193
6209
|
scroll_script = "window.scrollTo(0, 0);"
|
6194
|
-
|
6210
|
+
with suppress(Exception):
|
6195
6211
|
self.execute_script(scroll_script)
|
6196
6212
|
time.sleep(0.012)
|
6197
|
-
return True
|
6198
|
-
except Exception:
|
6199
|
-
return False
|
6200
6213
|
|
6201
6214
|
def scroll_to_bottom(self):
|
6202
6215
|
"""Scroll to the bottom of the page."""
|
6203
6216
|
self.__check_scope()
|
6217
|
+
if self.__is_cdp_swap_needed():
|
6218
|
+
self.cdp.scroll_to_bottom()
|
6219
|
+
return
|
6204
6220
|
scroll_script = "window.scrollTo(0, 10000);"
|
6205
|
-
|
6221
|
+
with suppress(Exception):
|
6222
|
+
self.execute_script(scroll_script)
|
6223
|
+
time.sleep(0.012)
|
6224
|
+
|
6225
|
+
def scroll_to_y(self, y):
|
6226
|
+
"""Scroll to y position on the page."""
|
6227
|
+
self.__check_scope()
|
6228
|
+
y = int(y)
|
6229
|
+
if self.__is_cdp_swap_needed():
|
6230
|
+
self.cdp.scroll_to_y(y)
|
6231
|
+
return
|
6232
|
+
scroll_script = "window.scrollTo(0, %s);" % y
|
6233
|
+
with suppress(Exception):
|
6206
6234
|
self.execute_script(scroll_script)
|
6207
6235
|
time.sleep(0.012)
|
6208
|
-
return True
|
6209
|
-
except Exception:
|
6210
|
-
return False
|
6211
6236
|
|
6212
6237
|
def click_xpath(self, xpath):
|
6213
6238
|
"""Technically, self.click() automatically detects xpath selectors,
|
@@ -15420,7 +15445,8 @@ class BaseCase(unittest.TestCase):
|
|
15420
15445
|
elif hasattr(self, "_using_sb_fixture") and self._using_sb_fixture:
|
15421
15446
|
test_id = sb_config._latest_display_id
|
15422
15447
|
test_id = test_id.replace(".py::", ".").replace("::", ".")
|
15423
|
-
test_id = test_id.replace("/", ".").replace("
|
15448
|
+
test_id = test_id.replace("/", ".").replace("\\", ".")
|
15449
|
+
test_id = test_id.replace(" ", "_")
|
15424
15450
|
# Linux filename length limit for `codecs.open(filename)` = 255
|
15425
15451
|
# 255 - len("latest_logs/") - len("/basic_test_info.txt") = 223
|
15426
15452
|
if len(test_id) <= 223:
|
@@ -16117,11 +16143,7 @@ class BaseCase(unittest.TestCase):
|
|
16117
16143
|
# This test already called tearDown()
|
16118
16144
|
return
|
16119
16145
|
if hasattr(self, "recorder_mode") and self.recorder_mode:
|
16120
|
-
|
16121
|
-
try:
|
16122
|
-
self.driver.window_handles
|
16123
|
-
except Exception:
|
16124
|
-
self.driver.connect()
|
16146
|
+
page_actions._reconnect_if_disconnected(self.driver)
|
16125
16147
|
try:
|
16126
16148
|
self.__process_recorded_actions()
|
16127
16149
|
except Exception as e:
|
@@ -16162,12 +16184,7 @@ class BaseCase(unittest.TestCase):
|
|
16162
16184
|
)
|
16163
16185
|
raise Exception(message)
|
16164
16186
|
# *** Start tearDown() officially ***
|
16165
|
-
|
16166
|
-
try:
|
16167
|
-
self.driver.window_handles
|
16168
|
-
except Exception:
|
16169
|
-
with suppress(Exception):
|
16170
|
-
self.driver.connect()
|
16187
|
+
page_actions._reconnect_if_disconnected(self.driver)
|
16171
16188
|
self.__slow_mode_pause_if_active()
|
16172
16189
|
has_exception = self.__has_exception()
|
16173
16190
|
sb_config._has_exception = has_exception
|
@@ -10,6 +10,7 @@ from seleniumbase import config as sb_config
|
|
10
10
|
from seleniumbase.config import settings
|
11
11
|
from seleniumbase.fixtures import constants
|
12
12
|
from seleniumbase.fixtures import css_to_xpath
|
13
|
+
from seleniumbase.fixtures import shared_utils
|
13
14
|
from seleniumbase.fixtures import xpath_to_css
|
14
15
|
|
15
16
|
|
@@ -24,9 +25,6 @@ def wait_for_ready_state_complete(driver, timeout=settings.LARGE_TIMEOUT):
|
|
24
25
|
(Previously, tests would fail immediately if exceeding the timeout.)"""
|
25
26
|
if hasattr(settings, "SKIP_JS_WAITS") and settings.SKIP_JS_WAITS:
|
26
27
|
return
|
27
|
-
if sb_config.time_limit and not sb_config.recorder_mode:
|
28
|
-
from seleniumbase.fixtures import shared_utils
|
29
|
-
|
30
28
|
start_ms = time.time() * 1000.0
|
31
29
|
stop_ms = start_ms + (timeout * 1000.0)
|
32
30
|
for x in range(int(timeout * 10)):
|
@@ -243,8 +241,6 @@ def escape_quotes_if_needed(string):
|
|
243
241
|
def is_in_frame(driver):
|
244
242
|
# Returns True if the driver has switched to a frame.
|
245
243
|
# Returns False if the driver was on default content.
|
246
|
-
from seleniumbase.fixtures import shared_utils
|
247
|
-
|
248
244
|
if shared_utils.is_cdp_swap_needed(driver):
|
249
245
|
return False
|
250
246
|
in_basic_frame = driver.execute_script(
|
@@ -1555,8 +1555,6 @@ def _reconnect_if_disconnected(driver):
|
|
1555
1555
|
if (
|
1556
1556
|
hasattr(driver, "_is_using_uc")
|
1557
1557
|
and driver._is_using_uc
|
1558
|
-
and hasattr(driver, "_is_connected")
|
1559
|
-
and not driver._is_connected
|
1560
1558
|
and hasattr(driver, "is_connected")
|
1561
1559
|
and not driver.is_connected()
|
1562
1560
|
):
|
@@ -84,6 +84,17 @@ def fix_url_as_needed(url):
|
|
84
84
|
return url
|
85
85
|
|
86
86
|
|
87
|
+
def reconnect_if_disconnected(driver):
|
88
|
+
if (
|
89
|
+
hasattr(driver, "_is_using_uc")
|
90
|
+
and driver._is_using_uc
|
91
|
+
and hasattr(driver, "is_connected")
|
92
|
+
and not driver.is_connected()
|
93
|
+
):
|
94
|
+
with suppress(Exception):
|
95
|
+
driver.connect()
|
96
|
+
|
97
|
+
|
87
98
|
def is_cdp_swap_needed(driver):
|
88
99
|
"""
|
89
100
|
When someone is using CDP Mode with a disconnected webdriver,
|
@@ -1202,7 +1202,7 @@ def SB(
|
|
1202
1202
|
from seleniumbase.core import download_helper
|
1203
1203
|
from seleniumbase.core import proxy_helper
|
1204
1204
|
|
1205
|
-
log_helper.log_folder_setup(constants.Logs.LATEST +
|
1205
|
+
log_helper.log_folder_setup(constants.Logs.LATEST + os.sep)
|
1206
1206
|
log_helper.clear_empty_logs()
|
1207
1207
|
download_helper.reset_downloads_folder()
|
1208
1208
|
if not sb_config.multi_proxy:
|
@@ -1228,7 +1228,7 @@ def SB(
|
|
1228
1228
|
the_traceback = traceback.format_exc().strip()
|
1229
1229
|
try:
|
1230
1230
|
p2 = the_traceback.split(', in ')[1].split('", line ')[0]
|
1231
|
-
filename = p2.split(
|
1231
|
+
filename = p2.split(os.sep)[-1]
|
1232
1232
|
sb.cm_filename = filename
|
1233
1233
|
except Exception:
|
1234
1234
|
sb.cm_filename = None
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: seleniumbase
|
3
|
-
Version: 4.32.
|
3
|
+
Version: 4.32.11
|
4
4
|
Summary: A complete web automation framework for end-to-end testing.
|
5
5
|
Home-page: https://github.com/seleniumbase/SeleniumBase
|
6
6
|
Author: Michael Mintz
|
@@ -127,7 +127,7 @@ Requires-Dist: allure-behave>=2.13.5; extra == "allure"
|
|
127
127
|
Provides-Extra: coverage
|
128
128
|
Requires-Dist: coverage>=7.6.1; python_version < "3.9" and extra == "coverage"
|
129
129
|
Requires-Dist: pytest-cov>=5.0.0; python_version < "3.9" and extra == "coverage"
|
130
|
-
Requires-Dist: coverage>=7.6.
|
130
|
+
Requires-Dist: coverage>=7.6.5; python_version >= "3.9" and extra == "coverage"
|
131
131
|
Requires-Dist: pytest-cov>=6.0.0; python_version >= "3.9" and extra == "coverage"
|
132
132
|
Provides-Extra: flake8
|
133
133
|
Requires-Dist: mccabe==0.7.0; extra == "flake8"
|
@@ -3,7 +3,7 @@ sbase/__main__.py,sha256=G0bVB1-DM4PGwQ1KyOupaWCs4ePbChZNNWuX2htim5U,647
|
|
3
3
|
sbase/steps.py,sha256=bKT_u5bJkKzYWEuAXi9NVVRYYxQRCM1_YJUrNFFRVPY,42865
|
4
4
|
seleniumbase/__init__.py,sha256=OtJh8nGKL4xtZpw8KPqmn7Q6R-86t4cWUDyVF5MbMTo,2398
|
5
5
|
seleniumbase/__main__.py,sha256=dn1p6dgCchmcH1zzTzzQvFwwdQQqnTGH6ULV9m4hv24,654
|
6
|
-
seleniumbase/__version__.py,sha256=
|
6
|
+
seleniumbase/__version__.py,sha256=0NN9rH4ffocZPC19OF8zCT06wDT8muncnxK87-frKM8,47
|
7
7
|
seleniumbase/behave/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
8
|
seleniumbase/behave/behave_helper.py,sha256=elkl8P9eLulRAioLstE9baYNM9N_PHBmAOcajX-pH_Y,24198
|
9
9
|
seleniumbase/behave/behave_sb.py,sha256=-hza7Nx2U41mSObYiPMi48v3JlPh3sJO3yzP0kqZ1Gk,59174
|
@@ -36,7 +36,7 @@ seleniumbase/console_scripts/sb_print.py,sha256=tNy-bMDgwHJO3bZxMpmo9weSE8uhbH0C
|
|
36
36
|
seleniumbase/console_scripts/sb_recorder.py,sha256=1oAA4wFzVboNhIFDwJLD3jgy9RuoavywKQG7R67bNZE,10908
|
37
37
|
seleniumbase/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
38
38
|
seleniumbase/core/application_manager.py,sha256=e_0sjtI8cjY5BNyZj1QBR0j6_oCScxGmSXYEpcYwuZE,576
|
39
|
-
seleniumbase/core/browser_launcher.py,sha256=
|
39
|
+
seleniumbase/core/browser_launcher.py,sha256=Lo-R29qNyhNw2mTjm1I8JkwqIVchEHQeJTiE8JVdATE,219934
|
40
40
|
seleniumbase/core/capabilities_parser.py,sha256=meIS2uHapTCq2ldfNAToC7r0cKmZDRXuYNKExM1GHDY,6038
|
41
41
|
seleniumbase/core/colored_traceback.py,sha256=DrRWfg7XEnKcgY59Xj7Jdk09H-XqHYBSUpB-DiZt6iY,2020
|
42
42
|
seleniumbase/core/create_db_tables.sql,sha256=VWPtrdiW_HQ6yETHjqTu-VIrTwvd8I8o1NfBeaVSHpU,972
|
@@ -44,14 +44,14 @@ seleniumbase/core/detect_b_ver.py,sha256=RxeGRMbBUTMrXh5KsS1P1SH7eEKYbzL1vQw1gTd
|
|
44
44
|
seleniumbase/core/download_helper.py,sha256=qSR54kQISucF4RQaLCOuuerSu6DR41juGi_30HVvWYY,2943
|
45
45
|
seleniumbase/core/encoded_images.py,sha256=rDKJ4cNJSuKiRcFViYU7bjyTS9_moI57gUPRXVg3u2k,14209
|
46
46
|
seleniumbase/core/jqc_helper.py,sha256=2DDQr9Q2jSSZqFzX588jLlUM9oJvyrRWq2aORSIPUdI,10322
|
47
|
-
seleniumbase/core/log_helper.py,sha256=
|
47
|
+
seleniumbase/core/log_helper.py,sha256=T_nPPSRSjhqt6TTzVE6pN1owVvIeRBNF5pWK6sl4dMY,22609
|
48
48
|
seleniumbase/core/mysql.py,sha256=8Fzj3p5dhtDWfMpFqFYxpSwa9s1UltiHsWJ56_aPOqk,3993
|
49
49
|
seleniumbase/core/proxy_helper.py,sha256=cXhu8ErK9Vjdm82RMaQj7hEq_yUWizSp6LyiD50Ieu4,8020
|
50
50
|
seleniumbase/core/recorder_helper.py,sha256=fNGjbapXmEsht54x1o6Igk198QdnPxDDnjUOzQxNhNQ,25055
|
51
51
|
seleniumbase/core/report_helper.py,sha256=AIl6Qava2yW1uSzbLpJBlPlYDz0KE-rVhogh8hsGWBo,12201
|
52
52
|
seleniumbase/core/s3_manager.py,sha256=bkeI8I4y19ebWuQG1oEZV5qJbotC6eN8vin31OCNWJk,3521
|
53
|
-
seleniumbase/core/sb_cdp.py,sha256=
|
54
|
-
seleniumbase/core/sb_driver.py,sha256=
|
53
|
+
seleniumbase/core/sb_cdp.py,sha256=zisjMDPULeGZQ48Cdqpa1JE41NYsoR1dVS8OJB2yHZA,63278
|
54
|
+
seleniumbase/core/sb_driver.py,sha256=xMgtvBitEMr73RkqgQLT-3IvkP6sh7cJv-caCUPoO-o,12179
|
55
55
|
seleniumbase/core/session_helper.py,sha256=s9zD3PVZEWVzG2h81cCUskbNWLfdjC_LwwQjKptHCak,558
|
56
56
|
seleniumbase/core/settings_parser.py,sha256=KokVXpCiGZhJ-D4Bo-hizPz5r-iefzWoiTANu9zNaq4,7504
|
57
57
|
seleniumbase/core/style_sheet.py,sha256=tPpJ1xl6Kuw425Z-3Y0OgVRLGXk_ciBDREZjXk_NuPE,11395
|
@@ -65,14 +65,14 @@ seleniumbase/extensions/disable_csp.zip,sha256=YMifIIgEBiLrEFrS1sfW4Exh4br1V4oK1
|
|
65
65
|
seleniumbase/extensions/recorder.zip,sha256=OOyzF-Ize2cSRu1CqhzSAq5vusI9hqLLd2OIApUHesI,11918
|
66
66
|
seleniumbase/extensions/sbase_ext.zip,sha256=3s1N8zrVaMz8RQEOIoBzC3KDjtmHwVZRvVsX25Odr_s,8175
|
67
67
|
seleniumbase/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
68
|
-
seleniumbase/fixtures/base_case.py,sha256=
|
69
|
-
seleniumbase/fixtures/constants.py,sha256=
|
68
|
+
seleniumbase/fixtures/base_case.py,sha256=4NIR3rsLRqLtDLoe67SsLnB6ln3q2ycjyXL5QqboT8Y,713744
|
69
|
+
seleniumbase/fixtures/constants.py,sha256=e1LppavlrAcI4XBJMq7u5j8SffaQ7SPQps1y0YvZYfY,13649
|
70
70
|
seleniumbase/fixtures/css_to_xpath.py,sha256=9ouDB1xl4MJ2os6JOgTIAyHKOQfuxtxvXC3O5hSnEKA,1954
|
71
71
|
seleniumbase/fixtures/errors.py,sha256=KyxuEVx_e3MPhVrJfNIa_3ltMpbCFxfy_jxK8RFNTns,555
|
72
|
-
seleniumbase/fixtures/js_utils.py,sha256=
|
73
|
-
seleniumbase/fixtures/page_actions.py,sha256=
|
72
|
+
seleniumbase/fixtures/js_utils.py,sha256=2l4UY_zUBsMviRoJpLA0z3XxhGeLMWj0Mv07FUR_jzg,50939
|
73
|
+
seleniumbase/fixtures/page_actions.py,sha256=dbp63c-7asYZyd8aOu57Y3dxQQozp_VJsP5h74s1kBA,66552
|
74
74
|
seleniumbase/fixtures/page_utils.py,sha256=5m7iXpikLs80TJoRO6_gEfXE1AKeQgcH1aFbR8o1C9A,12034
|
75
|
-
seleniumbase/fixtures/shared_utils.py,sha256=
|
75
|
+
seleniumbase/fixtures/shared_utils.py,sha256=WbPb15IvIWzRtMInKG8DUzJ26UZU-PixdOwTCjXQirU,7545
|
76
76
|
seleniumbase/fixtures/unittest_helper.py,sha256=sfZ92rZeBAn_sF_yQ3I6_I7h3lyU5-cV_UMegBNoEm8,1294
|
77
77
|
seleniumbase/fixtures/words.py,sha256=FOA4mAYvl3EPVpBTvgvK6YwCL8BdlRCmed685kEe7Vg,7827
|
78
78
|
seleniumbase/fixtures/xpath_to_css.py,sha256=lML56k656fElXJ4NJF07r35FjctrbgQkXUotNk7A-as,8876
|
@@ -90,7 +90,7 @@ seleniumbase/plugins/driver_manager.py,sha256=s20s0pJYaNrG0WNwyIC04oUMRVFjtm6V_n
|
|
90
90
|
seleniumbase/plugins/page_source.py,sha256=loTnXxOj4kxEukuTZEiGyvKBhY3KDVDMnNlHHheTBDE,1889
|
91
91
|
seleniumbase/plugins/pytest_plugin.py,sha256=Up96HY6q3hcPo4LQoEcKqt1hm2OmY5GZz_nMXTqDSXQ,97185
|
92
92
|
seleniumbase/plugins/s3_logging_plugin.py,sha256=WDfertQgGOW_SRJpFMaekYD6vBVW9VO62POtXXy2HCM,2319
|
93
|
-
seleniumbase/plugins/sb_manager.py,sha256=
|
93
|
+
seleniumbase/plugins/sb_manager.py,sha256=lVCPDL0Y1ig2TAOZUlJmMZs2ij-SqhYhaEd_SYZyRfQ,54256
|
94
94
|
seleniumbase/plugins/screen_shots.py,sha256=1hrXw-hzuZ1BR6Yh7AyWX2ABnvnP73-RCbwdz958gj4,1127
|
95
95
|
seleniumbase/plugins/selenium_plugin.py,sha256=GhGW2ATy2kM7UH7NrZ2je402nN2LMlVHpM-yxlU3I9E,59069
|
96
96
|
seleniumbase/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -135,9 +135,9 @@ seleniumbase/utilities/selenium_grid/start-grid-hub.bat,sha256=Ftq-GrAKRYH2ssDPr
|
|
135
135
|
seleniumbase/utilities/selenium_grid/start-grid-hub.sh,sha256=KADv0RUHONLL2_I443QFK8PryBpDmKn5Gy0s4o0vDSM,106
|
136
136
|
seleniumbase/utilities/selenium_ide/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
137
137
|
seleniumbase/utilities/selenium_ide/convert_ide.py,sha256=pZFnqEJQEKZPyNFjkLD29s2HPQgCrWW9XJWpCPhWOoM,31691
|
138
|
-
seleniumbase-4.32.
|
139
|
-
seleniumbase-4.32.
|
140
|
-
seleniumbase-4.32.
|
141
|
-
seleniumbase-4.32.
|
142
|
-
seleniumbase-4.32.
|
143
|
-
seleniumbase-4.32.
|
138
|
+
seleniumbase-4.32.11.dist-info/LICENSE,sha256=odSYtWibXBnQ1gBg6CnDZ82n8kLF_if5-2nbqnEyD8k,1085
|
139
|
+
seleniumbase-4.32.11.dist-info/METADATA,sha256=VuRR7rY9QmKSwRL8cbN6el6Vrw4NFcJ_qYpkxWg_22o,86462
|
140
|
+
seleniumbase-4.32.11.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
|
141
|
+
seleniumbase-4.32.11.dist-info/entry_points.txt,sha256=CNrh2EKNaHYEhO6pP1RJyVLB99LkDDYX7TnUK8xfjqk,623
|
142
|
+
seleniumbase-4.32.11.dist-info/top_level.txt,sha256=4N97aBOQ8ETCnDnokBsWb07lJfTaq3C1ZzYRxvLMxqU,19
|
143
|
+
seleniumbase-4.32.11.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|