seleniumbase 4.34.15__py3-none-any.whl → 4.35.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.
@@ -1,2 +1,2 @@
1
1
  # seleniumbase package
2
- __version__ = "4.34.15"
2
+ __version__ = "4.35.0"
@@ -718,7 +718,13 @@ def uc_open_with_cdp_mode(driver, url=None):
718
718
  cdp.is_selected = CDPM.is_selected
719
719
  cdp.is_element_present = CDPM.is_element_present
720
720
  cdp.is_element_visible = CDPM.is_element_visible
721
+ cdp.is_text_visible = CDPM.is_text_visible
722
+ cdp.is_exact_text_visible = CDPM.is_exact_text_visible
723
+ cdp.wait_for_text = CDPM.wait_for_text
724
+ cdp.wait_for_text_not_visible = CDPM.wait_for_text_not_visible
721
725
  cdp.wait_for_element_visible = CDPM.wait_for_element_visible
726
+ cdp.wait_for_element_not_visible = CDPM.wait_for_element_not_visible
727
+ cdp.wait_for_element_absent = CDPM.wait_for_element_absent
722
728
  cdp.assert_element = CDPM.assert_element
723
729
  cdp.assert_element_visible = CDPM.assert_element_visible
724
730
  cdp.assert_element_present = CDPM.assert_element_present
@@ -731,6 +737,7 @@ def uc_open_with_cdp_mode(driver, url=None):
731
737
  cdp.assert_url_contains = CDPM.assert_url_contains
732
738
  cdp.assert_text = CDPM.assert_text
733
739
  cdp.assert_exact_text = CDPM.assert_exact_text
740
+ cdp.assert_text_not_visible = CDPM.assert_text_not_visible
734
741
  cdp.assert_true = CDPM.assert_true
735
742
  cdp.assert_false = CDPM.assert_false
736
743
  cdp.assert_equal = CDPM.assert_equal
@@ -1623,9 +1630,19 @@ def _uc_gui_handle_captcha_(driver, frame="iframe", ctype=None):
1623
1630
  ):
1624
1631
  driver.uc_open_with_disconnect(driver.current_url, 3.8)
1625
1632
  with suppress(Exception):
1633
+ if "--debug" in sys.argv:
1634
+ if sb_config._saved_cf_tab_count == 1:
1635
+ print(' <DEBUG> pyautogui.press("\\t")')
1636
+ else:
1637
+ print(
1638
+ ' <DEBUG> pyautogui.press("\\t") * %s'
1639
+ % sb_config._saved_cf_tab_count
1640
+ )
1626
1641
  for i in range(sb_config._saved_cf_tab_count):
1627
1642
  pyautogui.press("\t")
1628
1643
  time.sleep(0.027)
1644
+ if "--debug" in sys.argv:
1645
+ print(' <DEBUG> pyautogui.press(" ")')
1629
1646
  pyautogui.press(" ")
1630
1647
  else:
1631
1648
  driver.disconnect()
@@ -2280,6 +2297,7 @@ def _set_chrome_options(
2280
2297
  or proxy_string
2281
2298
  ):
2282
2299
  chrome_options.add_argument("--ignore-certificate-errors")
2300
+ chrome_options.add_argument("--ignore-ssl-errors=yes")
2283
2301
  if not enable_ws:
2284
2302
  chrome_options.add_argument("--disable-web-security")
2285
2303
  if (
@@ -2304,7 +2322,14 @@ def _set_chrome_options(
2304
2322
  and not enable_3d_apis
2305
2323
  ):
2306
2324
  chrome_options.add_argument("--disable-gpu")
2307
- if not IS_LINUX and is_using_uc(undetectable, browser_name):
2325
+ if (
2326
+ (not IS_LINUX and is_using_uc(undetectable, browser_name))
2327
+ or (
2328
+ IS_MAC
2329
+ and binary_location
2330
+ and "chrome-headless-shell" in binary_location
2331
+ )
2332
+ ):
2308
2333
  chrome_options.add_argument("--disable-dev-shm-usage")
2309
2334
  chrome_options.add_argument("--disable-application-cache")
2310
2335
  if IS_LINUX:
@@ -4231,6 +4256,7 @@ def get_local_driver(
4231
4256
  edge_options.add_argument("--log-level=3")
4232
4257
  edge_options.add_argument("--no-first-run")
4233
4258
  edge_options.add_argument("--ignore-certificate-errors")
4259
+ edge_options.add_argument("--ignore-ssl-errors=yes")
4234
4260
  if devtools and not headless:
4235
4261
  edge_options.add_argument("--auto-open-devtools-for-tabs")
4236
4262
  edge_options.add_argument("--allow-file-access-from-files")
@@ -56,12 +56,16 @@ class CDPMethods():
56
56
  element, *args, **kwargs
57
57
  )
58
58
  element.focus = lambda: self.__focus(element)
59
+ element.gui_click = (
60
+ lambda *args, **kwargs: self.__gui_click(element, *args, **kwargs)
61
+ )
59
62
  element.highlight_overlay = lambda: self.__highlight_overlay(element)
60
63
  element.mouse_click = lambda: self.__mouse_click(element)
61
64
  element.mouse_drag = (
62
65
  lambda destination: self.__mouse_drag(element, destination)
63
66
  )
64
67
  element.mouse_move = lambda: self.__mouse_move(element)
68
+ element.press_keys = lambda text: self.__press_keys(element, text)
65
69
  element.query_selector = (
66
70
  lambda selector: self.__query_selector(element, selector)
67
71
  )
@@ -211,7 +215,8 @@ class CDPMethods():
211
215
  element = self.__add_sync_methods(element.parent)
212
216
  return self.__add_sync_methods(element)
213
217
  elif (
214
- element.parent.parent
218
+ element.parent
219
+ and element.parent.parent
215
220
  and tag_name in element.parent.parent.tag_name.lower()
216
221
  and text.strip() in element.parent.parent.text
217
222
  ):
@@ -272,7 +277,8 @@ class CDPMethods():
272
277
  if element not in updated_elements:
273
278
  updated_elements.append(element)
274
279
  elif (
275
- element.parent.parent
280
+ element.parent
281
+ and element.parent.parent
276
282
  and tag_name in element.parent.parent.tag_name.lower()
277
283
  and text.strip() in element.parent.parent.text
278
284
  ):
@@ -423,6 +429,39 @@ class CDPMethods():
423
429
  self.loop.run_until_complete(element.focus_async())
424
430
  )
425
431
 
432
+ def __gui_click(self, element, timeframe=None):
433
+ element.scroll_into_view()
434
+ self.__add_light_pause()
435
+ position = element.get_position()
436
+ x = position.x
437
+ y = position.y
438
+ e_width = position.width
439
+ e_height = position.height
440
+ # Relative to window
441
+ element_rect = {"height": e_height, "width": e_width, "x": x, "y": y}
442
+ window_rect = self.get_window_rect()
443
+ w_bottom_y = window_rect["y"] + window_rect["height"]
444
+ viewport_height = window_rect["innerHeight"]
445
+ x = window_rect["x"] + element_rect["x"]
446
+ y = w_bottom_y - viewport_height + element_rect["y"]
447
+ y_scroll_offset = window_rect["pageYOffset"]
448
+ y = y - y_scroll_offset
449
+ x = x + window_rect["scrollX"]
450
+ y = y + window_rect["scrollY"]
451
+ # Relative to screen
452
+ element_rect = {"height": e_height, "width": e_width, "x": x, "y": y}
453
+ e_width = element_rect["width"]
454
+ e_height = element_rect["height"]
455
+ e_x = element_rect["x"]
456
+ e_y = element_rect["y"]
457
+ x, y = ((e_x + e_width / 2.0) + 0.5), ((e_y + e_height / 2.0) + 0.5)
458
+ if not timeframe or not isinstance(timeframe, (int, float)):
459
+ timeframe = 0.25
460
+ if timeframe > 3:
461
+ timeframe = 3
462
+ self.gui_click_x_y(x, y, timeframe=timeframe)
463
+ return self.loop.run_until_complete(self.page.wait())
464
+
426
465
  def __highlight_overlay(self, element):
427
466
  return (
428
467
  self.loop.run_until_complete(element.highlight_overlay_async())
@@ -445,6 +484,21 @@ class CDPMethods():
445
484
  self.loop.run_until_complete(element.mouse_move_async())
446
485
  )
447
486
 
487
+ def __press_keys(self, element, text):
488
+ element.scroll_into_view()
489
+ submit = False
490
+ if text.endswith("\n") or text.endswith("\r"):
491
+ submit = True
492
+ text = text[:-1]
493
+ for key in text:
494
+ element.send_keys(key)
495
+ time.sleep(0.044)
496
+ if submit:
497
+ element.send_keys("\r\n")
498
+ time.sleep(0.044)
499
+ self.__slow_mode_pause_if_set()
500
+ return self.loop.run_until_complete(self.page.sleep(0.025))
501
+
448
502
  def __query_selector(self, element, selector):
449
503
  selector = self.__convert_to_css_if_xpath(selector)
450
504
  element2 = self.loop.run_until_complete(
@@ -810,7 +864,7 @@ class CDPMethods():
810
864
  text = text[:-1] + "\r\n"
811
865
  element.send_keys(text)
812
866
  self.__slow_mode_pause_if_set()
813
- self.loop.run_until_complete(self.page.wait())
867
+ self.loop.run_until_complete(self.page.sleep(0.025))
814
868
 
815
869
  def press_keys(self, selector, text, timeout=None):
816
870
  """Similar to send_keys(), but presses keys at human speed."""
@@ -830,7 +884,7 @@ class CDPMethods():
830
884
  element.send_keys("\r\n")
831
885
  time.sleep(0.044)
832
886
  self.__slow_mode_pause_if_set()
833
- self.loop.run_until_complete(self.page.wait())
887
+ self.loop.run_until_complete(self.page.sleep(0.025))
834
888
 
835
889
  def type(self, selector, text, timeout=None):
836
890
  """Similar to send_keys(), but clears the text field first."""
@@ -845,7 +899,7 @@ class CDPMethods():
845
899
  text = text[:-1] + "\r\n"
846
900
  element.send_keys(text)
847
901
  self.__slow_mode_pause_if_set()
848
- self.loop.run_until_complete(self.page.wait())
902
+ self.loop.run_until_complete(self.page.sleep(0.025))
849
903
 
850
904
  def set_value(self, selector, text, timeout=None):
851
905
  """Similar to send_keys(), but clears the text field first."""
@@ -883,7 +937,7 @@ class CDPMethods():
883
937
  self.__add_light_pause()
884
938
  self.send_keys(selector, "\n")
885
939
  self.__slow_mode_pause_if_set()
886
- self.loop.run_until_complete(self.page.wait())
940
+ self.loop.run_until_complete(self.page.sleep(0.025))
887
941
 
888
942
  def evaluate(self, expression):
889
943
  """Run a JavaScript expression and return the result."""
@@ -1323,7 +1377,7 @@ class CDPMethods():
1323
1377
  pyautogui.press(key)
1324
1378
  time.sleep(0.044)
1325
1379
  self.__slow_mode_pause_if_set()
1326
- self.loop.run_until_complete(self.page.wait())
1380
+ self.loop.run_until_complete(self.page.sleep(0.025))
1327
1381
 
1328
1382
  def gui_press_keys(self, keys):
1329
1383
  self.__install_pyautogui_if_missing()
@@ -1338,7 +1392,7 @@ class CDPMethods():
1338
1392
  pyautogui.press(key)
1339
1393
  time.sleep(0.044)
1340
1394
  self.__slow_mode_pause_if_set()
1341
- self.loop.run_until_complete(self.page.wait())
1395
+ self.loop.run_until_complete(self.page.sleep(0.025))
1342
1396
 
1343
1397
  def gui_write(self, text):
1344
1398
  self.__install_pyautogui_if_missing()
@@ -1351,7 +1405,7 @@ class CDPMethods():
1351
1405
  self.__make_sure_pyautogui_lock_is_writable()
1352
1406
  pyautogui.write(text)
1353
1407
  self.__slow_mode_pause_if_set()
1354
- self.loop.run_until_complete(self.page.wait())
1408
+ self.loop.run_until_complete(self.page.sleep(0.025))
1355
1409
 
1356
1410
  def __gui_click_x_y(self, x, y, timeframe=0.25, uc_lock=False):
1357
1411
  self.__install_pyautogui_if_missing()
@@ -1681,59 +1735,93 @@ class CDPMethods():
1681
1735
  return True
1682
1736
  return False
1683
1737
 
1684
- def wait_for_element_visible(self, selector, timeout=None):
1685
- if not timeout:
1686
- timeout = settings.SMALL_TIMEOUT
1738
+ def is_text_visible(self, text, selector="body"):
1739
+ selector = self.__convert_to_css_if_xpath(selector)
1740
+ text = text.strip()
1741
+ element = None
1687
1742
  try:
1688
- self.select(selector, timeout=timeout)
1743
+ element = self.find_element(selector, timeout=0.1)
1689
1744
  except Exception:
1690
- raise Exception("Element {%s} was not found!" % selector)
1691
- for i in range(30):
1692
- if self.is_element_visible(selector):
1693
- return self.select(selector)
1694
- time.sleep(0.1)
1695
- raise Exception("Element {%s} was not visible!" % selector)
1745
+ return False
1746
+ with suppress(Exception):
1747
+ if text in element.text_all:
1748
+ return True
1749
+ return False
1696
1750
 
1697
- def assert_element(self, selector, timeout=None):
1698
- """Same as assert_element_visible()"""
1751
+ def is_exact_text_visible(self, text, selector="body"):
1752
+ selector = self.__convert_to_css_if_xpath(selector)
1753
+ text = text.strip()
1754
+ element = None
1755
+ try:
1756
+ element = self.find_element(selector, timeout=0.1)
1757
+ except Exception:
1758
+ return False
1759
+ with suppress(Exception):
1760
+ if text == element.text_all.strip():
1761
+ return True
1762
+ return False
1763
+
1764
+ def wait_for_text(self, text, selector="body", timeout=None):
1699
1765
  if not timeout:
1700
1766
  timeout = settings.SMALL_TIMEOUT
1767
+ start_ms = time.time() * 1000.0
1768
+ stop_ms = start_ms + (timeout * 1000.0)
1769
+ text = text.strip()
1770
+ element = None
1701
1771
  try:
1702
- self.select(selector, timeout=timeout)
1772
+ element = self.find_element(selector, timeout=timeout)
1703
1773
  except Exception:
1704
- raise Exception("Element {%s} was not found!" % selector)
1705
- for i in range(30):
1706
- if self.is_element_visible(selector):
1774
+ raise Exception("Element {%s} not found!" % selector)
1775
+ for i in range(int(timeout * 10)):
1776
+ with suppress(Exception):
1777
+ element = self.find_element(selector, timeout=0.1)
1778
+ if text in element.text_all:
1707
1779
  return True
1780
+ now_ms = time.time() * 1000.0
1781
+ if now_ms >= stop_ms:
1782
+ break
1708
1783
  time.sleep(0.1)
1709
- raise Exception("Element {%s} was not visible!" % selector)
1784
+ raise Exception(
1785
+ "Text {%s} not found in {%s}! Actual text: {%s}"
1786
+ % (text, selector, element.text_all)
1787
+ )
1710
1788
 
1711
- def assert_element_visible(self, selector, timeout=None):
1712
- """Same as assert_element()"""
1789
+ def wait_for_text_not_visible(self, text, selector="body", timeout=None):
1713
1790
  if not timeout:
1714
1791
  timeout = settings.SMALL_TIMEOUT
1715
- try:
1716
- self.select(selector, timeout=timeout)
1717
- except Exception:
1718
- raise Exception("Element {%s} was not found!" % selector)
1719
- for i in range(30):
1720
- if self.is_element_visible(selector):
1792
+ text = text.strip()
1793
+ start_ms = time.time() * 1000.0
1794
+ stop_ms = start_ms + (timeout * 1000.0)
1795
+ for i in range(int(timeout * 10)):
1796
+ if not self.is_text_visible(text, selector):
1721
1797
  return True
1798
+ now_ms = time.time() * 1000.0
1799
+ if now_ms >= stop_ms:
1800
+ break
1722
1801
  time.sleep(0.1)
1723
- raise Exception("Element {%s} was not visible!" % selector)
1802
+ plural = "s"
1803
+ if timeout == 1:
1804
+ plural = ""
1805
+ raise Exception(
1806
+ "Text {%s} in {%s} was still visible after %s second%s!"
1807
+ % (text, selector, timeout, plural)
1808
+ )
1724
1809
 
1725
- def assert_element_present(self, selector, timeout=None):
1726
- """Assert element is present in the DOM. (Visibility NOT required)"""
1810
+ def wait_for_element_visible(self, selector, timeout=None):
1727
1811
  if not timeout:
1728
1812
  timeout = settings.SMALL_TIMEOUT
1729
1813
  try:
1730
1814
  self.select(selector, timeout=timeout)
1731
1815
  except Exception:
1732
1816
  raise Exception("Element {%s} was not found!" % selector)
1733
- return True
1817
+ for i in range(30):
1818
+ if self.is_element_visible(selector):
1819
+ return self.select(selector)
1820
+ time.sleep(0.1)
1821
+ raise Exception("Element {%s} was not visible!" % selector)
1734
1822
 
1735
- def assert_element_absent(self, selector, timeout=None):
1736
- """Assert element is not present in the DOM."""
1823
+ def wait_for_element_not_visible(self, selector, timeout=None):
1824
+ """Wait for element to not be visible on page. (May still be in DOM)"""
1737
1825
  if not timeout:
1738
1826
  timeout = settings.SMALL_TIMEOUT
1739
1827
  start_ms = time.time() * 1000.0
@@ -1741,6 +1829,8 @@ class CDPMethods():
1741
1829
  for i in range(int(timeout * 10)):
1742
1830
  if not self.is_element_present(selector):
1743
1831
  return True
1832
+ elif not self.is_element_visible(selector):
1833
+ return True
1744
1834
  now_ms = time.time() * 1000.0
1745
1835
  if now_ms >= stop_ms:
1746
1836
  break
@@ -1749,12 +1839,12 @@ class CDPMethods():
1749
1839
  if timeout == 1:
1750
1840
  plural = ""
1751
1841
  raise Exception(
1752
- "Element {%s} was still present after %s second%s!"
1842
+ "Element {%s} was still visible after %s second%s!"
1753
1843
  % (selector, timeout, plural)
1754
1844
  )
1755
1845
 
1756
- def assert_element_not_visible(self, selector, timeout=None):
1757
- """Assert element is not visible on page. (May still be in DOM)"""
1846
+ def wait_for_element_absent(self, selector, timeout=None):
1847
+ """Wait for element to not be present in the DOM."""
1758
1848
  if not timeout:
1759
1849
  timeout = settings.SMALL_TIMEOUT
1760
1850
  start_ms = time.time() * 1000.0
@@ -1762,8 +1852,6 @@ class CDPMethods():
1762
1852
  for i in range(int(timeout * 10)):
1763
1853
  if not self.is_element_present(selector):
1764
1854
  return True
1765
- elif not self.is_element_visible(selector):
1766
- return True
1767
1855
  now_ms = time.time() * 1000.0
1768
1856
  if now_ms >= stop_ms:
1769
1857
  break
@@ -1772,10 +1860,49 @@ class CDPMethods():
1772
1860
  if timeout == 1:
1773
1861
  plural = ""
1774
1862
  raise Exception(
1775
- "Element {%s} was still visible after %s second%s!"
1863
+ "Element {%s} was still present after %s second%s!"
1776
1864
  % (selector, timeout, plural)
1777
1865
  )
1778
1866
 
1867
+ def assert_element(self, selector, timeout=None):
1868
+ """Same as assert_element_visible()"""
1869
+ self.assert_element_visible(selector, timeout=timeout)
1870
+ return True
1871
+
1872
+ def assert_element_visible(self, selector, timeout=None):
1873
+ """Same as assert_element()"""
1874
+ if not timeout:
1875
+ timeout = settings.SMALL_TIMEOUT
1876
+ try:
1877
+ self.select(selector, timeout=timeout)
1878
+ except Exception:
1879
+ raise Exception("Element {%s} was not found!" % selector)
1880
+ for i in range(30):
1881
+ if self.is_element_visible(selector):
1882
+ return True
1883
+ time.sleep(0.1)
1884
+ raise Exception("Element {%s} was not visible!" % selector)
1885
+
1886
+ def assert_element_present(self, selector, timeout=None):
1887
+ """Assert element is present in the DOM. (Visibility NOT required)"""
1888
+ if not timeout:
1889
+ timeout = settings.SMALL_TIMEOUT
1890
+ try:
1891
+ self.select(selector, timeout=timeout)
1892
+ except Exception:
1893
+ raise Exception("Element {%s} was not found!" % selector)
1894
+ return True
1895
+
1896
+ def assert_element_absent(self, selector, timeout=None):
1897
+ """Assert element is not present in the DOM."""
1898
+ self.wait_for_element_absent(selector, timeout=timeout)
1899
+ return True
1900
+
1901
+ def assert_element_not_visible(self, selector, timeout=None):
1902
+ """Assert element is not visible on page. (May still be in DOM)"""
1903
+ self.wait_for_element_not_visible(selector, timeout=timeout)
1904
+ return True
1905
+
1779
1906
  def assert_element_attribute(self, selector, attribute, value=None):
1780
1907
  attributes = self.get_element_attributes(selector)
1781
1908
  if attribute not in attributes:
@@ -1852,29 +1979,9 @@ class CDPMethods():
1852
1979
  raise Exception(error % (expected, actual))
1853
1980
 
1854
1981
  def assert_text(self, text, selector="body", timeout=None):
1855
- if not timeout:
1856
- timeout = settings.SMALL_TIMEOUT
1857
- start_ms = time.time() * 1000.0
1858
- stop_ms = start_ms + (timeout * 1000.0)
1859
- text = text.strip()
1860
- element = None
1861
- try:
1862
- element = self.find_element(selector, timeout=timeout)
1863
- except Exception:
1864
- raise Exception("Element {%s} not found!" % selector)
1865
- for i in range(int(timeout * 10)):
1866
- with suppress(Exception):
1867
- element = self.find_element(selector, timeout=0.1)
1868
- if text in element.text_all:
1869
- return True
1870
- now_ms = time.time() * 1000.0
1871
- if now_ms >= stop_ms:
1872
- break
1873
- time.sleep(0.1)
1874
- raise Exception(
1875
- "Text {%s} not found in {%s}! Actual text: {%s}"
1876
- % (text, selector, element.text_all)
1877
- )
1982
+ """Same as wait_for_text()"""
1983
+ self.wait_for_text(text, selector=selector, timeout=timeout)
1984
+ return True
1878
1985
 
1879
1986
  def assert_exact_text(self, text, selector="body", timeout=None):
1880
1987
  if not timeout:
@@ -1904,6 +2011,13 @@ class CDPMethods():
1904
2011
  % (text, element.text_all, selector)
1905
2012
  )
1906
2013
 
2014
+ def assert_text_not_visible(self, text, selector="body", timeout=None):
2015
+ """Raises an exception if the text is still visible after timeout."""
2016
+ self.wait_for_text_not_visible(
2017
+ text, selector=selector, timeout=timeout
2018
+ )
2019
+ return True
2020
+
1907
2021
  def assert_true(self, expression):
1908
2022
  if not expression:
1909
2023
  raise AssertionError("%s is not true" % expression)
@@ -1454,6 +1454,8 @@ class BaseCase(unittest.TestCase):
1454
1454
 
1455
1455
  def is_text_visible(self, text, selector="body", by="css selector"):
1456
1456
  """Returns whether the text substring is visible in the element."""
1457
+ if self.__is_cdp_swap_needed():
1458
+ return self.cdp.is_text_visible(text, selector)
1457
1459
  self.wait_for_ready_state_complete()
1458
1460
  time.sleep(0.01)
1459
1461
  selector, by = self.__recalculate_selector(selector, by)
@@ -1464,6 +1466,8 @@ class BaseCase(unittest.TestCase):
1464
1466
  def is_exact_text_visible(self, text, selector="body", by="css selector"):
1465
1467
  """Returns whether the text is exactly equal to the element text.
1466
1468
  (Leading and trailing whitespace is ignored in the verification.)"""
1469
+ if self.__is_cdp_swap_needed():
1470
+ return self.cdp.is_exact_text_visible(text, selector)
1467
1471
  self.wait_for_ready_state_complete()
1468
1472
  time.sleep(0.01)
1469
1473
  selector, by = self.__recalculate_selector(selector, by)
@@ -9120,7 +9124,7 @@ class BaseCase(unittest.TestCase):
9120
9124
  original_selector = selector
9121
9125
  selector, by = self.__recalculate_selector(selector, by)
9122
9126
  if self.__is_cdp_swap_needed():
9123
- self.cdp.assert_element_absent(selector)
9127
+ self.cdp.wait_for_element_absent(selector, timeout=timeout)
9124
9128
  return True
9125
9129
  return page_actions.wait_for_element_absent(
9126
9130
  self.driver,
@@ -9281,7 +9285,8 @@ class BaseCase(unittest.TestCase):
9281
9285
  "bottom_left", "bottom_center", "bottom_right"]
9282
9286
  max_messages: The limit of concurrent messages to display."""
9283
9287
  self.__check_scope()
9284
- self._check_browser()
9288
+ if not self.__is_cdp_swap_needed():
9289
+ self._check_browser()
9285
9290
  if not theme:
9286
9291
  theme = "default" # "flat"
9287
9292
  if not location:
@@ -9308,7 +9313,8 @@ class BaseCase(unittest.TestCase):
9308
9313
  You can also post messages by using =>
9309
9314
  self.execute_script('Messenger().post("My Message")') """
9310
9315
  self.__check_scope()
9311
- self._check_browser()
9316
+ if not self.__is_cdp_swap_needed():
9317
+ self._check_browser()
9312
9318
  if style not in ["info", "success", "error"]:
9313
9319
  style = "info"
9314
9320
  if not duration:
@@ -9579,7 +9585,7 @@ class BaseCase(unittest.TestCase):
9579
9585
  self.assert_elements_present(selector, by=by, timeout=timeout)
9580
9586
  return True
9581
9587
  if self.__is_cdp_swap_needed():
9582
- self.cdp.assert_element_present(selector)
9588
+ self.cdp.assert_element_present(selector, timeout=timeout)
9583
9589
  return True
9584
9590
  if self.__is_shadow_selector(selector):
9585
9591
  self.__assert_shadow_element_present(selector)
@@ -9656,7 +9662,7 @@ class BaseCase(unittest.TestCase):
9656
9662
  if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
9657
9663
  timeout = self.__get_new_timeout(timeout)
9658
9664
  if self.__is_cdp_swap_needed():
9659
- self.cdp.assert_element(selector)
9665
+ self.cdp.assert_element(selector, timeout=timeout)
9660
9666
  return True
9661
9667
  if isinstance(selector, list):
9662
9668
  self.assert_elements(selector, by=by, timeout=timeout)
@@ -9949,7 +9955,7 @@ class BaseCase(unittest.TestCase):
9949
9955
  messenger_post, selector, by
9950
9956
  )
9951
9957
  elif self.__is_cdp_swap_needed():
9952
- self.cdp.assert_text(text, selector)
9958
+ self.cdp.assert_text(text, selector, timeout=timeout)
9953
9959
  return True
9954
9960
  elif not self.is_connected():
9955
9961
  self.connect()
@@ -9999,7 +10005,7 @@ class BaseCase(unittest.TestCase):
9999
10005
  original_selector = selector
10000
10006
  selector, by = self.__recalculate_selector(selector, by)
10001
10007
  if self.__is_cdp_swap_needed():
10002
- self.cdp.assert_exact_text(text, selector)
10008
+ self.cdp.assert_exact_text(text, selector, timeout=timeout)
10003
10009
  return True
10004
10010
  if self.__is_shadow_selector(selector):
10005
10011
  self.__assert_exact_shadow_text_visible(text, selector, timeout)
@@ -10239,6 +10245,9 @@ class BaseCase(unittest.TestCase):
10239
10245
  timeout = self.__get_new_timeout(timeout)
10240
10246
  original_selector = selector
10241
10247
  selector, by = self.__recalculate_selector(selector, by)
10248
+ if self.__is_cdp_swap_needed():
10249
+ self.cdp.wait_for_element_absent(selector, timeout=timeout)
10250
+ return True
10242
10251
  return page_actions.wait_for_element_absent(
10243
10252
  self.driver,
10244
10253
  selector,
@@ -10261,7 +10270,7 @@ class BaseCase(unittest.TestCase):
10261
10270
  if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
10262
10271
  timeout = self.__get_new_timeout(timeout)
10263
10272
  if self.__is_cdp_swap_needed():
10264
- self.cdp.assert_element_absent(selector)
10273
+ self.cdp.assert_element_absent(selector, timeout=timeout)
10265
10274
  return True
10266
10275
  self.wait_for_element_absent(selector, by=by, timeout=timeout)
10267
10276
  return True
@@ -10282,7 +10291,7 @@ class BaseCase(unittest.TestCase):
10282
10291
  original_selector = selector
10283
10292
  selector, by = self.__recalculate_selector(selector, by)
10284
10293
  if self.__is_cdp_swap_needed():
10285
- self.cdp.assert_element_not_visible(selector)
10294
+ self.cdp.wait_for_element_not_visible(selector, timeout=timeout)
10286
10295
  return True
10287
10296
  return page_actions.wait_for_element_not_visible(
10288
10297
  self.driver,
@@ -10304,7 +10313,7 @@ class BaseCase(unittest.TestCase):
10304
10313
  if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
10305
10314
  timeout = self.__get_new_timeout(timeout)
10306
10315
  if self.__is_cdp_swap_needed():
10307
- self.cdp.assert_element_not_visible(selector)
10316
+ self.cdp.assert_element_not_visible(selector, timeout=timeout)
10308
10317
  return True
10309
10318
  self.wait_for_element_not_visible(selector, by=by, timeout=timeout)
10310
10319
  if self.recorder_mode and self.__current_url_is_recordable():
@@ -10326,6 +10335,10 @@ class BaseCase(unittest.TestCase):
10326
10335
  if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
10327
10336
  timeout = self.__get_new_timeout(timeout)
10328
10337
  selector, by = self.__recalculate_selector(selector, by)
10338
+ if self.__is_cdp_swap_needed():
10339
+ return self.cdp.wait_for_text(
10340
+ text, selector=selector, timeout=timeout
10341
+ )
10329
10342
  return page_actions.wait_for_text_not_visible(
10330
10343
  self.driver, text, selector, by, timeout
10331
10344
  )
@@ -13909,7 +13922,8 @@ class BaseCase(unittest.TestCase):
13909
13922
  js_utils.highlight_element_with_js(self.driver, element, loops, o_bs)
13910
13923
 
13911
13924
  def __highlight_with_jquery(self, selector, loops, o_bs):
13912
- self.wait_for_ready_state_complete()
13925
+ if not self.__is_cdp_swap_needed():
13926
+ self.wait_for_ready_state_complete()
13913
13927
  js_utils.highlight_with_jquery(self.driver, selector, loops, o_bs)
13914
13928
 
13915
13929
  def __highlight_with_js_2(self, message, selector, o_bs):
@@ -585,52 +585,60 @@ def highlight_with_jquery(driver, selector, loops=4, o_bs=""):
585
585
  '0px 0px 6px 6px rgba(128, 128, 128, 0.5)');"""
586
586
  % selector
587
587
  )
588
- safe_execute_script(driver, script)
588
+ with suppress(Exception):
589
+ safe_execute_script(driver, script)
589
590
  for n in range(loops):
590
591
  script = (
591
592
  """jQuery('%s').css('box-shadow',
592
593
  '0px 0px 6px 6px rgba(255, 0, 0, 1)');"""
593
594
  % selector
594
595
  )
595
- execute_script(driver, script)
596
+ with suppress(Exception):
597
+ execute_script(driver, script)
596
598
  time.sleep(0.0181)
597
599
  script = (
598
600
  """jQuery('%s').css('box-shadow',
599
601
  '0px 0px 6px 6px rgba(128, 0, 128, 1)');"""
600
602
  % selector
601
603
  )
602
- execute_script(driver, script)
604
+ with suppress(Exception):
605
+ execute_script(driver, script)
603
606
  time.sleep(0.0181)
604
607
  script = (
605
608
  """jQuery('%s').css('box-shadow',
606
609
  '0px 0px 6px 6px rgba(0, 0, 255, 1)');"""
607
610
  % selector
608
611
  )
609
- execute_script(driver, script)
612
+ with suppress(Exception):
613
+ execute_script(driver, script)
610
614
  time.sleep(0.0181)
611
615
  script = (
612
616
  """jQuery('%s').css('box-shadow',
613
617
  '0px 0px 6px 6px rgba(0, 255, 0, 1)');"""
614
618
  % selector
615
619
  )
616
- execute_script(driver, script)
620
+ with suppress(Exception):
621
+ execute_script(driver, script)
617
622
  time.sleep(0.0181)
618
623
  script = (
619
624
  """jQuery('%s').css('box-shadow',
620
625
  '0px 0px 6px 6px rgba(128, 128, 0, 1)');"""
621
626
  % selector
622
627
  )
623
- execute_script(driver, script)
628
+ with suppress(Exception):
629
+ execute_script(driver, script)
624
630
  time.sleep(0.0181)
625
631
  script = (
626
632
  """jQuery('%s').css('box-shadow',
627
633
  '0px 0px 6px 6px rgba(128, 0, 128, 1)');"""
628
634
  % selector
629
635
  )
630
- execute_script(driver, script)
636
+ with suppress(Exception):
637
+ execute_script(driver, script)
631
638
  time.sleep(0.0181)
632
639
  script = """jQuery('%s').css('box-shadow', '%s');""" % (selector, o_bs)
633
- execute_script(driver, script)
640
+ with suppress(Exception):
641
+ execute_script(driver, script)
634
642
 
635
643
 
636
644
  def add_css_link(driver, css_link):
@@ -924,9 +932,20 @@ def post_message(driver, message, msg_dur=None, style="info"):
924
932
  """hideAfter: %s, hideOnNavigate: true});"""
925
933
  % (message, style, msg_dur)
926
934
  )
935
+ retry = False
927
936
  try:
928
937
  execute_script(driver, messenger_script)
938
+ except TypeError as e:
939
+ if (
940
+ shared_utils.is_cdp_swap_needed(driver)
941
+ and "cannot unpack non-iterable" in str(e)
942
+ ):
943
+ pass
944
+ else:
945
+ retry = True
929
946
  except Exception:
947
+ retry = True
948
+ if retry:
930
949
  activate_messenger(driver)
931
950
  set_messenger_theme(driver)
932
951
  try:
@@ -1273,7 +1292,10 @@ def slow_scroll_to_element(driver, element, *args, **kwargs):
1273
1292
  scroll_position = execute_script(driver, "return window.scrollY;")
1274
1293
  element_location_y = None
1275
1294
  try:
1276
- element_location_y = element.location["y"]
1295
+ if shared_utils.is_cdp_swap_needed(driver):
1296
+ element.get_position().y
1297
+ else:
1298
+ element_location_y = element.location["y"]
1277
1299
  except Exception:
1278
1300
  element.location_once_scrolled_into_view
1279
1301
  return
@@ -208,7 +208,6 @@ class Base(Plugin):
208
208
  self.duration = float(0)
209
209
  self.page_results_list = []
210
210
  self.test_count = 0
211
- self.import_error = False
212
211
  log_path = constants.Logs.LATEST + "/"
213
212
  archive_logs = options.archive_logs
214
213
  log_helper.log_folder_setup(log_path, archive_logs)
@@ -238,6 +237,7 @@ class Base(Plugin):
238
237
  )
239
238
  else:
240
239
  variables = {}
240
+ test.test.test_id = test.id()
241
241
  test.test.is_nosetest = True
242
242
  test.test.environment = self.options.environment
243
243
  test.test.env = self.options.environment # Add a shortened version
@@ -263,17 +263,16 @@ class Base(Plugin):
263
263
  )
264
264
  log_helper.clear_empty_logs()
265
265
  if self.report_on:
266
- if not self.import_error:
267
- report_helper.add_bad_page_log_file(self.page_results_list)
268
- report_log_path = report_helper.archive_new_report_logs()
269
- report_helper.build_report(
270
- report_log_path,
271
- self.page_results_list,
272
- self.successes,
273
- self.failures,
274
- self.options.browser,
275
- self.show_report,
276
- )
266
+ report_helper.add_bad_page_log_file(self.page_results_list)
267
+ report_log_path = report_helper.archive_new_report_logs()
268
+ report_helper.build_report(
269
+ report_log_path,
270
+ self.page_results_list,
271
+ self.successes,
272
+ self.failures,
273
+ self.options.browser,
274
+ self.show_report,
275
+ )
277
276
 
278
277
  def addSuccess(self, test, capt):
279
278
  if self.report_on:
@@ -293,9 +292,6 @@ class Base(Plugin):
293
292
  "%.2fs" % (float(time.time()) - float(self.start_time))
294
293
  )
295
294
  if test.id() == "nose.failure.Failure.runTest":
296
- print(">>> ERROR: Could not locate tests to run!")
297
- print(">>> The Test Report WILL NOT be generated!")
298
- self.import_error = True
299
295
  return
300
296
  self.failures.append(test.id())
301
297
  self.page_results_list.append(
@@ -314,6 +310,7 @@ class Base(Plugin):
314
310
  test._log_fail_data()
315
311
  sb_config._excinfo_tb = err
316
312
  log_path = None
313
+ source = None
317
314
  if hasattr(sb_config, "_test_logpath"):
318
315
  log_path = sb_config._test_logpath
319
316
  if hasattr(sb_config, "_last_page_source"):
@@ -1309,6 +1309,7 @@ class SeleniumBrowser(Plugin):
1309
1309
  test.test.dashboard = False
1310
1310
  test.test._multithreaded = False
1311
1311
  test.test._reuse_session = False
1312
+ sb_config.recorder_mode = test.test.recorder_mode
1312
1313
  sb_config.no_screenshot = test.test.no_screenshot_after_test
1313
1314
  if test.test.servername != "localhost":
1314
1315
  # Using Selenium Grid
@@ -265,6 +265,8 @@ class Browser:
265
265
  :param new_window: Open new window
266
266
  :return: Page
267
267
  """
268
+ if url and ":" not in url:
269
+ url = "https://" + url
268
270
  if new_tab or new_window:
269
271
  # Create new target using the browser session.
270
272
  target_id = await self.connection.send(
@@ -4,6 +4,7 @@ import asyncio
4
4
  import fasteners
5
5
  import logging
6
6
  import os
7
+ import sys
7
8
  import time
8
9
  import types
9
10
  import typing
@@ -11,6 +12,7 @@ from contextlib import suppress
11
12
  from seleniumbase import config as sb_config
12
13
  from seleniumbase.config import settings
13
14
  from seleniumbase.core import detect_b_ver
15
+ from seleniumbase.core import proxy_helper
14
16
  from seleniumbase.fixtures import constants
15
17
  from seleniumbase.fixtures import shared_utils
16
18
  from typing import Optional, List, Union, Callable
@@ -23,6 +25,7 @@ import mycdp as cdp
23
25
 
24
26
  logger = logging.getLogger(__name__)
25
27
  IS_LINUX = shared_utils.is_linux()
28
+ PROXY_DIR_LOCK = proxy_helper.PROXY_DIR_LOCK
26
29
  T = typing.TypeVar("T")
27
30
 
28
31
 
@@ -139,6 +142,85 @@ def __activate_virtual_display_as_needed(
139
142
  __activate_standard_virtual_display()
140
143
 
141
144
 
145
+ def __set_proxy_filenames():
146
+ DOWNLOADS_DIR = constants.Files.DOWNLOADS_FOLDER
147
+ for num in range(1000):
148
+ PROXY_DIR_PATH = os.path.join(DOWNLOADS_DIR, "proxy_ext_dir_%s" % num)
149
+ if os.path.exists(PROXY_DIR_PATH):
150
+ continue
151
+ proxy_helper.PROXY_DIR_PATH = PROXY_DIR_PATH
152
+ return
153
+ # Exceeded upper bound. Use Defaults:
154
+ PROXY_DIR_PATH = os.path.join(DOWNLOADS_DIR, "proxy_ext_dir")
155
+ proxy_helper.PROXY_DIR_PATH = PROXY_DIR_PATH
156
+
157
+
158
+ def __add_chrome_ext_dir(extension_dir, dir_path):
159
+ # Add dir_path to the existing extension_dir
160
+ option_exists = False
161
+ if extension_dir:
162
+ option_exists = True
163
+ extension_dir = "%s,%s" % (
164
+ extension_dir, os.path.realpath(dir_path)
165
+ )
166
+ if not option_exists:
167
+ extension_dir = os.path.realpath(dir_path)
168
+ return extension_dir
169
+
170
+
171
+ def __add_chrome_proxy_extension(
172
+ extension_dir,
173
+ proxy_string,
174
+ proxy_user,
175
+ proxy_pass,
176
+ proxy_bypass_list=None,
177
+ multi_proxy=False,
178
+ ):
179
+ """Implementation of https://stackoverflow.com/a/35293284/7058266
180
+ for https://stackoverflow.com/q/12848327/7058266
181
+ (Run Selenium on a proxy server that requires authentication.)"""
182
+ args = " ".join(sys.argv)
183
+ bypass_list = proxy_bypass_list
184
+ if (
185
+ not ("-n" in sys.argv or " -n=" in args or args == "-c")
186
+ and not multi_proxy
187
+ ):
188
+ # Single-threaded
189
+ proxy_dir_lock = fasteners.InterProcessLock(PROXY_DIR_LOCK)
190
+ with proxy_dir_lock:
191
+ proxy_helper.create_proxy_ext(
192
+ proxy_string,
193
+ proxy_user,
194
+ proxy_pass,
195
+ bypass_list,
196
+ zip_it=False,
197
+ )
198
+ proxy_dir_path = proxy_helper.PROXY_DIR_PATH
199
+ extension_dir = __add_chrome_ext_dir(
200
+ extension_dir, proxy_dir_path
201
+ )
202
+ else:
203
+ # Multi-threaded
204
+ proxy_dir_lock = fasteners.InterProcessLock(PROXY_DIR_LOCK)
205
+ with proxy_dir_lock:
206
+ with suppress(Exception):
207
+ shared_utils.make_writable(PROXY_DIR_LOCK)
208
+ if multi_proxy:
209
+ __set_proxy_filenames()
210
+ if not os.path.exists(proxy_helper.PROXY_DIR_PATH):
211
+ proxy_helper.create_proxy_ext(
212
+ proxy_string,
213
+ proxy_user,
214
+ proxy_pass,
215
+ bypass_list,
216
+ zip_it=False,
217
+ )
218
+ extension_dir = __add_chrome_ext_dir(
219
+ extension_dir, proxy_helper.PROXY_DIR_PATH
220
+ )
221
+ return extension_dir
222
+
223
+
142
224
  async def start(
143
225
  config: Optional[Config] = None,
144
226
  *,
@@ -156,6 +238,8 @@ async def start(
156
238
  xvfb: Optional[int] = None, # Use a special virtual display on Linux
157
239
  headed: Optional[bool] = None, # Override default Xvfb mode on Linux
158
240
  expert: Optional[bool] = None, # Open up closed Shadow-root elements
241
+ proxy: Optional[str] = None, # "host:port" or "user:pass@host:port"
242
+ extension_dir: Optional[str] = None, # Chrome extension directory
159
243
  **kwargs: Optional[dict],
160
244
  ) -> Browser:
161
245
  """
@@ -200,6 +284,18 @@ async def start(
200
284
  if IS_LINUX and not headless and not headed and not xvfb:
201
285
  xvfb = True # The default setting on Linux
202
286
  __activate_virtual_display_as_needed(headless, headed, xvfb, xvfb_metrics)
287
+ if proxy and "@" in str(proxy):
288
+ user_with_pass = proxy.split("@")[0]
289
+ if ":" in user_with_pass:
290
+ proxy_user = user_with_pass.split(":")[0]
291
+ proxy_pass = user_with_pass.split(":")[1]
292
+ proxy_string = proxy.split("@")[1]
293
+ extension_dir = __add_chrome_proxy_extension(
294
+ extension_dir,
295
+ proxy_string,
296
+ proxy_user,
297
+ proxy_pass,
298
+ )
203
299
  if not config:
204
300
  config = Config(
205
301
  user_data_dir,
@@ -213,13 +309,19 @@ async def start(
213
309
  host=host,
214
310
  port=port,
215
311
  expert=expert,
312
+ proxy=proxy,
313
+ extension_dir=extension_dir,
216
314
  **kwargs,
217
315
  )
316
+ driver = None
218
317
  try:
219
- return await Browser.create(config)
318
+ driver = await Browser.create(config)
220
319
  except Exception:
221
320
  time.sleep(0.15)
222
- return await Browser.create(config)
321
+ driver = await Browser.create(config)
322
+ if proxy and "@" in str(proxy):
323
+ time.sleep(0.11)
324
+ return driver
223
325
 
224
326
 
225
327
  async def start_async(*args, **kwargs) -> Browser:
@@ -40,6 +40,8 @@ class Config:
40
40
  host: str = AUTO,
41
41
  port: int = AUTO,
42
42
  expert: bool = AUTO,
43
+ proxy: Optional[str] = None,
44
+ extension_dir: Optional[str] = None,
43
45
  **kwargs: dict,
44
46
  ):
45
47
  """
@@ -91,6 +93,8 @@ class Config:
91
93
  self.host = host
92
94
  self.port = port
93
95
  self.expert = expert
96
+ self.proxy = proxy
97
+ self.extension_dir = extension_dir
94
98
  self._extensions = []
95
99
  # When using posix-ish operating system and running as root,
96
100
  # you must use no_sandbox=True
@@ -195,6 +199,12 @@ class Config:
195
199
  "--disable-web-security",
196
200
  "--disable-site-isolation-trials",
197
201
  ]
202
+ if self.proxy:
203
+ args.append("--proxy-server=%s" % self.proxy.split("@")[-1])
204
+ args.append("--ignore-certificate-errors")
205
+ args.append("--ignore-ssl-errors=yes")
206
+ if self.extension_dir:
207
+ args.append("--load-extension=%s" % self.extension_dir)
198
208
  if self._browser_args:
199
209
  args.extend([arg for arg in self._browser_args if arg not in args])
200
210
  if self.headless:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: seleniumbase
3
- Version: 4.34.15
3
+ Version: 4.35.0
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
@@ -68,12 +68,12 @@ Requires-Dist: attrs>=25.1.0
68
68
  Requires-Dist: certifi>=2025.1.31
69
69
  Requires-Dist: exceptiongroup>=1.2.2
70
70
  Requires-Dist: websockets~=13.1; python_version < "3.9"
71
- Requires-Dist: websockets>=14.2; python_version >= "3.9"
71
+ Requires-Dist: websockets>=15.0; python_version >= "3.9"
72
72
  Requires-Dist: filelock~=3.16.1; python_version < "3.9"
73
73
  Requires-Dist: filelock>=3.17.0; python_version >= "3.9"
74
74
  Requires-Dist: fasteners>=0.19
75
75
  Requires-Dist: mycdp>=1.1.0
76
- Requires-Dist: pynose>=1.5.3
76
+ Requires-Dist: pynose>=1.5.4
77
77
  Requires-Dist: platformdirs>=4.3.6
78
78
  Requires-Dist: typing-extensions>=4.12.2
79
79
  Requires-Dist: sbvirtualdisplay>=1.4.0
@@ -99,12 +99,12 @@ Requires-Dist: sniffio==1.3.1
99
99
  Requires-Dist: h11==0.14.0
100
100
  Requires-Dist: outcome==1.3.0.post0
101
101
  Requires-Dist: trio==0.27.0; python_version < "3.9"
102
- Requires-Dist: trio==0.28.0; python_version >= "3.9"
103
- Requires-Dist: trio-websocket==0.11.1
102
+ Requires-Dist: trio==0.29.0; python_version >= "3.9"
103
+ Requires-Dist: trio-websocket==0.12.1
104
104
  Requires-Dist: wsproto==1.2.0
105
105
  Requires-Dist: websocket-client==1.8.0
106
106
  Requires-Dist: selenium==4.27.1; python_version < "3.9"
107
- Requires-Dist: selenium==4.28.1; python_version >= "3.9"
107
+ Requires-Dist: selenium==4.29.0; python_version >= "3.9"
108
108
  Requires-Dist: cssselect==1.2.0
109
109
  Requires-Dist: sortedcontainers==2.4.0
110
110
  Requires-Dist: execnet==2.1.1
@@ -137,7 +137,7 @@ Requires-Dist: pytest-cov>=5.0.0; python_version < "3.9" and extra == "coverage"
137
137
  Requires-Dist: pytest-cov>=6.0.0; python_version >= "3.9" and extra == "coverage"
138
138
  Provides-Extra: flake8
139
139
  Requires-Dist: flake8==5.0.4; python_version < "3.9" and extra == "flake8"
140
- Requires-Dist: flake8==7.1.1; python_version >= "3.9" and extra == "flake8"
140
+ Requires-Dist: flake8==7.1.2; python_version >= "3.9" and extra == "flake8"
141
141
  Requires-Dist: mccabe==0.7.0; extra == "flake8"
142
142
  Requires-Dist: pyflakes==2.5.0; python_version < "3.9" and extra == "flake8"
143
143
  Requires-Dist: pyflakes==3.2.0; python_version >= "3.9" and extra == "flake8"
@@ -3,7 +3,7 @@ sbase/__main__.py,sha256=G0bVB1-DM4PGwQ1KyOupaWCs4ePbChZNNWuX2htim5U,647
3
3
  sbase/steps.py,sha256=_WvAjydKqZfTdnZW9LPKkRty-g-lfdUPmLqnZj6ulcs,43013
4
4
  seleniumbase/__init__.py,sha256=OtJh8nGKL4xtZpw8KPqmn7Q6R-86t4cWUDyVF5MbMTo,2398
5
5
  seleniumbase/__main__.py,sha256=dn1p6dgCchmcH1zzTzzQvFwwdQQqnTGH6ULV9m4hv24,654
6
- seleniumbase/__version__.py,sha256=HQYREOtXe_KHVKfcnng511WpKG975mX8PLrqOajrkgI,47
6
+ seleniumbase/__version__.py,sha256=9RgXYgvnicdq4_gy9e8NFDceDM5_JZE-7snSYmzYXAs,46
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=qQF85LoohJBfrPK5ZcPi50v-pWtOrC9qcN1B3Ki_3tY,59401
@@ -36,7 +36,7 @@ seleniumbase/console_scripts/sb_print.py,sha256=tNy-bMDgwHJO3bZxMpmo9weSE8uhbH0C
36
36
  seleniumbase/console_scripts/sb_recorder.py,sha256=fnHb5-kh11Hit-E9Ha-e4QXzqLcZvtij6mb5qNd4B1Q,11032
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=ahPk232q2gp5H55X5uH1B93IWvFioeuuoGlahgbnNWo,235352
39
+ seleniumbase/core/browser_launcher.py,sha256=jUDL2RlOXnSDUwhQuZekgGisY11hhmMU-ftFVyM-afs,236519
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
@@ -50,7 +50,7 @@ seleniumbase/core/proxy_helper.py,sha256=4VkpMwavz0fx8wcOqJ_jyBT0HIXwcxmAcpd1gjJ
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=r9sv8WjwLhS_AFLn4QGLvbK4osfaC6ncRJRj0asrBvI,76754
53
+ seleniumbase/core/sb_cdp.py,sha256=vxgI2BLs-MyYOPsdgytBVBrMD1Outo0GvxfwbkWt4xQ,81129
54
54
  seleniumbase/core/sb_driver.py,sha256=yvTDRblBzG6bDX7XcLiAA6QcBelSJj_HHL_04lcfeeE,13760
55
55
  seleniumbase/core/session_helper.py,sha256=s9zD3PVZEWVzG2h81cCUskbNWLfdjC_LwwQjKptHCak,558
56
56
  seleniumbase/core/settings_parser.py,sha256=gqVohHVlE_5L5Cqe2L24uYrRzvoK-saX8E_Df7_-_3I,7609
@@ -65,11 +65,11 @@ seleniumbase/extensions/disable_csp.zip,sha256=5RvomXnm2PdivUVcxTV6jfvD8WhTEsQYH
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=0bW99a1g8YH5YCXLnsJvZ5uSXvLOmY6QutDEpxDjX9U,721561
68
+ seleniumbase/fixtures/base_case.py,sha256=ncejN3q7m6_GHQTASuy4LHkeeCn829RRZN4lRB0-MkA,722341
69
69
  seleniumbase/fixtures/constants.py,sha256=WMrItuNyKq3XVJ64NluLIRc4gJCxDw8K8qXED0b9S2w,13752
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=asZJ0LDFv2BPQOzUVKK_9ie8ToGcmFousDnGdb3Vabg,51534
72
+ seleniumbase/fixtures/js_utils.py,sha256=QxHC0Wz_rDQ5dB6B1CK_UFs9zzryuElr-fj7MUtf_lA,52204
73
73
  seleniumbase/fixtures/page_actions.py,sha256=LPcFSkUvBkxLrOt4laQHHN-NLmqInT41E2vlPiOlLFY,66753
74
74
  seleniumbase/fixtures/page_utils.py,sha256=H1iV8f9vDyEy87DBntyiBXC_tg8HskcebUOAJVn0hxE,12160
75
75
  seleniumbase/fixtures/shared_utils.py,sha256=G6CsE-Adt-GfuZF-71jXWKSIQW7YZPx8FIM24pVd_yI,8368
@@ -83,7 +83,7 @@ seleniumbase/js_code/recorder_js.py,sha256=ApFNh6DImuPGmaydvq8OOzGixc0t-xdYSCzfQ
83
83
  seleniumbase/masterqa/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
84
84
  seleniumbase/masterqa/master_qa.py,sha256=jLWmAx32Rnu1IhmvrRt8BbsUIcDW5xYj2ouVozny-Y4,19258
85
85
  seleniumbase/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
86
- seleniumbase/plugins/base_plugin.py,sha256=FemdftNhOaTfQIw5bWcJQPPPGQ3P0_sMEI_YYDuzZgU,14972
86
+ seleniumbase/plugins/base_plugin.py,sha256=ItLgtaZmu_363iycy8BNX0Do5LyIWGiTMLW6krXM-WQ,14748
87
87
  seleniumbase/plugins/basic_test_info.py,sha256=8ov6n417gPbqqvrlT4zrch7l2XcRt-GF2ny6rR9AMWk,2108
88
88
  seleniumbase/plugins/db_reporting_plugin.py,sha256=En09qUCoojrk9-vbcnsoHdSELoGmag2GDIyu3jTiJas,7331
89
89
  seleniumbase/plugins/driver_manager.py,sha256=QGGekWvcj58VMGr87UyXl1OvVTMjZDEdt8jaq7K13u8,35863
@@ -92,7 +92,7 @@ seleniumbase/plugins/pytest_plugin.py,sha256=SKCHzUFSd8dHPQwYQTJp-6AX7YD6Kce-Mem
92
92
  seleniumbase/plugins/s3_logging_plugin.py,sha256=WDfertQgGOW_SRJpFMaekYD6vBVW9VO62POtXXy2HCM,2319
93
93
  seleniumbase/plugins/sb_manager.py,sha256=aOaP5ZxLM7EfpLml4f_iBXkidKtFA1KcZQQIGm4aSQQ,56242
94
94
  seleniumbase/plugins/screen_shots.py,sha256=1hrXw-hzuZ1BR6Yh7AyWX2ABnvnP73-RCbwdz958gj4,1127
95
- seleniumbase/plugins/selenium_plugin.py,sha256=qpbP4pMGGdM2s_YWWNzgZQx9pLGETW6H3_Gbx2FQ57o,60023
95
+ seleniumbase/plugins/selenium_plugin.py,sha256=y0eNco8T4KgGLProLPHPLw479QH5lRms4wqwOnTgkSc,60081
96
96
  seleniumbase/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
97
97
  seleniumbase/translate/__init__.py,sha256=N2i5XntTwJZmwr9-qvdX5gC6Rdm5-ClIbnQ8yyPn4Oo,459
98
98
  seleniumbase/translate/chinese.py,sha256=0QhK2eadtsdN4KCvwki1J7jBCe8I4xxWbKzteJKJozY,24698
@@ -115,9 +115,9 @@ seleniumbase/undetected/reactor.py,sha256=NropaXcO54pzmDq6quR27qPJxab6636H7LRAaq
115
115
  seleniumbase/undetected/webelement.py,sha256=OOpUYbEiOG52KsYYyuDW9tYLdA2SMnukvwQHUdPVn9E,1389
116
116
  seleniumbase/undetected/cdp_driver/__init__.py,sha256=c0TjMwPfVFyoqYOJ7PQ-Jln_L_dpN3ebHyaD-juQoM0,64
117
117
  seleniumbase/undetected/cdp_driver/_contradict.py,sha256=lP4b0h5quAy573ETn_TBbYV889cL1AuPLVInpJ0ZkiU,3183
118
- seleniumbase/undetected/cdp_driver/browser.py,sha256=vwccwrAZDssRmVnf-NVXYvs5Dvv8DtGzeiDHSY3RTfM,30189
119
- seleniumbase/undetected/cdp_driver/cdp_util.py,sha256=B5myq2zi-Gdq_vfZGPOG-LTSwbhK4n2h6SY2Z9dmIzQ,17784
120
- seleniumbase/undetected/cdp_driver/config.py,sha256=oHFJ3UH0OmLmEGgG5S6SZwbyBs9ZYMsbUJ02QCA7iZc,12044
118
+ seleniumbase/undetected/cdp_driver/browser.py,sha256=ruPunmJKwE67Veh1MjSkZAF5W38FMwc32lHgy1YULho,30261
119
+ seleniumbase/undetected/cdp_driver/cdp_util.py,sha256=zlYc_oTqtCSjV_T7lzPbFyJlj_78NHMxKkrpleXcfpQ,21374
120
+ seleniumbase/undetected/cdp_driver/config.py,sha256=t8KV1Vqa5SQRBq3-gjkHHmj9h85AplAM01asO3AWufs,12507
121
121
  seleniumbase/undetected/cdp_driver/connection.py,sha256=sOTUGjbUqKA2hPvDcRCdqw1VQjVGJs7mbgVvzS7ldtE,23360
122
122
  seleniumbase/undetected/cdp_driver/element.py,sha256=FIC6v7OmumLCT-_vIc3H4oju_oBbaLpWJUJIKm2c_q4,40467
123
123
  seleniumbase/undetected/cdp_driver/tab.py,sha256=rcASsWY_mC7L0wXpFSWM5mtojzA47qG9BWEMXe7ZGF8,50906
@@ -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.34.15.dist-info/LICENSE,sha256=BRblZsX7HyPUjQmYTiyWr_e9tzWvmR3R4SFclM2R3W0,1085
139
- seleniumbase-4.34.15.dist-info/METADATA,sha256=KFp4laKW_MENuhZdfslrP38qajSDf88F7Yb8HJ9loM8,86522
140
- seleniumbase-4.34.15.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
141
- seleniumbase-4.34.15.dist-info/entry_points.txt,sha256=CNrh2EKNaHYEhO6pP1RJyVLB99LkDDYX7TnUK8xfjqk,623
142
- seleniumbase-4.34.15.dist-info/top_level.txt,sha256=4N97aBOQ8ETCnDnokBsWb07lJfTaq3C1ZzYRxvLMxqU,19
143
- seleniumbase-4.34.15.dist-info/RECORD,,
138
+ seleniumbase-4.35.0.dist-info/LICENSE,sha256=BRblZsX7HyPUjQmYTiyWr_e9tzWvmR3R4SFclM2R3W0,1085
139
+ seleniumbase-4.35.0.dist-info/METADATA,sha256=EeKLn-w_eOXpmkxalRWbl9_cFlbJsGdKUsNgqskwprQ,86521
140
+ seleniumbase-4.35.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
141
+ seleniumbase-4.35.0.dist-info/entry_points.txt,sha256=CNrh2EKNaHYEhO6pP1RJyVLB99LkDDYX7TnUK8xfjqk,623
142
+ seleniumbase-4.35.0.dist-info/top_level.txt,sha256=4N97aBOQ8ETCnDnokBsWb07lJfTaq3C1ZzYRxvLMxqU,19
143
+ seleniumbase-4.35.0.dist-info/RECORD,,