seleniumbase 4.33.11__py3-none-any.whl → 4.33.13__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.33.11"
2
+ __version__ = "4.33.13"
@@ -533,10 +533,26 @@ def uc_open_with_cdp_mode(driver, url=None):
533
533
  if url_protocol not in ["about", "data", "chrome"]:
534
534
  safe_url = False
535
535
 
536
+ headless = False
537
+ headed = None
538
+ xvfb = None
539
+ if hasattr(sb_config, "headless"):
540
+ headless = sb_config.headless
541
+ if hasattr(sb_config, "headed"):
542
+ headed = sb_config.headed
543
+ if hasattr(sb_config, "xvfb"):
544
+ xvfb = sb_config.xvfb
545
+
536
546
  loop = asyncio.new_event_loop()
537
547
  asyncio.set_event_loop(loop)
538
548
  driver.cdp_base = loop.run_until_complete(
539
- cdp_util.start(host=cdp_host, port=cdp_port)
549
+ cdp_util.start(
550
+ host=cdp_host,
551
+ port=cdp_port,
552
+ headless=headless,
553
+ headed=headed,
554
+ xvfb=xvfb,
555
+ )
540
556
  )
541
557
  loop.run_until_complete(driver.cdp_base.wait(0))
542
558
 
@@ -863,13 +879,15 @@ def __install_pyautogui_if_missing():
863
879
  xvfb_height = 768
864
880
  sb_config._xvfb_height = xvfb_height
865
881
  with suppress(Exception):
866
- xvfb_display = Display(
882
+ _xvfb_display = Display(
867
883
  visible=True,
868
884
  size=(xvfb_width, xvfb_height),
869
885
  backend="xvfb",
870
886
  use_xauth=True,
871
887
  )
872
- xvfb_display.start()
888
+ _xvfb_display.start()
889
+ sb_config._virtual_display = _xvfb_display
890
+ sb_config.headless_active = True
873
891
 
874
892
 
875
893
  def install_pyautogui_if_missing(driver):
@@ -15,6 +15,11 @@ if sys.version_info >= (3, 11):
15
15
  py311_patch2 = constants.PatchPy311.PATCH
16
16
 
17
17
 
18
+ def __is_cdp_swap_needed(driver):
19
+ """If the driver is disconnected, use a CDP method when available."""
20
+ return shared_utils.is_cdp_swap_needed(driver)
21
+
22
+
18
23
  def log_screenshot(test_logpath, driver, screenshot=None, get=False):
19
24
  screenshot_name = settings.SCREENSHOT_NAME
20
25
  screenshot_path = os.path.join(test_logpath, screenshot_name)
@@ -356,7 +361,11 @@ def log_page_source(test_logpath, driver, source=None):
356
361
  page_source = source
357
362
  else:
358
363
  try:
359
- page_source = driver.page_source
364
+ page_source = None
365
+ if __is_cdp_swap_needed(driver):
366
+ page_source = driver.cdp.get_page_source()
367
+ else:
368
+ page_source = driver.page_source
360
369
  page_source = get_html_source_with_base_href(driver, page_source)
361
370
  except Exception:
362
371
  source = constants.Warnings.PAGE_SOURCE_UNDEFINED
@@ -448,7 +457,11 @@ def get_test_name(test):
448
457
 
449
458
  def get_last_page(driver):
450
459
  try:
451
- last_page = driver.current_url
460
+ last_page = None
461
+ if __is_cdp_swap_needed(driver):
462
+ last_page = driver.cdp.get_current_url()
463
+ else:
464
+ last_page = driver.current_url
452
465
  except Exception:
453
466
  last_page = "[WARNING! Browser Not Open!]"
454
467
  if len(last_page) < 5:
@@ -127,14 +127,14 @@ class CDPMethods():
127
127
  def add_handler(self, event, handler):
128
128
  self.page.add_handler(event, handler)
129
129
 
130
- def find_element(
131
- self, selector, best_match=False, timeout=settings.SMALL_TIMEOUT
132
- ):
130
+ def find_element(self, selector, best_match=False, timeout=None):
133
131
  """Similar to select(), but also finds elements by text content.
134
132
  When using text-based searches, if best_match=False, then will
135
133
  find the first element with the text. If best_match=True, then
136
134
  if multiple elements have that text, then will use the element
137
135
  with the closest text-length to the text being searched for."""
136
+ if not timeout:
137
+ timeout = settings.SMALL_TIMEOUT
138
138
  self.__add_light_pause()
139
139
  selector = self.__convert_to_css_if_xpath(selector)
140
140
  early_failure = False
@@ -167,12 +167,12 @@ class CDPMethods():
167
167
  self.__slow_mode_pause_if_set()
168
168
  return element
169
169
 
170
- def find_element_by_text(
171
- self, text, tag_name=None, timeout=settings.SMALL_TIMEOUT
172
- ):
170
+ def find_element_by_text(self, text, tag_name=None, timeout=None):
173
171
  """Returns an element by matching text.
174
172
  Optionally, provide a tag_name to narrow down the search to an
175
173
  element with the given tag. (Eg: a, button, div, script, span)"""
174
+ if not timeout:
175
+ timeout = settings.SMALL_TIMEOUT
176
176
  self.__add_light_pause()
177
177
  time_now = time.time()
178
178
  self.assert_text(text, timeout=timeout)
@@ -218,7 +218,9 @@ class CDPMethods():
218
218
  % (text, tag_name, timeout, plural)
219
219
  )
220
220
 
221
- def find_all(self, selector, timeout=settings.SMALL_TIMEOUT):
221
+ def find_all(self, selector, timeout=None):
222
+ if not timeout:
223
+ timeout = settings.SMALL_TIMEOUT
222
224
  self.__add_light_pause()
223
225
  selector = self.__convert_to_css_if_xpath(selector)
224
226
  elements = self.loop.run_until_complete(
@@ -272,8 +274,10 @@ class CDPMethods():
272
274
  updated_elements.append(element)
273
275
  return updated_elements
274
276
 
275
- def select(self, selector, timeout=settings.SMALL_TIMEOUT):
277
+ def select(self, selector, timeout=None):
276
278
  """Similar to find_element(), but without text-based search."""
279
+ if not timeout:
280
+ timeout = settings.SMALL_TIMEOUT
277
281
  self.__add_light_pause()
278
282
  selector = self.__convert_to_css_if_xpath(selector)
279
283
  if (":contains(" in selector):
@@ -307,7 +311,9 @@ class CDPMethods():
307
311
  self.__slow_mode_pause_if_set()
308
312
  return element
309
313
 
310
- def select_all(self, selector, timeout=settings.SMALL_TIMEOUT):
314
+ def select_all(self, selector, timeout=None):
315
+ if not timeout:
316
+ timeout = settings.SMALL_TIMEOUT
311
317
  self.__add_light_pause()
312
318
  selector = self.__convert_to_css_if_xpath(selector)
313
319
  elements = self.loop.run_until_complete(
@@ -319,10 +325,14 @@ class CDPMethods():
319
325
  updated_elements.append(element)
320
326
  return updated_elements
321
327
 
322
- def find_elements(self, selector, timeout=settings.SMALL_TIMEOUT):
328
+ def find_elements(self, selector, timeout=None):
329
+ if not timeout:
330
+ timeout = settings.SMALL_TIMEOUT
323
331
  return self.select_all(selector, timeout=timeout)
324
332
 
325
- def find_visible_elements(self, selector, timeout=settings.SMALL_TIMEOUT):
333
+ def find_visible_elements(self, selector, timeout=None):
334
+ if not timeout:
335
+ timeout = settings.SMALL_TIMEOUT
326
336
  visible_elements = []
327
337
  elements = self.select_all(selector, timeout=timeout)
328
338
  for element in elements:
@@ -587,12 +597,12 @@ class CDPMethods():
587
597
  driver.cookies.load(*args, **kwargs)
588
598
  )
589
599
 
590
- def clear_cookies(self, *args, **kwargs):
600
+ def clear_cookies(self):
591
601
  driver = self.driver
592
602
  if hasattr(driver, "cdp_base"):
593
603
  driver = driver.cdp_base
594
604
  return self.loop.run_until_complete(
595
- driver.cookies.clear(*args, **kwargs)
605
+ driver.cookies.clear()
596
606
  )
597
607
 
598
608
  def sleep(self, seconds):
@@ -616,7 +626,9 @@ class CDPMethods():
616
626
  self.page.evaluate(js_code)
617
627
  )
618
628
 
619
- def click(self, selector, timeout=settings.SMALL_TIMEOUT):
629
+ def click(self, selector, timeout=None):
630
+ if not timeout:
631
+ timeout = settings.SMALL_TIMEOUT
620
632
  self.__slow_mode_pause_if_set()
621
633
  element = self.find_element(selector, timeout=timeout)
622
634
  element.scroll_into_view()
@@ -672,8 +684,10 @@ class CDPMethods():
672
684
  except Exception:
673
685
  break
674
686
 
675
- def mouse_click(self, selector, timeout=settings.SMALL_TIMEOUT):
687
+ def mouse_click(self, selector, timeout=None):
676
688
  """(Attempt simulating a mouse click)"""
689
+ if not timeout:
690
+ timeout = settings.SMALL_TIMEOUT
677
691
  self.__slow_mode_pause_if_set()
678
692
  element = self.find_element(selector, timeout=timeout)
679
693
  element.scroll_into_view()
@@ -771,7 +785,9 @@ class CDPMethods():
771
785
  with suppress(Exception):
772
786
  self.loop.run_until_complete(self.page.evaluate(js_code))
773
787
 
774
- def send_keys(self, selector, text, timeout=settings.SMALL_TIMEOUT):
788
+ def send_keys(self, selector, text, timeout=None):
789
+ if not timeout:
790
+ timeout = settings.SMALL_TIMEOUT
775
791
  self.__slow_mode_pause_if_set()
776
792
  element = self.select(selector, timeout=timeout)
777
793
  element.scroll_into_view()
@@ -781,8 +797,10 @@ class CDPMethods():
781
797
  self.__slow_mode_pause_if_set()
782
798
  self.loop.run_until_complete(self.page.wait())
783
799
 
784
- def press_keys(self, selector, text, timeout=settings.SMALL_TIMEOUT):
800
+ def press_keys(self, selector, text, timeout=None):
785
801
  """Similar to send_keys(), but presses keys at human speed."""
802
+ if not timeout:
803
+ timeout = settings.SMALL_TIMEOUT
786
804
  self.__slow_mode_pause_if_set()
787
805
  element = self.select(selector, timeout=timeout)
788
806
  element.scroll_into_view()
@@ -799,8 +817,10 @@ class CDPMethods():
799
817
  self.__slow_mode_pause_if_set()
800
818
  self.loop.run_until_complete(self.page.wait())
801
819
 
802
- def type(self, selector, text, timeout=settings.SMALL_TIMEOUT):
820
+ def type(self, selector, text, timeout=None):
803
821
  """Similar to send_keys(), but clears the text field first."""
822
+ if not timeout:
823
+ timeout = settings.SMALL_TIMEOUT
804
824
  self.__slow_mode_pause_if_set()
805
825
  element = self.select(selector, timeout=timeout)
806
826
  element.scroll_into_view()
@@ -812,8 +832,10 @@ class CDPMethods():
812
832
  self.__slow_mode_pause_if_set()
813
833
  self.loop.run_until_complete(self.page.wait())
814
834
 
815
- def set_value(self, selector, text, timeout=settings.SMALL_TIMEOUT):
835
+ def set_value(self, selector, text, timeout=None):
816
836
  """Similar to send_keys(), but clears the text field first."""
837
+ if not timeout:
838
+ timeout = settings.SMALL_TIMEOUT
817
839
  self.__slow_mode_pause_if_set()
818
840
  selector = self.__convert_to_css_if_xpath(selector)
819
841
  element = self.select(selector, timeout=timeout)
@@ -1036,7 +1058,9 @@ class CDPMethods():
1036
1058
  coordinates["y"] = y if y else 0
1037
1059
  return coordinates
1038
1060
 
1039
- def get_element_rect(self, selector, timeout=settings.SMALL_TIMEOUT):
1061
+ def get_element_rect(self, selector, timeout=None):
1062
+ if not timeout:
1063
+ timeout = settings.SMALL_TIMEOUT
1040
1064
  selector = self.__convert_to_css_if_xpath(selector)
1041
1065
  self.select(selector, timeout=timeout)
1042
1066
  self.__add_light_pause()
@@ -1049,23 +1073,29 @@ class CDPMethods():
1049
1073
  )
1050
1074
  return coordinates
1051
1075
 
1052
- def get_element_size(self, selector):
1053
- element_rect = self.get_element_rect(selector)
1076
+ def get_element_size(self, selector, timeout=None):
1077
+ if not timeout:
1078
+ timeout = settings.SMALL_TIMEOUT
1079
+ element_rect = self.get_element_rect(selector, timeout=timeout)
1054
1080
  coordinates = {}
1055
1081
  coordinates["width"] = element_rect["width"]
1056
1082
  coordinates["height"] = element_rect["height"]
1057
1083
  return coordinates
1058
1084
 
1059
- def get_element_position(self, selector):
1060
- element_rect = self.get_element_rect(selector)
1085
+ def get_element_position(self, selector, timeout=None):
1086
+ if not timeout:
1087
+ timeout = settings.SMALL_TIMEOUT
1088
+ element_rect = self.get_element_rect(selector, timeout=timeout)
1061
1089
  coordinates = {}
1062
1090
  coordinates["x"] = element_rect["x"]
1063
1091
  coordinates["y"] = element_rect["y"]
1064
1092
  return coordinates
1065
1093
 
1066
- def get_gui_element_rect(self, selector):
1094
+ def get_gui_element_rect(self, selector, timeout=None):
1067
1095
  """(Coordinates are relative to the screen. Not the window.)"""
1068
- element_rect = self.get_element_rect(selector)
1096
+ if not timeout:
1097
+ timeout = settings.SMALL_TIMEOUT
1098
+ element_rect = self.get_element_rect(selector, timeout=timeout)
1069
1099
  e_width = element_rect["width"]
1070
1100
  e_height = element_rect["height"]
1071
1101
  window_rect = self.get_window_rect()
@@ -1079,9 +1109,11 @@ class CDPMethods():
1079
1109
  y = y + window_rect["scrollY"]
1080
1110
  return ({"height": e_height, "width": e_width, "x": x, "y": y})
1081
1111
 
1082
- def get_gui_element_center(self, selector):
1112
+ def get_gui_element_center(self, selector, timeout=None):
1083
1113
  """(Coordinates are relative to the screen. Not the window.)"""
1084
- element_rect = self.get_gui_element_rect(selector)
1114
+ if not timeout:
1115
+ timeout = settings.SMALL_TIMEOUT
1116
+ element_rect = self.get_gui_element_rect(selector, timeout=timeout)
1085
1117
  e_width = element_rect["width"]
1086
1118
  e_height = element_rect["height"]
1087
1119
  e_x = element_rect["x"]
@@ -1629,9 +1661,9 @@ class CDPMethods():
1629
1661
  return True
1630
1662
  return False
1631
1663
 
1632
- def wait_for_element_visible(
1633
- self, selector, timeout=settings.SMALL_TIMEOUT
1634
- ):
1664
+ def wait_for_element_visible(self, selector, timeout=None):
1665
+ if not timeout:
1666
+ timeout = settings.SMALL_TIMEOUT
1635
1667
  try:
1636
1668
  self.select(selector, timeout=timeout)
1637
1669
  except Exception:
@@ -1642,8 +1674,10 @@ class CDPMethods():
1642
1674
  time.sleep(0.1)
1643
1675
  raise Exception("Element {%s} was not visible!" % selector)
1644
1676
 
1645
- def assert_element(self, selector, timeout=settings.SMALL_TIMEOUT):
1677
+ def assert_element(self, selector, timeout=None):
1646
1678
  """Same as assert_element_visible()"""
1679
+ if not timeout:
1680
+ timeout = settings.SMALL_TIMEOUT
1647
1681
  try:
1648
1682
  self.select(selector, timeout=timeout)
1649
1683
  except Exception:
@@ -1654,8 +1688,10 @@ class CDPMethods():
1654
1688
  time.sleep(0.1)
1655
1689
  raise Exception("Element {%s} was not visible!" % selector)
1656
1690
 
1657
- def assert_element_visible(self, selector, timeout=settings.SMALL_TIMEOUT):
1691
+ def assert_element_visible(self, selector, timeout=None):
1658
1692
  """Same as assert_element()"""
1693
+ if not timeout:
1694
+ timeout = settings.SMALL_TIMEOUT
1659
1695
  try:
1660
1696
  self.select(selector, timeout=timeout)
1661
1697
  except Exception:
@@ -1666,16 +1702,20 @@ class CDPMethods():
1666
1702
  time.sleep(0.1)
1667
1703
  raise Exception("Element {%s} was not visible!" % selector)
1668
1704
 
1669
- def assert_element_present(self, selector, timeout=settings.SMALL_TIMEOUT):
1705
+ def assert_element_present(self, selector, timeout=None):
1670
1706
  """Assert element is present in the DOM. (Visibility NOT required)"""
1707
+ if not timeout:
1708
+ timeout = settings.SMALL_TIMEOUT
1671
1709
  try:
1672
1710
  self.select(selector, timeout=timeout)
1673
1711
  except Exception:
1674
1712
  raise Exception("Element {%s} was not found!" % selector)
1675
1713
  return True
1676
1714
 
1677
- def assert_element_absent(self, selector, timeout=settings.SMALL_TIMEOUT):
1715
+ def assert_element_absent(self, selector, timeout=None):
1678
1716
  """Assert element is not present in the DOM."""
1717
+ if not timeout:
1718
+ timeout = settings.SMALL_TIMEOUT
1679
1719
  start_ms = time.time() * 1000.0
1680
1720
  stop_ms = start_ms + (timeout * 1000.0)
1681
1721
  for i in range(int(timeout * 10)):
@@ -1693,10 +1733,10 @@ class CDPMethods():
1693
1733
  % (selector, timeout, plural)
1694
1734
  )
1695
1735
 
1696
- def assert_element_not_visible(
1697
- self, selector, timeout=settings.SMALL_TIMEOUT
1698
- ):
1736
+ def assert_element_not_visible(self, selector, timeout=None):
1699
1737
  """Assert element is not visible on page. (May still be in DOM)"""
1738
+ if not timeout:
1739
+ timeout = settings.SMALL_TIMEOUT
1700
1740
  start_ms = time.time() * 1000.0
1701
1741
  stop_ms = start_ms + (timeout * 1000.0)
1702
1742
  for i in range(int(timeout * 10)):
@@ -1791,9 +1831,9 @@ class CDPMethods():
1791
1831
  if expected not in actual:
1792
1832
  raise Exception(error % (expected, actual))
1793
1833
 
1794
- def assert_text(
1795
- self, text, selector="body", timeout=settings.SMALL_TIMEOUT
1796
- ):
1834
+ def assert_text(self, text, selector="body", timeout=None):
1835
+ if not timeout:
1836
+ timeout = settings.SMALL_TIMEOUT
1797
1837
  start_ms = time.time() * 1000.0
1798
1838
  stop_ms = start_ms + (timeout * 1000.0)
1799
1839
  text = text.strip()
@@ -1816,9 +1856,9 @@ class CDPMethods():
1816
1856
  % (text, selector, element.text_all)
1817
1857
  )
1818
1858
 
1819
- def assert_exact_text(
1820
- self, text, selector="body", timeout=settings.SMALL_TIMEOUT
1821
- ):
1859
+ def assert_exact_text(self, text, selector="body", timeout=None):
1860
+ if not timeout:
1861
+ timeout = settings.SMALL_TIMEOUT
1822
1862
  start_ms = time.time() * 1000.0
1823
1863
  stop_ms = start_ms + (timeout * 1000.0)
1824
1864
  text = text.strip()
@@ -4492,7 +4492,8 @@ class BaseCase(unittest.TestCase):
4492
4492
  @Params
4493
4493
  name - The file name to save the current page's HTML to.
4494
4494
  folder - The folder to save the file to. (Default = current folder)"""
4495
- self.wait_for_ready_state_complete()
4495
+ if not self.__is_cdp_swap_needed():
4496
+ self.wait_for_ready_state_complete()
4496
4497
  return page_actions.save_page_source(self.driver, name, folder)
4497
4498
 
4498
4499
  def save_cookies(self, name="cookies.txt"):
@@ -4550,6 +4551,9 @@ class BaseCase(unittest.TestCase):
4550
4551
  def delete_all_cookies(self):
4551
4552
  """Deletes all cookies in the web browser.
4552
4553
  Does NOT delete the saved cookies file."""
4554
+ if self.__is_cdp_swap_needed():
4555
+ self.cdp.clear_cookies()
4556
+ return
4553
4557
  self.wait_for_ready_state_complete()
4554
4558
  self.driver.delete_all_cookies()
4555
4559
  if self.recorder_mode:
@@ -4561,7 +4565,6 @@ class BaseCase(unittest.TestCase):
4561
4565
  def delete_saved_cookies(self, name="cookies.txt"):
4562
4566
  """Deletes the cookies file from the "saved_cookies" folder.
4563
4567
  Does NOT delete the cookies from the web browser."""
4564
- self.wait_for_ready_state_complete()
4565
4568
  if name.endswith("/"):
4566
4569
  raise Exception("Invalid filename for Cookies!")
4567
4570
  if "/" in name:
@@ -4600,14 +4603,20 @@ class BaseCase(unittest.TestCase):
4600
4603
  return json.loads(json_cookies)
4601
4604
 
4602
4605
  def get_cookie(self, name):
4606
+ self.__check_scope()
4607
+ self._check_browser()
4603
4608
  return self.driver.get_cookie(name)
4604
4609
 
4605
4610
  def get_cookies(self):
4611
+ self.__check_scope()
4612
+ self._check_browser()
4606
4613
  return self.driver.get_cookies()
4607
4614
 
4608
4615
  def get_cookie_string(self):
4616
+ self.__check_scope()
4609
4617
  if self.__is_cdp_swap_needed():
4610
4618
  return self.cdp.get_cookie_string()
4619
+ self._check_browser()
4611
4620
  return self.execute_script("return document.cookie;")
4612
4621
 
4613
4622
  def add_cookie(self, cookie_dict, expiry=False):
@@ -4622,6 +4631,8 @@ class BaseCase(unittest.TestCase):
4622
4631
  If expiry > 0: Set "expiry" to expiry minutes in the future.
4623
4632
  If expiry == True: Set "expiry" to 24 hours in the future.
4624
4633
  """
4634
+ self.__check_scope()
4635
+ self._check_browser()
4625
4636
  cookie = cookie_dict
4626
4637
  if "domain" in cookie:
4627
4638
  origin = self.get_origin()
@@ -4646,6 +4657,8 @@ class BaseCase(unittest.TestCase):
4646
4657
  If expiry > 0: Set "expiry" to expiry minutes in the future.
4647
4658
  If expiry == True: Set "expiry" to 24 hours in the future.
4648
4659
  """
4660
+ self.__check_scope()
4661
+ self._check_browser()
4649
4662
  origin = self.get_origin()
4650
4663
  trim_origin = origin.split("://")[-1]
4651
4664
  for cookie in cookies:
@@ -13782,7 +13795,8 @@ class BaseCase(unittest.TestCase):
13782
13795
  if self.get_current_url() == "about:blank":
13783
13796
  self.switch_to_window(current_window)
13784
13797
  except Exception:
13785
- self.switch_to_window(current_window)
13798
+ with suppress(Exception):
13799
+ self.switch_to_window(current_window)
13786
13800
 
13787
13801
  def __needs_minimum_wait(self):
13788
13802
  if (
@@ -13991,9 +14005,10 @@ class BaseCase(unittest.TestCase):
13991
14005
  visible=0, size=(width, height)
13992
14006
  )
13993
14007
  self._xvfb_display.start()
13994
- sb_config._virtual_display = self._xvfb_display
13995
14008
  self.headless_active = True
13996
- sb_config.headless_active = True
14009
+ if not self.undetectable:
14010
+ sb_config._virtual_display = self._xvfb_display
14011
+ sb_config.headless_active = True
13997
14012
 
13998
14013
  def __activate_virtual_display(self):
13999
14014
  if self.undetectable and not (self.headless or self.headless2):
@@ -14016,6 +14031,8 @@ class BaseCase(unittest.TestCase):
14016
14031
  "\nX11 display failed! Will use regular xvfb!"
14017
14032
  )
14018
14033
  self.__activate_standard_virtual_display()
14034
+ else:
14035
+ self.headless_active = True
14019
14036
  except Exception as e:
14020
14037
  if hasattr(e, "msg"):
14021
14038
  print("\n" + str(e.msg))
@@ -16588,6 +16605,7 @@ class BaseCase(unittest.TestCase):
16588
16605
  self.__quit_all_drivers()
16589
16606
  # Resume tearDown() for all test runners, (Pytest / Pynose / Behave)
16590
16607
  if hasattr(self, "_xvfb_display") and self._xvfb_display:
16608
+ # Stop the Xvfb virtual display launched from BaseCase
16591
16609
  try:
16592
16610
  if hasattr(self._xvfb_display, "stop"):
16593
16611
  self._xvfb_display.stop()
@@ -16597,6 +16615,20 @@ class BaseCase(unittest.TestCase):
16597
16615
  pass
16598
16616
  except Exception:
16599
16617
  pass
16618
+ if (
16619
+ hasattr(sb_config, "_virtual_display")
16620
+ and sb_config._virtual_display
16621
+ and hasattr(sb_config._virtual_display, "stop")
16622
+ ):
16623
+ # CDP Mode may launch a 2nd Xvfb virtual display
16624
+ try:
16625
+ sb_config._virtual_display.stop()
16626
+ sb_config._virtual_display = None
16627
+ sb_config.headless_active = False
16628
+ except AttributeError:
16629
+ pass
16630
+ except Exception:
16631
+ pass
16600
16632
  if self.__visual_baseline_copies:
16601
16633
  sb_config._visual_baseline_copies = True
16602
16634
  if has_exception:
@@ -1342,7 +1342,8 @@ def save_page_source(driver, name, folder=None):
1342
1342
  """
1343
1343
  from seleniumbase.core import log_helper
1344
1344
 
1345
- _reconnect_if_disconnected(driver)
1345
+ if not __is_cdp_swap_needed(driver):
1346
+ _reconnect_if_disconnected(driver) # If disconnected without CDP
1346
1347
  if not name.endswith(".html"):
1347
1348
  name = name + ".html"
1348
1349
  if folder:
@@ -1353,7 +1354,11 @@ def save_page_source(driver, name, folder=None):
1353
1354
  html_file_path = os.path.join(file_path, name)
1354
1355
  else:
1355
1356
  html_file_path = name
1356
- page_source = driver.page_source
1357
+ page_source = None
1358
+ if __is_cdp_swap_needed(driver):
1359
+ page_source = driver.cdp.get_page_source()
1360
+ else:
1361
+ page_source = driver.page_source
1357
1362
  html_file = codecs.open(html_file_path, "w+", "utf-8")
1358
1363
  rendered_source = log_helper.get_html_source_with_base_href(
1359
1364
  driver, page_source
@@ -1256,6 +1256,19 @@ def SB(
1256
1256
  print(traceback.format_exc().strip())
1257
1257
  if test and not test_passed:
1258
1258
  print("********** ERROR: The test AND the tearDown() FAILED!")
1259
+ if (
1260
+ hasattr(sb_config, "_virtual_display")
1261
+ and sb_config._virtual_display
1262
+ and hasattr(sb_config._virtual_display, "stop")
1263
+ ):
1264
+ try:
1265
+ sb_config._virtual_display.stop()
1266
+ sb_config._virtual_display = None
1267
+ sb_config.headless_active = False
1268
+ except AttributeError:
1269
+ pass
1270
+ except Exception:
1271
+ pass
1259
1272
  end_time = time.time()
1260
1273
  run_time = end_time - start_time
1261
1274
  sb_config = sb_config_backup
@@ -84,6 +84,9 @@ def __activate_virtual_display_as_needed(
84
84
  "\nX11 display failed! Will use regular xvfb!"
85
85
  )
86
86
  __activate_standard_virtual_display()
87
+ else:
88
+ sb_config._virtual_display = _xvfb_display
89
+ sb_config.headless_active = True
87
90
  except Exception as e:
88
91
  if hasattr(e, "msg"):
89
92
  print("\n" + str(e.msg))
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2014-2024 Michael Mintz
3
+ Copyright (c) 2014-2025 Michael Mintz
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: seleniumbase
3
- Version: 4.33.11
3
+ Version: 4.33.13
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
@@ -62,9 +62,9 @@ License-File: LICENSE
62
62
  Requires-Dist: pip>=24.3.1
63
63
  Requires-Dist: packaging>=24.2
64
64
  Requires-Dist: setuptools~=70.2; python_version < "3.10"
65
- Requires-Dist: setuptools>=75.6.0; python_version >= "3.10"
65
+ Requires-Dist: setuptools>=75.8.0; python_version >= "3.10"
66
66
  Requires-Dist: wheel>=0.45.1
67
- Requires-Dist: attrs>=24.2.0
67
+ Requires-Dist: attrs>=24.3.0
68
68
  Requires-Dist: certifi>=2024.12.14
69
69
  Requires-Dist: exceptiongroup>=1.2.2
70
70
  Requires-Dist: websockets~=13.1; python_version < "3.9"
@@ -75,26 +75,30 @@ Requires-Dist: mycdp>=1.1.0
75
75
  Requires-Dist: pynose>=1.5.3
76
76
  Requires-Dist: platformdirs>=4.3.6
77
77
  Requires-Dist: typing-extensions>=4.12.2
78
- Requires-Dist: sbvirtualdisplay>=1.3.1
78
+ Requires-Dist: sbvirtualdisplay>=1.4.0
79
+ Requires-Dist: MarkupSafe==2.1.5; python_version < "3.9"
80
+ Requires-Dist: MarkupSafe>=3.0.2; python_version >= "3.9"
81
+ Requires-Dist: Jinja2>=3.1.5
79
82
  Requires-Dist: six>=1.17.0
80
83
  Requires-Dist: parse>=1.20.2
81
84
  Requires-Dist: parse-type>=0.6.4
82
85
  Requires-Dist: colorama>=0.4.6
83
86
  Requires-Dist: pyyaml>=6.0.2
84
- Requires-Dist: pygments>=2.18.0
87
+ Requires-Dist: pygments>=2.19.1
85
88
  Requires-Dist: pyreadline3>=3.5.3; platform_system == "Windows"
86
89
  Requires-Dist: tabcompleter>=1.4.0
87
90
  Requires-Dist: pdbp>=1.6.1
88
91
  Requires-Dist: idna==3.10
89
92
  Requires-Dist: chardet==5.2.0
90
- Requires-Dist: charset-normalizer==3.4.0
93
+ Requires-Dist: charset-normalizer==3.4.1
91
94
  Requires-Dist: urllib3<2,>=1.26.20; python_version < "3.10"
92
- Requires-Dist: urllib3<2.3.0,>=1.26.20; python_version >= "3.10"
95
+ Requires-Dist: urllib3<2.4.0,>=1.26.20; python_version >= "3.10"
93
96
  Requires-Dist: requests==2.32.3
94
97
  Requires-Dist: sniffio==1.3.1
95
98
  Requires-Dist: h11==0.14.0
96
99
  Requires-Dist: outcome==1.3.0.post0
97
- Requires-Dist: trio==0.27.0
100
+ Requires-Dist: trio==0.27.0; python_version < "3.9"
101
+ Requires-Dist: trio==0.28.0; python_version >= "3.9"
98
102
  Requires-Dist: trio-websocket==0.11.1
99
103
  Requires-Dist: wsproto==1.2.0
100
104
  Requires-Dist: websocket-client==1.8.0
@@ -126,7 +130,7 @@ Requires-Dist: allure-python-commons>=2.13.5; extra == "allure"
126
130
  Requires-Dist: allure-behave>=2.13.5; extra == "allure"
127
131
  Provides-Extra: coverage
128
132
  Requires-Dist: coverage>=7.6.1; python_version < "3.9" and extra == "coverage"
129
- Requires-Dist: coverage>=7.6.9; python_version >= "3.9" and extra == "coverage"
133
+ Requires-Dist: coverage>=7.6.10; python_version >= "3.9" and extra == "coverage"
130
134
  Requires-Dist: pytest-cov>=5.0.0; python_version < "3.9" and extra == "coverage"
131
135
  Requires-Dist: pytest-cov>=6.0.0; python_version >= "3.9" and extra == "coverage"
132
136
  Provides-Extra: flake8
@@ -150,7 +154,7 @@ Requires-Dist: cffi==1.17.1; extra == "pdfminer"
150
154
  Requires-Dist: pycparser==2.22; extra == "pdfminer"
151
155
  Provides-Extra: pillow
152
156
  Requires-Dist: Pillow>=10.4.0; python_version < "3.9" and extra == "pillow"
153
- Requires-Dist: Pillow>=11.0.0; python_version >= "3.9" and extra == "pillow"
157
+ Requires-Dist: Pillow>=11.1.0; python_version >= "3.9" and extra == "pillow"
154
158
  Provides-Extra: pip-system-certs
155
159
  Requires-Dist: pip-system-certs==4.0; platform_system == "Windows" and extra == "pip-system-certs"
156
160
  Provides-Extra: proxy
@@ -173,6 +177,18 @@ Requires-Dist: hyperframe==6.0.1; extra == "selenium-wire"
173
177
  Requires-Dist: kaitaistruct==0.10; extra == "selenium-wire"
174
178
  Requires-Dist: pyasn1==0.6.1; extra == "selenium-wire"
175
179
  Requires-Dist: zstandard==0.23.0; extra == "selenium-wire"
180
+ Dynamic: author
181
+ Dynamic: author-email
182
+ Dynamic: classifier
183
+ Dynamic: home-page
184
+ Dynamic: keywords
185
+ Dynamic: license
186
+ Dynamic: maintainer
187
+ Dynamic: platform
188
+ Dynamic: provides-extra
189
+ Dynamic: requires-dist
190
+ Dynamic: requires-python
191
+ Dynamic: summary
176
192
 
177
193
  <!-- SeleniumBase Docs -->
178
194
 
@@ -236,7 +252,7 @@ Requires-Dist: zstandard==0.23.0; extra == "selenium-wire"
236
252
 
237
253
  📚 Learn from [**over 200 examples** in the **SeleniumBase/examples/** folder](https://github.com/seleniumbase/SeleniumBase/tree/master/examples).
238
254
 
239
- 🐙 Note that <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/uc_mode.md"><b>UC Mode</b></a> and <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md"><b>CDP Mode</b></a> (Stealth Mode) have separate docs</a>.
255
+ 🐙 Note that <a translate="no" href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/uc_mode.md"><b>UC Mode</b></a> / <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md"><b>CDP Mode</b></a> (Stealth Mode) have their own ReadMe files.
240
256
 
241
257
  ℹ️ Most scripts run with raw <code translate="no"><b>python</b></code>, although some scripts use <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/syntax_formats.md">Syntax Formats</a> that expect <a href="https://docs.pytest.org/en/latest/how-to/usage.html" translate="no"><b>pytest</b></a> (a Python unit-testing framework included with SeleniumBase that can discover, collect, and run tests automatically).
242
258
 
@@ -247,21 +263,37 @@ Requires-Dist: zstandard==0.23.0; extra == "selenium-wire"
247
263
  ```python
248
264
  from seleniumbase import SB
249
265
 
250
- with SB(test=True, ad_block=True, locale_code="en") as sb:
266
+ with SB(test=True) as sb:
251
267
  sb.open("https://google.com/ncr")
252
268
  sb.type('[title="Search"]', "SeleniumBase GitHub page\n")
253
- sb.click('[href*="github.com/seleniumbase/SeleniumBase"]')
254
- sb.save_screenshot_to_logs() # (See ./latest_logs folder)
269
+ sb.click('[href*="github.com/seleniumbase/"]')
270
+ sb.save_screenshot_to_logs() # ./latest_logs/
255
271
  print(sb.get_page_title())
256
272
  ```
257
273
 
258
274
  > `python raw_google.py`
259
275
 
260
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py"><img src="https://seleniumbase.github.io/cdn/gif/google_search.gif" alt="SeleniumBase Test" title="SeleniumBase Test" width="480" /></a>
276
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py"><img src="https://seleniumbase.github.io/cdn/gif/google_search.gif" alt="SeleniumBase Test" title="SeleniumBase Test" width="420" /></a>
261
277
 
262
278
  --------
263
279
 
264
- <p align="left">📗 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_get_swag.py">test_get_swag.py</a>, which tests a fake shopping site:</p>
280
+ <p align="left">📗 Here's an example of bypassing Cloudflare's challenge page: <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/raw_gitlab.py">SeleniumBase/examples/cdp_mode/raw_gitlab.py</a></p>
281
+
282
+ ```python
283
+ from seleniumbase import SB
284
+
285
+ with SB(uc=True, test=True, locale_code="en") as sb:
286
+ url = "https://gitlab.com/users/sign_in"
287
+ sb.activate_cdp_mode(url)
288
+ sb.uc_gui_click_captcha()
289
+ sb.sleep(2)
290
+ ```
291
+
292
+ <img src="https://seleniumbase.github.io/other/cf_sec.jpg" title="SeleniumBase" width="332"> <img src="https://seleniumbase.github.io/other/gitlab_bypass.png" title="SeleniumBase" width="288">
293
+
294
+ --------
295
+
296
+ <p align="left">📗 Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_get_swag.py">test_get_swag.py</a>, which tests an e-commerce site:</p>
265
297
 
266
298
  ```python
267
299
  from seleniumbase import BaseCase
@@ -287,7 +319,7 @@ class MyTestClass(BaseCase):
287
319
 
288
320
  > `pytest test_get_swag.py`
289
321
 
290
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_get_swag.py"><img src="https://seleniumbase.github.io/cdn/gif/fast_swag_2.gif" alt="SeleniumBase Test" title="SeleniumBase Test" width="520" /></a>
322
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_get_swag.py"><img src="https://seleniumbase.github.io/cdn/gif/fast_swag_2.gif" alt="SeleniumBase Test" title="SeleniumBase Test" width="480" /></a>
291
323
 
292
324
  > (The default browser is ``--chrome`` if not set.)
293
325
 
@@ -299,7 +331,7 @@ class MyTestClass(BaseCase):
299
331
  pytest test_coffee_cart.py --demo
300
332
  ```
301
333
 
302
- <p align="left"><a href="https://seleniumbase.io/coffee/" target="_blank"><img src="https://seleniumbase.github.io/cdn/gif/coffee_cart.gif" width="520" alt="SeleniumBase Coffee Cart Test" title="SeleniumBase Coffee Cart Test" /></a></p>
334
+ <p align="left"><a href="https://seleniumbase.io/coffee/" target="_blank"><img src="https://seleniumbase.github.io/cdn/gif/coffee_cart.gif" width="480" alt="SeleniumBase Coffee Cart Test" title="SeleniumBase Coffee Cart Test" /></a></p>
303
335
 
304
336
  > <p>(<code translate="no">--demo</code> mode slows down tests and highlights actions)</p>
305
337
 
@@ -313,7 +345,7 @@ pytest test_coffee_cart.py --demo
313
345
  pytest test_demo_site.py
314
346
  ```
315
347
 
316
- <p align="left"><a href="https://seleniumbase.io/demo_page" target="_blank"><img src="https://seleniumbase.github.io/cdn/gif/demo_page_5.gif" width="520" alt="SeleniumBase Example" title="SeleniumBase Example" /></a></p>
348
+ <p align="left"><a href="https://seleniumbase.io/demo_page" target="_blank"><img src="https://seleniumbase.github.io/cdn/gif/demo_page_5.gif" width="480" alt="SeleniumBase Example" title="SeleniumBase Example" /></a></p>
317
349
 
318
350
  > Easy to type, click, select, toggle, drag & drop, and more.
319
351
 
@@ -569,7 +601,7 @@ cd examples/
569
601
  pytest my_first_test.py
570
602
  ```
571
603
 
572
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/my_first_test.py"><img src="https://seleniumbase.github.io/cdn/gif/fast_swag_2.gif" alt="SeleniumBase Test" title="SeleniumBase Test" width="520" /></a>
604
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/my_first_test.py"><img src="https://seleniumbase.github.io/cdn/gif/fast_swag_2.gif" alt="SeleniumBase Test" title="SeleniumBase Test" width="480" /></a>
573
605
 
574
606
  <p align="left"><b>Here's the full code for <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/my_first_test.py">my_first_test.py</a>:</b></p>
575
607
 
@@ -987,7 +1019,7 @@ You can run it from the ``examples/`` folder like this:
987
1019
  pytest test_fail.py
988
1020
  ```
989
1021
 
990
- 🔵 You'll notice that a logs folder, "latest_logs", was created to hold information about the failing test, and screenshots. During test runs, past results get moved to the archived_logs folder if you have ARCHIVE_EXISTING_LOGS set to True in [settings.py](https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/config/settings.py), or if your run tests with ``--archive-logs``. If you choose not to archive existing logs, they will be deleted and replaced by the logs of the latest test run.
1022
+ 🔵 You'll notice that a logs folder, ``./latest_logs/``, was created to hold information (and screenshots) about the failing test. During test runs, past results get moved to the archived_logs folder if you have ARCHIVE_EXISTING_LOGS set to True in [settings.py](https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/config/settings.py), or if your run tests with ``--archive-logs``. If you choose not to archive existing logs, they will be deleted and replaced by the logs of the latest test run.
991
1023
 
992
1024
  --------
993
1025
 
@@ -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=S1DbyhxNhK6WB7lAkTdc62vKiXt-79j5ugmqsX5eI6A,47
6
+ seleniumbase/__version__.py,sha256=fdIgU6XLjQLyRj6V05cYPC9_n4yf9X6eAsNFamcuZgo,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=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=nQ8-5dvNU4Uy5lSTgnwB2nFAemS43PqJhHccdvdGJ94,224486
39
+ seleniumbase/core/browser_launcher.py,sha256=RqsyaqqFvQ-L9LcVXS8Yr5s9abykUEF5_72RO6cYUqs,224989
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,13 +44,13 @@ 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=N0YbsRy8sEoGQu4BjiAJHC5mK_ydl0YLgRp6jAcwwos,22987
47
+ seleniumbase/core/log_helper.py,sha256=SW8wx2f2HfU3ERbANjxEC-jDbjy_IzaNYRKPlayfRRI,23442
48
48
  seleniumbase/core/mysql.py,sha256=8Fzj3p5dhtDWfMpFqFYxpSwa9s1UltiHsWJ56_aPOqk,3993
49
49
  seleniumbase/core/proxy_helper.py,sha256=kZnfkflB3XhuL2h-3inmx3UOLS8VAZ385BGCc4H8TvU,8267
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=hxMc1BB0vLftcGR70kdwCFt98jmVUhj2vKj5ZusNYQs,74622
53
+ seleniumbase/core/sb_cdp.py,sha256=f6l4GUJP-jg-ivukpbwVLyFNvnlzUnXjm5Y2oUw0I88,76028
54
54
  seleniumbase/core/sb_driver.py,sha256=NGa4adi8OAi2WFtFkEguXg3JCd1p-JuZweIpGNifEfU,13488
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,12 +65,12 @@ 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=Aj3MoG1Q_CTaCSGkhyOIEuRcfogBf-zYYsethFmyKcU,718790
68
+ seleniumbase/fixtures/base_case.py,sha256=IfOwY0b31ngawTZY0thwHvcRGOSCUd647sm_iGKIMk0,719922
69
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
72
  seleniumbase/fixtures/js_utils.py,sha256=asZJ0LDFv2BPQOzUVKK_9ie8ToGcmFousDnGdb3Vabg,51534
73
- seleniumbase/fixtures/page_actions.py,sha256=dbp63c-7asYZyd8aOu57Y3dxQQozp_VJsP5h74s1kBA,66552
73
+ seleniumbase/fixtures/page_actions.py,sha256=LPcFSkUvBkxLrOt4laQHHN-NLmqInT41E2vlPiOlLFY,66753
74
74
  seleniumbase/fixtures/page_utils.py,sha256=5m7iXpikLs80TJoRO6_gEfXE1AKeQgcH1aFbR8o1C9A,12034
75
75
  seleniumbase/fixtures/shared_utils.py,sha256=G6CsE-Adt-GfuZF-71jXWKSIQW7YZPx8FIM24pVd_yI,8368
76
76
  seleniumbase/fixtures/unittest_helper.py,sha256=sfZ92rZeBAn_sF_yQ3I6_I7h3lyU5-cV_UMegBNoEm8,1294
@@ -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=JjpglUqHkfl6rzdg1SkJ7PMtNRpceOgLNbUi2DyKpJI,105416
92
92
  seleniumbase/plugins/s3_logging_plugin.py,sha256=WDfertQgGOW_SRJpFMaekYD6vBVW9VO62POtXXy2HCM,2319
93
- seleniumbase/plugins/sb_manager.py,sha256=qCf6RAkAfziLTGgiJvB3V416RxWoTbRLm9wc-KsB8g8,54419
93
+ seleniumbase/plugins/sb_manager.py,sha256=Z19CfRSaqcxdn_YvzXVt4B9Nu3Bhs97QIO5tHlvbuyk,54871
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
@@ -116,7 +116,7 @@ seleniumbase/undetected/webelement.py,sha256=_s6evgUkdWJpwOnzX4qR9i796PoVbz3txlz
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
118
  seleniumbase/undetected/cdp_driver/browser.py,sha256=quD0e2aoehXQrs9zxGsobF0kZY11gmJ58Q_JQhheQYg,30144
119
- seleniumbase/undetected/cdp_driver/cdp_util.py,sha256=YhtD2Tm6PLIy9VKbgk8lHdGniS3mObyX4yAC1aG0TgQ,16733
119
+ seleniumbase/undetected/cdp_driver/cdp_util.py,sha256=X7bd5qt-kegTiOEcsoLUHrAJ5YTruEub-9oL4TBDTYk,16886
120
120
  seleniumbase/undetected/cdp_driver/config.py,sha256=oHFJ3UH0OmLmEGgG5S6SZwbyBs9ZYMsbUJ02QCA7iZc,12044
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
@@ -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.33.11.dist-info/LICENSE,sha256=odSYtWibXBnQ1gBg6CnDZ82n8kLF_if5-2nbqnEyD8k,1085
139
- seleniumbase-4.33.11.dist-info/METADATA,sha256=DNryNKlBpGpVUrHMTxnc6i6lVMpIda8h0I8rGTqAs1w,85294
140
- seleniumbase-4.33.11.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
141
- seleniumbase-4.33.11.dist-info/entry_points.txt,sha256=CNrh2EKNaHYEhO6pP1RJyVLB99LkDDYX7TnUK8xfjqk,623
142
- seleniumbase-4.33.11.dist-info/top_level.txt,sha256=4N97aBOQ8ETCnDnokBsWb07lJfTaq3C1ZzYRxvLMxqU,19
143
- seleniumbase-4.33.11.dist-info/RECORD,,
138
+ seleniumbase-4.33.13.dist-info/LICENSE,sha256=BRblZsX7HyPUjQmYTiyWr_e9tzWvmR3R4SFclM2R3W0,1085
139
+ seleniumbase-4.33.13.dist-info/METADATA,sha256=bMOMidFBkEka4HeTU6dLn4Vj1JPxenoqxYyRZ66Q8y4,86361
140
+ seleniumbase-4.33.13.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
141
+ seleniumbase-4.33.13.dist-info/entry_points.txt,sha256=CNrh2EKNaHYEhO6pP1RJyVLB99LkDDYX7TnUK8xfjqk,623
142
+ seleniumbase-4.33.13.dist-info/top_level.txt,sha256=4N97aBOQ8ETCnDnokBsWb07lJfTaq3C1ZzYRxvLMxqU,19
143
+ seleniumbase-4.33.13.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5