seleniumbase 4.31.6a4__py3-none-any.whl → 4.32.0__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.
@@ -49,6 +49,8 @@ def is_element_present(driver, selector, by="css selector"):
49
49
  @Returns
50
50
  Boolean (is element present)
51
51
  """
52
+ if __is_cdp_swap_needed(driver):
53
+ return driver.cdp.is_element_present(selector)
52
54
  selector, by = page_utils.swap_selector_and_by_if_reversed(selector, by)
53
55
  try:
54
56
  driver.find_element(by=by, value=selector)
@@ -67,6 +69,8 @@ def is_element_visible(driver, selector, by="css selector"):
67
69
  @Returns
68
70
  Boolean (is element visible)
69
71
  """
72
+ if __is_cdp_swap_needed(driver):
73
+ return driver.cdp.is_element_visible(selector)
70
74
  selector, by = page_utils.swap_selector_and_by_if_reversed(selector, by)
71
75
  try:
72
76
  element = driver.find_element(by=by, value=selector)
@@ -85,6 +89,7 @@ def is_element_clickable(driver, selector, by="css selector"):
85
89
  @Returns
86
90
  Boolean (is element clickable)
87
91
  """
92
+ _reconnect_if_disconnected(driver)
88
93
  try:
89
94
  element = driver.find_element(by=by, value=selector)
90
95
  if element.is_displayed() and element.is_enabled():
@@ -104,6 +109,7 @@ def is_element_enabled(driver, selector, by="css selector"):
104
109
  @Returns
105
110
  Boolean (is element enabled)
106
111
  """
112
+ _reconnect_if_disconnected(driver)
107
113
  try:
108
114
  element = driver.find_element(by=by, value=selector)
109
115
  return element.is_enabled()
@@ -122,6 +128,7 @@ def is_text_visible(driver, text, selector="html", by="css selector"):
122
128
  @Returns
123
129
  Boolean (is text visible)
124
130
  """
131
+ _reconnect_if_disconnected(driver)
125
132
  selector, by = page_utils.swap_selector_and_by_if_reversed(selector, by)
126
133
  text = str(text)
127
134
  try:
@@ -151,6 +158,7 @@ def is_exact_text_visible(driver, text, selector, by="css selector"):
151
158
  @Returns
152
159
  Boolean (is text visible)
153
160
  """
161
+ _reconnect_if_disconnected(driver)
154
162
  selector, by = page_utils.swap_selector_and_by_if_reversed(selector, by)
155
163
  text = str(text)
156
164
  try:
@@ -185,6 +193,7 @@ def is_attribute_present(
185
193
  @Returns
186
194
  Boolean (is attribute present)
187
195
  """
196
+ _reconnect_if_disconnected(driver)
188
197
  try:
189
198
  element = driver.find_element(by=by, value=selector)
190
199
  found_value = element.get_attribute(attribute)
@@ -211,6 +220,7 @@ def is_non_empty_text_visible(driver, selector, by="css selector"):
211
220
  @Returns
212
221
  Boolean (is any text visible in the element with the selector)
213
222
  """
223
+ _reconnect_if_disconnected(driver)
214
224
  try:
215
225
  element = driver.find_element(by=by, value=selector)
216
226
  element_text = element.text
@@ -235,6 +245,7 @@ def hover_on_element(driver, selector, by="css selector"):
235
245
  selector - the locator for identifying the page element (required)
236
246
  by - the type of selector being used (Default: "css selector")
237
247
  """
248
+ _reconnect_if_disconnected(driver)
238
249
  element = driver.find_element(by=by, value=selector)
239
250
  hover = ActionChains(driver).move_to_element(element)
240
251
  hover.perform()
@@ -245,6 +256,7 @@ def hover_element(driver, element):
245
256
  """
246
257
  Similar to hover_on_element(), but uses found element, not a selector.
247
258
  """
259
+ _reconnect_if_disconnected(driver)
248
260
  hover = ActionChains(driver).move_to_element(element)
249
261
  hover.perform()
250
262
  return element
@@ -276,6 +288,7 @@ def hover_and_click(
276
288
  timeout - number of seconds to wait for click element to appear after hover
277
289
  js_click - the option to use js_click() instead of click() on the last part
278
290
  """
291
+ _reconnect_if_disconnected(driver)
279
292
  start_ms = time.time() * 1000.0
280
293
  stop_ms = start_ms + (timeout * 1000.0)
281
294
  element = driver.find_element(by=hover_by, value=hover_selector)
@@ -315,6 +328,7 @@ def hover_element_and_click(
315
328
  """
316
329
  Similar to hover_and_click(), but assumes top element is already found.
317
330
  """
331
+ _reconnect_if_disconnected(driver)
318
332
  start_ms = time.time() * 1000.0
319
333
  stop_ms = start_ms + (timeout * 1000.0)
320
334
  hover = ActionChains(driver).move_to_element(element)
@@ -347,6 +361,7 @@ def hover_element_and_double_click(
347
361
  click_by="css selector",
348
362
  timeout=settings.SMALL_TIMEOUT,
349
363
  ):
364
+ _reconnect_if_disconnected(driver)
350
365
  start_ms = time.time() * 1000.0
351
366
  stop_ms = start_ms + (timeout * 1000.0)
352
367
  hover = ActionChains(driver).move_to_element(element)
@@ -398,6 +413,7 @@ def wait_for_element_present(
398
413
  @Returns
399
414
  A web element object
400
415
  """
416
+ _reconnect_if_disconnected(driver)
401
417
  element = None
402
418
  start_ms = time.time() * 1000.0
403
419
  stop_ms = start_ms + (timeout * 1000.0)
@@ -457,6 +473,7 @@ def wait_for_element_visible(
457
473
  @Returns
458
474
  A web element object
459
475
  """
476
+ _reconnect_if_disconnected(driver)
460
477
  element = None
461
478
  is_present = False
462
479
  start_ms = time.time() * 1000.0
@@ -538,6 +555,7 @@ def wait_for_text_visible(
538
555
  @Returns
539
556
  A web element object that contains the text searched for
540
557
  """
558
+ _reconnect_if_disconnected(driver)
541
559
  element = None
542
560
  is_present = False
543
561
  full_text = None
@@ -648,6 +666,7 @@ def wait_for_exact_text_visible(
648
666
  @Returns
649
667
  A web element object that contains the text searched for
650
668
  """
669
+ _reconnect_if_disconnected(driver)
651
670
  element = None
652
671
  is_present = False
653
672
  actual_text = None
@@ -758,6 +777,7 @@ def wait_for_attribute(
758
777
  @Returns
759
778
  A web element object that contains the expected attribute/value
760
779
  """
780
+ _reconnect_if_disconnected(driver)
761
781
  element = None
762
782
  element_present = False
763
783
  attribute_present = False
@@ -844,6 +864,7 @@ def wait_for_element_clickable(
844
864
  @Returns
845
865
  A web element object
846
866
  """
867
+ _reconnect_if_disconnected(driver)
847
868
  element = None
848
869
  is_present = False
849
870
  is_visible = False
@@ -938,6 +959,7 @@ def wait_for_element_absent(
938
959
  timeout - the time to wait for elements in seconds
939
960
  original_selector - handle pre-converted ":contains(TEXT)" selector
940
961
  """
962
+ _reconnect_if_disconnected(driver)
941
963
  start_ms = time.time() * 1000.0
942
964
  stop_ms = start_ms + (timeout * 1000.0)
943
965
  for x in range(int(timeout * 10)):
@@ -985,6 +1007,7 @@ def wait_for_element_not_visible(
985
1007
  timeout - the time to wait for the element in seconds
986
1008
  original_selector - handle pre-converted ":contains(TEXT)" selector
987
1009
  """
1010
+ _reconnect_if_disconnected(driver)
988
1011
  start_ms = time.time() * 1000.0
989
1012
  stop_ms = start_ms + (timeout * 1000.0)
990
1013
  for x in range(int(timeout * 10)):
@@ -1037,6 +1060,7 @@ def wait_for_text_not_visible(
1037
1060
  @Returns
1038
1061
  A web element object that contains the text searched for
1039
1062
  """
1063
+ _reconnect_if_disconnected(driver)
1040
1064
  text = str(text)
1041
1065
  start_ms = time.time() * 1000.0
1042
1066
  stop_ms = start_ms + (timeout * 1000.0)
@@ -1080,6 +1104,7 @@ def wait_for_exact_text_not_visible(
1080
1104
  @Returns
1081
1105
  A web element object that contains the text searched for
1082
1106
  """
1107
+ _reconnect_if_disconnected(driver)
1083
1108
  text = str(text)
1084
1109
  start_ms = time.time() * 1000.0
1085
1110
  stop_ms = start_ms + (timeout * 1000.0)
@@ -1122,6 +1147,7 @@ def wait_for_non_empty_text_visible(
1122
1147
  @Returns
1123
1148
  The web element object that has text
1124
1149
  """
1150
+ _reconnect_if_disconnected(driver)
1125
1151
  start_ms = time.time() * 1000.0
1126
1152
  stop_ms = start_ms + (timeout * 1000.0)
1127
1153
  element = None
@@ -1239,6 +1265,7 @@ def find_visible_elements(driver, selector, by="css selector", limit=0):
1239
1265
  by - the type of selector being used (Default: "css selector")
1240
1266
  limit - the maximum number of elements to return if > 0.
1241
1267
  """
1268
+ _reconnect_if_disconnected(driver)
1242
1269
  elements = driver.find_elements(by=by, value=selector)
1243
1270
  if limit and limit > 0 and len(elements) > limit:
1244
1271
  elements = elements[:limit]
@@ -1276,6 +1303,7 @@ def save_screenshot(
1276
1303
  If the folder provided doesn't exist, it will get created.
1277
1304
  The screenshot will be in PNG format: (*.png)
1278
1305
  """
1306
+ _reconnect_if_disconnected(driver)
1279
1307
  if not name.endswith(".png"):
1280
1308
  name = name + ".png"
1281
1309
  if folder:
@@ -1314,6 +1342,7 @@ def save_page_source(driver, name, folder=None):
1314
1342
  """
1315
1343
  from seleniumbase.core import log_helper
1316
1344
 
1345
+ _reconnect_if_disconnected(driver)
1317
1346
  if not name.endswith(".html"):
1318
1347
  name = name + ".html"
1319
1348
  if folder:
@@ -1340,6 +1369,7 @@ def wait_for_and_accept_alert(driver, timeout=settings.LARGE_TIMEOUT):
1340
1369
  driver - the webdriver object (required)
1341
1370
  timeout - the time to wait for the alert in seconds
1342
1371
  """
1372
+ _reconnect_if_disconnected(driver)
1343
1373
  alert = wait_for_and_switch_to_alert(driver, timeout)
1344
1374
  alert_text = alert.text
1345
1375
  alert.accept()
@@ -1353,6 +1383,7 @@ def wait_for_and_dismiss_alert(driver, timeout=settings.LARGE_TIMEOUT):
1353
1383
  driver - the webdriver object (required)
1354
1384
  timeout - the time to wait for the alert in seconds
1355
1385
  """
1386
+ _reconnect_if_disconnected(driver)
1356
1387
  alert = wait_for_and_switch_to_alert(driver, timeout)
1357
1388
  alert_text = alert.text
1358
1389
  alert.dismiss()
@@ -1368,6 +1399,7 @@ def wait_for_and_switch_to_alert(driver, timeout=settings.LARGE_TIMEOUT):
1368
1399
  driver - the webdriver object (required)
1369
1400
  timeout - the time to wait for the alert in seconds
1370
1401
  """
1402
+ _reconnect_if_disconnected(driver)
1371
1403
  start_ms = time.time() * 1000.0
1372
1404
  stop_ms = start_ms + (timeout * 1000.0)
1373
1405
  for x in range(int(timeout * 10)):
@@ -1395,6 +1427,7 @@ def switch_to_frame(driver, frame, timeout=settings.SMALL_TIMEOUT):
1395
1427
  frame - the frame element, name, id, index, or selector
1396
1428
  timeout - the time to wait for the alert in seconds
1397
1429
  """
1430
+ _reconnect_if_disconnected(driver)
1398
1431
  start_ms = time.time() * 1000.0
1399
1432
  stop_ms = start_ms + (timeout * 1000.0)
1400
1433
  for x in range(int(timeout * 10)):
@@ -1460,6 +1493,7 @@ def switch_to_window(
1460
1493
  timeout - the time to wait for the window in seconds
1461
1494
  uc_lock - if UC Mode and True, switch_to_window() uses thread-locking
1462
1495
  """
1496
+ _reconnect_if_disconnected(driver)
1463
1497
  if window == -1:
1464
1498
  window = len(driver.window_handles) - 1
1465
1499
  start_ms = time.time() * 1000.0
@@ -1513,11 +1547,36 @@ def switch_to_window(
1513
1547
  timeout_exception(Exception, message)
1514
1548
 
1515
1549
 
1550
+ ############
1551
+
1552
+ # Special methods for use with UC Mode
1553
+
1554
+ def _reconnect_if_disconnected(driver):
1555
+ if (
1556
+ hasattr(driver, "_is_using_uc")
1557
+ and driver._is_using_uc
1558
+ and hasattr(driver, "_is_connected")
1559
+ and not driver._is_connected
1560
+ and hasattr(driver, "is_connected")
1561
+ and not driver.is_connected()
1562
+ ):
1563
+ with suppress(Exception):
1564
+ driver.connect()
1565
+
1566
+
1567
+ def __is_cdp_swap_needed(driver):
1568
+ """If the driver is disconnected, use a CDP method when available."""
1569
+ return shared_utils.is_cdp_swap_needed(driver)
1570
+
1571
+
1516
1572
  ############
1517
1573
 
1518
1574
  # Support methods for direct use from driver
1519
1575
 
1520
1576
  def open_url(driver, url):
1577
+ if __is_cdp_swap_needed(driver):
1578
+ driver.cdp.open(url)
1579
+ return
1521
1580
  url = str(url).strip() # Remove leading and trailing whitespace
1522
1581
  if not page_utils.looks_like_a_page_url(url):
1523
1582
  if page_utils.is_valid_url("https://" + url):
@@ -1527,6 +1586,9 @@ def open_url(driver, url):
1527
1586
 
1528
1587
  def click(driver, selector, by="css selector", timeout=settings.SMALL_TIMEOUT):
1529
1588
  selector, by = page_utils.recalculate_selector(selector, by)
1589
+ if __is_cdp_swap_needed(driver):
1590
+ driver.cdp.click(selector)
1591
+ return
1530
1592
  element = wait_for_element_clickable(
1531
1593
  driver, selector, by=by, timeout=timeout
1532
1594
  )
@@ -1534,6 +1596,9 @@ def click(driver, selector, by="css selector", timeout=settings.SMALL_TIMEOUT):
1534
1596
 
1535
1597
 
1536
1598
  def click_link(driver, link_text, timeout=settings.SMALL_TIMEOUT):
1599
+ if __is_cdp_swap_needed(driver):
1600
+ driver.cdp.click_link(link_text)
1601
+ return
1537
1602
  element = wait_for_element_clickable(
1538
1603
  driver, link_text, by="link text", timeout=timeout
1539
1604
  )
@@ -1544,6 +1609,9 @@ def click_if_visible(
1544
1609
  driver, selector, by="css selector", timeout=0
1545
1610
  ):
1546
1611
  selector, by = page_utils.recalculate_selector(selector, by)
1612
+ if __is_cdp_swap_needed(driver):
1613
+ driver.cdp.click_if_visible(selector)
1614
+ return
1547
1615
  if is_element_visible(driver, selector, by=by):
1548
1616
  click(driver, selector, by=by, timeout=1)
1549
1617
  elif timeout > 0:
@@ -1556,6 +1624,9 @@ def click_if_visible(
1556
1624
 
1557
1625
 
1558
1626
  def click_active_element(driver):
1627
+ if __is_cdp_swap_needed(driver):
1628
+ driver.cdp.click_active_element()
1629
+ return
1559
1630
  driver.execute_script("document.activeElement.click();")
1560
1631
 
1561
1632
 
@@ -1563,6 +1634,9 @@ def js_click(
1563
1634
  driver, selector, by="css selector", timeout=settings.SMALL_TIMEOUT
1564
1635
  ):
1565
1636
  selector, by = page_utils.recalculate_selector(selector, by)
1637
+ if __is_cdp_swap_needed(driver):
1638
+ driver.cdp.click(selector)
1639
+ return
1566
1640
  element = wait_for_element_present(
1567
1641
  driver, selector, by=by, timeout=timeout
1568
1642
  )
@@ -1588,6 +1662,9 @@ def send_keys(
1588
1662
  driver, selector, text, by="css selector", timeout=settings.LARGE_TIMEOUT
1589
1663
  ):
1590
1664
  selector, by = page_utils.recalculate_selector(selector, by)
1665
+ if __is_cdp_swap_needed(driver):
1666
+ driver.cdp.send_keys(selector, text)
1667
+ return
1591
1668
  element = wait_for_element_present(
1592
1669
  driver, selector, by=by, timeout=timeout
1593
1670
  )
@@ -1602,6 +1679,9 @@ def press_keys(
1602
1679
  driver, selector, text, by="css selector", timeout=settings.LARGE_TIMEOUT
1603
1680
  ):
1604
1681
  selector, by = page_utils.recalculate_selector(selector, by)
1682
+ if __is_cdp_swap_needed(driver):
1683
+ driver.cdp.press_keys(selector, text)
1684
+ return
1605
1685
  element = wait_for_element_present(
1606
1686
  driver, selector, by=by, timeout=timeout
1607
1687
  )
@@ -1618,6 +1698,9 @@ def update_text(
1618
1698
  driver, selector, text, by="css selector", timeout=settings.LARGE_TIMEOUT
1619
1699
  ):
1620
1700
  selector, by = page_utils.recalculate_selector(selector, by)
1701
+ if __is_cdp_swap_needed(driver):
1702
+ driver.cdp.type(selector, text)
1703
+ return
1621
1704
  element = wait_for_element_clickable(
1622
1705
  driver, selector, by=by, timeout=timeout
1623
1706
  )
@@ -1631,6 +1714,9 @@ def update_text(
1631
1714
 
1632
1715
  def submit(driver, selector, by="css selector"):
1633
1716
  selector, by = page_utils.recalculate_selector(selector, by)
1717
+ if __is_cdp_swap_needed(driver):
1718
+ driver.cdp.send_keys(selector, "\r\n")
1719
+ return
1634
1720
  element = wait_for_element_clickable(
1635
1721
  driver, selector, by=by, timeout=settings.SMALL_TIMEOUT
1636
1722
  )
@@ -1655,6 +1741,9 @@ def assert_element_visible(
1655
1741
  elif page_utils.is_valid_by(selector):
1656
1742
  original_selector = by
1657
1743
  selector, by = page_utils.recalculate_selector(selector, by)
1744
+ if __is_cdp_swap_needed(driver):
1745
+ driver.cdp.assert_element(selector)
1746
+ return True
1658
1747
  wait_for_element_visible(
1659
1748
  driver,
1660
1749
  selector,
@@ -1673,6 +1762,9 @@ def assert_element_present(
1673
1762
  elif page_utils.is_valid_by(selector):
1674
1763
  original_selector = by
1675
1764
  selector, by = page_utils.recalculate_selector(selector, by)
1765
+ if __is_cdp_swap_needed(driver):
1766
+ driver.cdp.assert_element_present(selector)
1767
+ return True
1676
1768
  wait_for_element_present(
1677
1769
  driver,
1678
1770
  selector,
@@ -1708,6 +1800,9 @@ def assert_text(
1708
1800
  timeout=settings.SMALL_TIMEOUT,
1709
1801
  ):
1710
1802
  selector, by = page_utils.recalculate_selector(selector, by)
1803
+ if __is_cdp_swap_needed(driver):
1804
+ driver.cdp.assert_text(text, selector)
1805
+ return True
1711
1806
  wait_for_text_visible(
1712
1807
  driver, text.strip(), selector, by=by, timeout=timeout
1713
1808
  )
@@ -1721,6 +1816,9 @@ def assert_exact_text(
1721
1816
  timeout=settings.SMALL_TIMEOUT,
1722
1817
  ):
1723
1818
  selector, by = page_utils.recalculate_selector(selector, by)
1819
+ if __is_cdp_swap_needed(driver):
1820
+ driver.cdp.assert_exact_text(text, selector)
1821
+ return True
1724
1822
  wait_for_exact_text_visible(
1725
1823
  driver, text.strip(), selector, by=by, timeout=timeout
1726
1824
  )
@@ -1763,6 +1861,8 @@ def wait_for_element(
1763
1861
  elif page_utils.is_valid_by(selector):
1764
1862
  original_selector = by
1765
1863
  selector, by = page_utils.recalculate_selector(selector, by)
1864
+ if __is_cdp_swap_needed(driver):
1865
+ return driver.cdp.select(selector)
1766
1866
  return wait_for_element_visible(
1767
1867
  driver=driver,
1768
1868
  selector=selector,
@@ -1784,6 +1884,8 @@ def wait_for_selector(
1784
1884
  elif page_utils.is_valid_by(selector):
1785
1885
  original_selector = by
1786
1886
  selector, by = page_utils.recalculate_selector(selector, by)
1887
+ if __is_cdp_swap_needed(driver):
1888
+ return driver.cdp.select(selector)
1787
1889
  return wait_for_element_present(
1788
1890
  driver=driver,
1789
1891
  selector=selector,
@@ -1801,6 +1903,8 @@ def wait_for_text(
1801
1903
  timeout=settings.LARGE_TIMEOUT,
1802
1904
  ):
1803
1905
  selector, by = page_utils.recalculate_selector(selector, by)
1906
+ if __is_cdp_swap_needed(driver):
1907
+ return driver.cdp.find_element(selector)
1804
1908
  return wait_for_text_visible(
1805
1909
  driver=driver,
1806
1910
  text=text,
@@ -1848,6 +1952,8 @@ def get_text(
1848
1952
  by="css selector",
1849
1953
  timeout=settings.LARGE_TIMEOUT
1850
1954
  ):
1955
+ if __is_cdp_swap_needed(driver):
1956
+ return driver.cdp.get_text(selector)
1851
1957
  element = wait_for_element(
1852
1958
  driver=driver,
1853
1959
  selector=selector,
@@ -73,6 +73,32 @@ def fix_colorama_if_windows():
73
73
  colorama.just_fix_windows_console()
74
74
 
75
75
 
76
+ def fix_url_as_needed(url):
77
+ if not url:
78
+ url = "data:,"
79
+ elif url.startswith("//"):
80
+ url = "https:" + url
81
+ elif ":" not in url:
82
+ url = "https://" + url
83
+ return url
84
+
85
+
86
+ def is_cdp_swap_needed(driver):
87
+ """
88
+ When someone is using CDP Mode with a disconnected webdriver,
89
+ but they forget to reconnect before calling a webdriver method,
90
+ this method is used to substitute the webdriver method for a
91
+ CDP Mode method instead, which keeps CDP Stealth Mode enabled.
92
+ For other webdriver methods, SeleniumBase will reconnect first.
93
+ """
94
+ return (
95
+ driver.is_cdp_mode_active()
96
+ # and hasattr(driver, "_is_connected")
97
+ # and not driver._is_connected
98
+ and not driver.is_connected()
99
+ )
100
+
101
+
76
102
  def format_exc(exception, message):
77
103
  """Formats an exception message to make the output cleaner."""
78
104
  from selenium.common.exceptions import ElementNotVisibleException