seleniumbase 4.32.9__py3-none-any.whl → 4.32.10a1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,2 +1,2 @@
1
1
  # seleniumbase package
2
- __version__ = "4.32.9"
2
+ __version__ = "4.32.10a1"
@@ -603,6 +603,7 @@ def uc_open_with_cdp_mode(driver, url=None):
603
603
  cdp.click = CDPM.click
604
604
  cdp.click_active_element = CDPM.click_active_element
605
605
  cdp.click_if_visible = CDPM.click_if_visible
606
+ cdp.click_visible_elements = CDPM.click_visible_elements
606
607
  cdp.mouse_click = CDPM.mouse_click
607
608
  cdp.remove_element = CDPM.remove_element
608
609
  cdp.remove_from_dom = CDPM.remove_from_dom
@@ -611,6 +612,7 @@ def uc_open_with_cdp_mode(driver, url=None):
611
612
  cdp.send_keys = CDPM.send_keys
612
613
  cdp.press_keys = CDPM.press_keys
613
614
  cdp.type = CDPM.type
615
+ cdp.set_value = CDPM.set_value
614
616
  cdp.evaluate = CDPM.evaluate
615
617
  cdp.js_dumps = CDPM.js_dumps
616
618
  cdp.maximize = CDPM.maximize
@@ -625,6 +627,11 @@ def uc_open_with_cdp_mode(driver, url=None):
625
627
  cdp.gui_write = CDPM.gui_write
626
628
  cdp.gui_click_x_y = CDPM.gui_click_x_y
627
629
  cdp.gui_click_element = CDPM.gui_click_element
630
+ cdp.gui_drag_drop_points = CDPM.gui_drag_drop_points
631
+ cdp.gui_drag_and_drop = CDPM.gui_drag_and_drop
632
+ cdp.gui_hover_x_y = CDPM.gui_hover_x_y
633
+ cdp.gui_hover_element = CDPM.gui_hover_element
634
+ cdp.gui_hover_and_click = CDPM.gui_hover_and_click
628
635
  cdp.internalize_links = CDPM.internalize_links
629
636
  cdp.get_window = CDPM.get_window
630
637
  cdp.get_element_attributes = CDPM.get_element_attributes
@@ -651,7 +658,9 @@ def uc_open_with_cdp_mode(driver, url=None):
651
658
  cdp.get_window_rect = CDPM.get_window_rect
652
659
  cdp.get_window_size = CDPM.get_window_size
653
660
  cdp.nested_click = CDPM.nested_click
661
+ cdp.select_option_by_text = CDPM.select_option_by_text
654
662
  cdp.flash = CDPM.flash
663
+ cdp.highlight = CDPM.highlight
655
664
  cdp.focus = CDPM.focus
656
665
  cdp.highlight_overlay = CDPM.highlight_overlay
657
666
  cdp.get_window_position = CDPM.get_window_position
@@ -663,8 +672,11 @@ def uc_open_with_cdp_mode(driver, url=None):
663
672
  cdp.is_element_present = CDPM.is_element_present
664
673
  cdp.is_element_visible = CDPM.is_element_visible
665
674
  cdp.assert_element_present = CDPM.assert_element_present
675
+ cdp.assert_element_absent = CDPM.assert_element_absent
666
676
  cdp.assert_element = CDPM.assert_element
667
677
  cdp.assert_element_visible = CDPM.assert_element
678
+ cdp.assert_element_not_visible = CDPM.assert_element_not_visible
679
+ cdp.assert_title = CDPM.assert_title
668
680
  cdp.assert_text = CDPM.assert_text
669
681
  cdp.assert_exact_text = CDPM.assert_exact_text
670
682
  cdp.scroll_down = CDPM.scroll_down
@@ -680,6 +692,7 @@ def uc_open_with_cdp_mode(driver, url=None):
680
692
  core_items.tab = cdp.tab
681
693
  core_items.util = cdp.util
682
694
  cdp.core = core_items
695
+ cdp.loop = cdp.get_event_loop()
683
696
  driver.cdp = cdp
684
697
  driver._is_using_cdp = True
685
698
 
@@ -944,48 +957,46 @@ def uc_gui_click_x_y(driver, x, y, timeframe=0.25):
944
957
  connected = True
945
958
  width_ratio = 1.0
946
959
  if IS_WINDOWS:
947
- try:
948
- driver.window_handles
949
- except Exception:
950
- connected = False
960
+ connected = driver.is_connected()
951
961
  if (
952
962
  not connected
953
963
  and (
954
964
  not hasattr(sb_config, "_saved_width_ratio")
955
965
  or not sb_config._saved_width_ratio
956
966
  )
967
+ and not __is_cdp_swap_needed(driver)
957
968
  ):
958
969
  driver.reconnect(0.1)
959
- connected = True
960
- if IS_WINDOWS and connected:
970
+ if IS_WINDOWS and not __is_cdp_swap_needed(driver):
961
971
  window_rect = driver.get_window_rect()
962
972
  width = window_rect["width"]
963
973
  height = window_rect["height"]
964
974
  win_x = window_rect["x"]
965
975
  win_y = window_rect["y"]
966
- if (
967
- hasattr(sb_config, "_saved_width_ratio")
968
- and sb_config._saved_width_ratio
969
- ):
970
- width_ratio = sb_config._saved_width_ratio
971
- else:
972
- scr_width = pyautogui.size().width
973
- driver.maximize_window()
974
- win_width = driver.get_window_size()["width"]
975
- width_ratio = round(float(scr_width) / float(win_width), 2)
976
- width_ratio += 0.01
977
- if width_ratio < 0.45 or width_ratio > 2.55:
978
- width_ratio = 1.01
979
- sb_config._saved_width_ratio = width_ratio
976
+ scr_width = pyautogui.size().width
977
+ driver.maximize_window()
978
+ win_width = driver.get_window_size()["width"]
979
+ width_ratio = round(float(scr_width) / float(win_width), 2) + 0.01
980
+ if width_ratio < 0.45 or width_ratio > 2.55:
981
+ width_ratio = 1.01
982
+ sb_config._saved_width_ratio = width_ratio
980
983
  driver.minimize_window()
981
984
  driver.set_window_rect(win_x, win_y, width, height)
982
- elif (
983
- IS_WINDOWS
984
- and not connected
985
- and hasattr(sb_config, "_saved_width_ratio")
986
- and sb_config._saved_width_ratio
987
- ):
988
- width_ratio = sb_config._saved_width_ratio
985
+ elif IS_WINDOWS and __is_cdp_swap_needed(driver):
986
+ window_rect = driver.cdp.get_window_rect()
987
+ width = window_rect["width"]
988
+ height = window_rect["height"]
989
+ win_x = window_rect["x"]
990
+ win_y = window_rect["y"]
991
+ scr_width = pyautogui.size().width
992
+ driver.cdp.maximize()
993
+ win_width = driver.cdp.get_window_size()["width"]
994
+ width_ratio = round(float(scr_width) / float(win_width), 2) + 0.01
995
+ if width_ratio < 0.45 or width_ratio > 2.55:
996
+ width_ratio = 1.01
997
+ sb_config._saved_width_ratio = width_ratio
998
+ driver.cdp.minimize()
999
+ driver.cdp.set_window_rect(win_x, win_y, width, height)
989
1000
  if IS_WINDOWS:
990
1001
  x = x * width_ratio
991
1002
  y = y * width_ratio
@@ -1090,6 +1101,21 @@ def _uc_gui_click_captcha(
1090
1101
  sb_config._saved_width_ratio = width_ratio
1091
1102
  driver.minimize_window()
1092
1103
  driver.set_window_rect(win_x, win_y, width, height)
1104
+ elif IS_WINDOWS and __is_cdp_swap_needed(driver):
1105
+ window_rect = driver.cdp.get_window_rect()
1106
+ width = window_rect["width"]
1107
+ height = window_rect["height"]
1108
+ win_x = window_rect["x"]
1109
+ win_y = window_rect["y"]
1110
+ scr_width = pyautogui.size().width
1111
+ driver.cdp.maximize()
1112
+ win_width = driver.cdp.get_window_size()["width"]
1113
+ width_ratio = round(float(scr_width) / float(win_width), 2) + 0.01
1114
+ if width_ratio < 0.45 or width_ratio > 2.55:
1115
+ width_ratio = 1.01
1116
+ sb_config._saved_width_ratio = width_ratio
1117
+ driver.cdp.minimize()
1118
+ driver.cdp.set_window_rect(win_x, win_y, width, height)
1093
1119
  if ctype == "cf_t":
1094
1120
  if (
1095
1121
  driver.is_element_present(".cf-turnstile-wrapper iframe")
@@ -1201,10 +1227,10 @@ def _uc_gui_click_captcha(
1201
1227
  element = driver.wait_for_element_present(
1202
1228
  selector, timeout=2.5
1203
1229
  )
1204
- x = i_x + element.rect["x"] + int(element.rect["width"] / 2)
1205
- x += 1
1206
- y = i_y + element.rect["y"] + int(element.rect["height"] / 2)
1207
- y += 1
1230
+ x = i_x + element.rect["x"] + (element.rect["width"] / 2.0)
1231
+ x += 0.5
1232
+ y = i_y + element.rect["y"] + (element.rect["height"] / 2.0)
1233
+ y += 0.5
1208
1234
  else:
1209
1235
  x = (i_x + 34) * width_ratio
1210
1236
  y = (i_y + 34) * width_ratio
@@ -39,7 +39,9 @@ class CDPMethods():
39
39
  return element
40
40
  element.clear_input = lambda: self.__clear_input(element)
41
41
  element.click = lambda: self.__click(element)
42
- element.flash = lambda: self.__flash(element)
42
+ element.flash = lambda *args, **kwargs: self.__flash(
43
+ element, *args, **kwargs
44
+ )
43
45
  element.focus = lambda: self.__focus(element)
44
46
  element.highlight_overlay = lambda: self.__highlight_overlay(element)
45
47
  element.mouse_click = lambda: self.__mouse_click(element)
@@ -258,9 +260,11 @@ class CDPMethods():
258
260
  self.loop.run_until_complete(self.page.wait())
259
261
  return result
260
262
 
261
- def __flash(self, element):
263
+ def __flash(self, element, *args, **kwargs):
262
264
  return (
263
- self.loop.run_until_complete(element.flash_async())
265
+ self.loop.run_until_complete(
266
+ element.flash_async(*args, **kwargs)
267
+ )
264
268
  )
265
269
 
266
270
  def __focus(self, element):
@@ -292,11 +296,11 @@ class CDPMethods():
292
296
 
293
297
  def __query_selector(self, element, selector):
294
298
  selector = self.__convert_to_css_if_xpath(selector)
295
- element = self.loop.run_until_complete(
299
+ element2 = self.loop.run_until_complete(
296
300
  element.query_selector_async(selector)
297
301
  )
298
- element = self.__add_sync_methods(element)
299
- return element
302
+ element2 = self.__add_sync_methods(element2)
303
+ return element2
300
304
 
301
305
  def __query_selector_all(self, element, selector):
302
306
  selector = self.__convert_to_css_if_xpath(selector)
@@ -467,6 +471,19 @@ class CDPMethods():
467
471
  self.__slow_mode_pause_if_set()
468
472
  self.loop.run_until_complete(self.page.wait())
469
473
 
474
+ def click_visible_elements(self, selector):
475
+ elements = self.select_all(selector)
476
+ for element in elements:
477
+ try:
478
+ position = element.get_position()
479
+ if (position.width != 0 or position.height != 0):
480
+ element.click()
481
+ time.sleep(0.0375)
482
+ self.__slow_mode_pause_if_set()
483
+ self.loop.run_until_complete(self.page.wait())
484
+ except Exception:
485
+ pass
486
+
470
487
  def mouse_click(self, selector, timeout=settings.SMALL_TIMEOUT):
471
488
  """(Attempt simulating a mouse click)"""
472
489
  self.__slow_mode_pause_if_set()
@@ -491,9 +508,45 @@ class CDPMethods():
491
508
  element = self.find_element(parent_selector)
492
509
  return element.query_selector(selector)
493
510
 
494
- def flash(self, selector):
511
+ def select_option_by_text(self, dropdown_selector, option):
512
+ element = self.find_element(dropdown_selector)
513
+ options = element.query_selector_all("option")
514
+ for found_option in options:
515
+ if found_option.text.strip() == option.strip():
516
+ found_option.select_option()
517
+ return
518
+ raise Exception(
519
+ "Unable to find text option {%s} in dropdown {%s}!"
520
+ % (dropdown_selector, option)
521
+ )
522
+
523
+ def flash(
524
+ self,
525
+ selector, # The CSS Selector to flash
526
+ duration=1, # (seconds) flash duration
527
+ color="44CC88", # RGB hex flash color
528
+ pause=0, # (seconds) If 0, the next action starts during flash
529
+ ):
495
530
  """Paint a quickly-vanishing dot over an element."""
496
- self.find_element(selector).flash()
531
+ selector = self.__convert_to_css_if_xpath(selector)
532
+ element = self.find_element(selector)
533
+ element.flash(duration=duration, color=color)
534
+ if pause and isinstance(pause, (int, float)):
535
+ time.sleep(pause)
536
+
537
+ def highlight(self, selector):
538
+ """Highlight an element with multi-colors."""
539
+ selector = self.__convert_to_css_if_xpath(selector)
540
+ element = self.find_element(selector)
541
+ element = self.find_element(selector)
542
+ element.flash(0.46, "44CC88")
543
+ time.sleep(0.15)
544
+ element.flash(0.42, "8844CC")
545
+ time.sleep(0.15)
546
+ element.flash(0.38, "CC8844")
547
+ time.sleep(0.15)
548
+ element.flash(0.30, "44CC88")
549
+ time.sleep(0.30)
497
550
 
498
551
  def focus(self, selector):
499
552
  self.find_element(selector).focus()
@@ -526,8 +579,9 @@ class CDPMethods():
526
579
  self.find_element(selector).scroll_into_view()
527
580
 
528
581
  def send_keys(self, selector, text, timeout=settings.SMALL_TIMEOUT):
529
- element = self.select(selector)
530
582
  self.__slow_mode_pause_if_set()
583
+ element = self.select(selector, timeout=timeout)
584
+ self.__add_light_pause()
531
585
  if text.endswith("\n") or text.endswith("\r"):
532
586
  text = text[:-1] + "\r\n"
533
587
  element.send_keys(text)
@@ -536,8 +590,9 @@ class CDPMethods():
536
590
 
537
591
  def press_keys(self, selector, text, timeout=settings.SMALL_TIMEOUT):
538
592
  """Similar to send_keys(), but presses keys at human speed."""
539
- element = self.select(selector)
540
593
  self.__slow_mode_pause_if_set()
594
+ element = self.select(selector, timeout=timeout)
595
+ self.__add_light_pause()
541
596
  submit = False
542
597
  if text.endswith("\n") or text.endswith("\r"):
543
598
  submit = True
@@ -553,8 +608,9 @@ class CDPMethods():
553
608
 
554
609
  def type(self, selector, text, timeout=settings.SMALL_TIMEOUT):
555
610
  """Similar to send_keys(), but clears the text field first."""
556
- element = self.select(selector)
557
611
  self.__slow_mode_pause_if_set()
612
+ element = self.select(selector, timeout=timeout)
613
+ self.__add_light_pause()
558
614
  with suppress(Exception):
559
615
  element.clear_input()
560
616
  if text.endswith("\n") or text.endswith("\r"):
@@ -563,6 +619,42 @@ class CDPMethods():
563
619
  self.__slow_mode_pause_if_set()
564
620
  self.loop.run_until_complete(self.page.wait())
565
621
 
622
+ def set_value(self, selector, text, timeout=settings.SMALL_TIMEOUT):
623
+ """Similar to send_keys(), but clears the text field first."""
624
+ self.__slow_mode_pause_if_set()
625
+ selector = self.__convert_to_css_if_xpath(selector)
626
+ self.select(selector, timeout=timeout)
627
+ self.__add_light_pause()
628
+ press_enter = False
629
+ if text.endswith("\n"):
630
+ text = text[:-1]
631
+ press_enter = True
632
+ value = js_utils.escape_quotes_if_needed(re.escape(text))
633
+ css_selector = re.escape(selector)
634
+ css_selector = js_utils.escape_quotes_if_needed(css_selector)
635
+ set_value_script = (
636
+ """m_elm = document.querySelector('%s');"""
637
+ """m_elm.value = '%s';""" % (css_selector, value)
638
+ )
639
+ self.loop.run_until_complete(self.page.evaluate(set_value_script))
640
+ the_type = self.get_element_attribute(selector, "type")
641
+ if the_type == "range":
642
+ # Some input sliders need a mouse event to trigger listeners.
643
+ with suppress(Exception):
644
+ mouse_move_script = (
645
+ """m_elm = document.querySelector('%s');"""
646
+ """m_evt = new Event('mousemove');"""
647
+ """m_elm.dispatchEvent(m_evt);""" % css_selector
648
+ )
649
+ self.loop.run_until_complete(
650
+ self.page.evaluate(mouse_move_script)
651
+ )
652
+ elif press_enter:
653
+ self.__add_light_pause()
654
+ self.send_keys(selector, "\n")
655
+ self.__slow_mode_pause_if_set()
656
+ self.loop.run_until_complete(self.page.wait())
657
+
566
658
  def evaluate(self, expression):
567
659
  """Run a JavaScript expression and return the result."""
568
660
  return self.loop.run_until_complete(
@@ -576,21 +668,30 @@ class CDPMethods():
576
668
  )
577
669
 
578
670
  def maximize(self):
579
- return self.loop.run_until_complete(
580
- self.page.maximize()
581
- )
671
+ if self.get_window()[1].window_state.value == "maximized":
672
+ return
673
+ elif self.get_window()[1].window_state.value == "minimized":
674
+ self.loop.run_until_complete(self.page.maximize())
675
+ time.sleep(0.0375)
676
+ return self.loop.run_until_complete(self.page.maximize())
582
677
 
583
678
  def minimize(self):
584
- return self.loop.run_until_complete(
585
- self.page.minimize()
586
- )
679
+ if self.get_window()[1].window_state.value != "minimized":
680
+ return self.loop.run_until_complete(self.page.minimize())
587
681
 
588
682
  def medimize(self):
589
- return self.loop.run_until_complete(
590
- self.page.medimize()
591
- )
683
+ if self.get_window()[1].window_state.value == "minimized":
684
+ self.loop.run_until_complete(self.page.medimize())
685
+ time.sleep(0.0375)
686
+ return self.loop.run_until_complete(self.page.medimize())
592
687
 
593
688
  def set_window_rect(self, x, y, width, height):
689
+ if self.get_window()[1].window_state.value == "minimized":
690
+ self.loop.run_until_complete(
691
+ self.page.set_window_size(
692
+ left=x, top=y, width=width, height=height)
693
+ )
694
+ time.sleep(0.0375)
594
695
  return self.loop.run_until_complete(
595
696
  self.page.set_window_size(
596
697
  left=x, top=y, width=width, height=height)
@@ -602,6 +703,7 @@ class CDPMethods():
602
703
  width = settings.CHROME_START_WIDTH
603
704
  height = settings.CHROME_START_HEIGHT
604
705
  self.set_window_rect(x, y, width, height)
706
+ self.__add_light_pause()
605
707
 
606
708
  def get_window(self):
607
709
  return self.loop.run_until_complete(
@@ -785,7 +887,7 @@ class CDPMethods():
785
887
  e_height = element_rect["height"]
786
888
  e_x = element_rect["x"]
787
889
  e_y = element_rect["y"]
788
- return ((e_x + e_width / 2), (e_y + e_height / 2))
890
+ return ((e_x + e_width / 2.0) + 0.5, (e_y + e_height / 2.0) + 0.5)
789
891
 
790
892
  def get_document(self):
791
893
  return self.loop.run_until_complete(
@@ -798,6 +900,7 @@ class CDPMethods():
798
900
  )
799
901
 
800
902
  def get_element_attributes(self, selector):
903
+ selector = self.__convert_to_css_if_xpath(selector)
801
904
  return self.loop.run_until_complete(
802
905
  self.page.js_dumps(
803
906
  """document.querySelector('%s')"""
@@ -1013,6 +1116,156 @@ class CDPMethods():
1013
1116
  pyautogui.click(x=x, y=y)
1014
1117
 
1015
1118
  def gui_click_x_y(self, x, y, timeframe=0.25):
1119
+ gui_lock = fasteners.InterProcessLock(
1120
+ constants.MultiBrowser.PYAUTOGUILOCK
1121
+ )
1122
+ with gui_lock: # Prevent issues with multiple processes
1123
+ self.__install_pyautogui_if_missing()
1124
+ import pyautogui
1125
+ pyautogui = self.__get_configured_pyautogui(pyautogui)
1126
+ width_ratio = 1.0
1127
+ if shared_utils.is_windows():
1128
+ window_rect = self.get_window_rect()
1129
+ width = window_rect["width"]
1130
+ height = window_rect["height"]
1131
+ win_x = window_rect["x"]
1132
+ win_y = window_rect["y"]
1133
+ scr_width = pyautogui.size().width
1134
+ self.maximize()
1135
+ self.__add_light_pause()
1136
+ win_width = self.get_window_size()["width"]
1137
+ width_ratio = round(float(scr_width) / float(win_width), 2)
1138
+ width_ratio += 0.01
1139
+ if width_ratio < 0.45 or width_ratio > 2.55:
1140
+ width_ratio = 1.01
1141
+ sb_config._saved_width_ratio = width_ratio
1142
+ self.minimize()
1143
+ self.__add_light_pause()
1144
+ self.set_window_rect(win_x, win_y, width, height)
1145
+ self.__add_light_pause()
1146
+ x = x * width_ratio
1147
+ y = y * width_ratio
1148
+ self.bring_active_window_to_front()
1149
+ self.__gui_click_x_y(x, y, timeframe=timeframe, uc_lock=False)
1150
+
1151
+ def gui_click_element(self, selector, timeframe=0.25):
1152
+ self.__slow_mode_pause_if_set()
1153
+ x, y = self.get_gui_element_center(selector)
1154
+ self.__add_light_pause()
1155
+ self.gui_click_x_y(x, y, timeframe=timeframe)
1156
+ self.__slow_mode_pause_if_set()
1157
+ self.loop.run_until_complete(self.page.wait())
1158
+
1159
+ def __gui_drag_drop(self, x1, y1, x2, y2, timeframe=0.25, uc_lock=False):
1160
+ self.__install_pyautogui_if_missing()
1161
+ import pyautogui
1162
+ pyautogui = self.__get_configured_pyautogui(pyautogui)
1163
+ screen_width, screen_height = pyautogui.size()
1164
+ if x1 < 0 or y1 < 0 or x1 > screen_width or y1 > screen_height:
1165
+ raise Exception(
1166
+ "PyAutoGUI cannot drag-drop from point (%s, %s)"
1167
+ " outside screen. (Width: %s, Height: %s)"
1168
+ % (x1, y1, screen_width, screen_height)
1169
+ )
1170
+ if x2 < 0 or y2 < 0 or x2 > screen_width or y2 > screen_height:
1171
+ raise Exception(
1172
+ "PyAutoGUI cannot drag-drop to point (%s, %s)"
1173
+ " outside screen. (Width: %s, Height: %s)"
1174
+ % (x2, y2, screen_width, screen_height)
1175
+ )
1176
+ if uc_lock:
1177
+ gui_lock = fasteners.InterProcessLock(
1178
+ constants.MultiBrowser.PYAUTOGUILOCK
1179
+ )
1180
+ with gui_lock: # Prevent issues with multiple processes
1181
+ pyautogui.moveTo(x1, y1, 0.25, pyautogui.easeOutQuad)
1182
+ self.__add_light_pause()
1183
+ if "--debug" in sys.argv:
1184
+ print(" <DEBUG> pyautogui.moveTo(%s, %s)" % (x1, y1))
1185
+ pyautogui.dragTo(x2, y2, button="left", duration=timeframe)
1186
+ else:
1187
+ # Called from a method where the gui_lock is already active
1188
+ pyautogui.moveTo(x1, y1, 0.25, pyautogui.easeOutQuad)
1189
+ self.__add_light_pause()
1190
+ if "--debug" in sys.argv:
1191
+ print(" <DEBUG> pyautogui.dragTo(%s, %s)" % (x2, y2))
1192
+ pyautogui.dragTo(x2, y2, button="left", duration=timeframe)
1193
+
1194
+ def gui_drag_drop_points(self, x1, y1, x2, y2, timeframe=0.35):
1195
+ gui_lock = fasteners.InterProcessLock(
1196
+ constants.MultiBrowser.PYAUTOGUILOCK
1197
+ )
1198
+ with gui_lock: # Prevent issues with multiple processes
1199
+ self.__install_pyautogui_if_missing()
1200
+ import pyautogui
1201
+ pyautogui = self.__get_configured_pyautogui(pyautogui)
1202
+ width_ratio = 1.0
1203
+ if shared_utils.is_windows():
1204
+ window_rect = self.get_window_rect()
1205
+ width = window_rect["width"]
1206
+ height = window_rect["height"]
1207
+ win_x = window_rect["x"]
1208
+ win_y = window_rect["y"]
1209
+ scr_width = pyautogui.size().width
1210
+ self.maximize()
1211
+ self.__add_light_pause()
1212
+ win_width = self.get_window_size()["width"]
1213
+ width_ratio = round(float(scr_width) / float(win_width), 2)
1214
+ width_ratio += 0.01
1215
+ if width_ratio < 0.45 or width_ratio > 2.55:
1216
+ width_ratio = 1.01
1217
+ sb_config._saved_width_ratio = width_ratio
1218
+ self.minimize()
1219
+ self.__add_light_pause()
1220
+ self.set_window_rect(win_x, win_y, width, height)
1221
+ self.__add_light_pause()
1222
+ x1 = x1 * width_ratio
1223
+ y1 = y1 * width_ratio
1224
+ x2 = x2 * width_ratio
1225
+ y2 = y2 * width_ratio
1226
+ self.bring_active_window_to_front()
1227
+ self.__gui_drag_drop(
1228
+ x1, y1, x2, y2, timeframe=timeframe, uc_lock=False
1229
+ )
1230
+ self.__slow_mode_pause_if_set()
1231
+ self.loop.run_until_complete(self.page.wait())
1232
+
1233
+ def gui_drag_and_drop(self, drag_selector, drop_selector, timeframe=0.35):
1234
+ self.__slow_mode_pause_if_set()
1235
+ x1, y1 = self.get_gui_element_center(drag_selector)
1236
+ self.__add_light_pause()
1237
+ x2, y2 = self.get_gui_element_center(drop_selector)
1238
+ self.__add_light_pause()
1239
+ self.gui_drag_drop_points(x1, y1, x2, y2, timeframe=timeframe)
1240
+
1241
+ def __gui_hover_x_y(self, x, y, timeframe=0.25, uc_lock=False):
1242
+ self.__install_pyautogui_if_missing()
1243
+ import pyautogui
1244
+ pyautogui = self.__get_configured_pyautogui(pyautogui)
1245
+ screen_width, screen_height = pyautogui.size()
1246
+ if x < 0 or y < 0 or x > screen_width or y > screen_height:
1247
+ raise Exception(
1248
+ "PyAutoGUI cannot hover on point (%s, %s)"
1249
+ " outside screen. (Width: %s, Height: %s)"
1250
+ % (x, y, screen_width, screen_height)
1251
+ )
1252
+ if uc_lock:
1253
+ gui_lock = fasteners.InterProcessLock(
1254
+ constants.MultiBrowser.PYAUTOGUILOCK
1255
+ )
1256
+ with gui_lock: # Prevent issues with multiple processes
1257
+ pyautogui.moveTo(x, y, timeframe, pyautogui.easeOutQuad)
1258
+ time.sleep(0.056)
1259
+ if "--debug" in sys.argv:
1260
+ print(" <DEBUG> pyautogui.moveTo(%s, %s)" % (x, y))
1261
+ else:
1262
+ # Called from a method where the gui_lock is already active
1263
+ pyautogui.moveTo(x, y, timeframe, pyautogui.easeOutQuad)
1264
+ time.sleep(0.056)
1265
+ if "--debug" in sys.argv:
1266
+ print(" <DEBUG> pyautogui.moveTo(%s, %s)" % (x, y))
1267
+
1268
+ def gui_hover_x_y(self, x, y, timeframe=0.25):
1016
1269
  gui_lock = fasteners.InterProcessLock(
1017
1270
  constants.MultiBrowser.PYAUTOGUILOCK
1018
1271
  )
@@ -1041,6 +1294,7 @@ class CDPMethods():
1041
1294
  else:
1042
1295
  scr_width = pyautogui.size().width
1043
1296
  self.maximize()
1297
+ self.__add_light_pause()
1044
1298
  win_width = self.get_window_size()["width"]
1045
1299
  width_ratio = round(float(scr_width) / float(win_width), 2)
1046
1300
  width_ratio += 0.01
@@ -1048,6 +1302,7 @@ class CDPMethods():
1048
1302
  width_ratio = 1.01
1049
1303
  sb_config._saved_width_ratio = width_ratio
1050
1304
  self.set_window_rect(win_x, win_y, width, height)
1305
+ self.__add_light_pause()
1051
1306
  self.bring_active_window_to_front()
1052
1307
  elif (
1053
1308
  shared_utils.is_windows()
@@ -1059,19 +1314,29 @@ class CDPMethods():
1059
1314
  if shared_utils.is_windows():
1060
1315
  x = x * width_ratio
1061
1316
  y = y * width_ratio
1062
- self.__gui_click_x_y(x, y, timeframe=timeframe, uc_lock=False)
1317
+ self.__gui_hover_x_y(x, y, timeframe=timeframe, uc_lock=False)
1063
1318
  return
1064
1319
  self.bring_active_window_to_front()
1065
- self.__gui_click_x_y(x, y, timeframe=timeframe, uc_lock=False)
1320
+ self.__gui_hover_x_y(x, y, timeframe=timeframe, uc_lock=False)
1066
1321
 
1067
- def gui_click_element(self, selector, timeframe=0.25):
1322
+ def gui_hover_element(self, selector, timeframe=0.25):
1068
1323
  self.__slow_mode_pause_if_set()
1069
1324
  x, y = self.get_gui_element_center(selector)
1070
1325
  self.__add_light_pause()
1071
- self.gui_click_x_y(x, y, timeframe=timeframe)
1326
+ self.__gui_hover_x_y(x, y, timeframe=timeframe)
1072
1327
  self.__slow_mode_pause_if_set()
1073
1328
  self.loop.run_until_complete(self.page.wait())
1074
1329
 
1330
+ def gui_hover_and_click(self, hover_selector, click_selector):
1331
+ gui_lock = fasteners.InterProcessLock(
1332
+ constants.MultiBrowser.PYAUTOGUILOCK
1333
+ )
1334
+ with gui_lock:
1335
+ self.gui_hover_element(hover_selector)
1336
+ time.sleep(0.15)
1337
+ self.gui_hover_element(click_selector)
1338
+ self.click(click_selector)
1339
+
1075
1340
  def internalize_links(self):
1076
1341
  """All `target="_blank"` links become `target="_self"`.
1077
1342
  This prevents those links from opening in a new tab."""
@@ -1079,24 +1344,30 @@ class CDPMethods():
1079
1344
 
1080
1345
  def is_checked(self, selector):
1081
1346
  """Return True if checkbox (or radio button) is checked."""
1347
+ selector = self.__convert_to_css_if_xpath(selector)
1082
1348
  self.find_element(selector, timeout=settings.SMALL_TIMEOUT)
1083
1349
  return self.get_element_attribute(selector, "checked")
1084
1350
 
1085
1351
  def is_selected(self, selector):
1352
+ selector = self.__convert_to_css_if_xpath(selector)
1086
1353
  return self.is_checked(selector)
1087
1354
 
1088
1355
  def check_if_unchecked(self, selector):
1356
+ selector = self.__convert_to_css_if_xpath(selector)
1089
1357
  if not self.is_checked(selector):
1090
1358
  self.click(selector)
1091
1359
 
1092
1360
  def select_if_unselected(self, selector):
1361
+ selector = self.__convert_to_css_if_xpath(selector)
1093
1362
  self.check_if_unchecked(selector)
1094
1363
 
1095
1364
  def uncheck_if_checked(self, selector):
1365
+ selector = self.__convert_to_css_if_xpath(selector)
1096
1366
  if self.is_checked(selector):
1097
1367
  self.click(selector)
1098
1368
 
1099
1369
  def unselect_if_selected(self, selector):
1370
+ selector = self.__convert_to_css_if_xpath(selector)
1100
1371
  self.uncheck_if_checked(selector)
1101
1372
 
1102
1373
  def is_element_present(self, selector):
@@ -1105,32 +1376,22 @@ class CDPMethods():
1105
1376
  return True
1106
1377
  except Exception:
1107
1378
  return False
1108
- selector = self.__convert_to_css_if_xpath(selector)
1109
- element = self.loop.run_until_complete(
1110
- self.page.js_dumps(
1111
- """document.querySelector('%s')"""
1112
- % js_utils.escape_quotes_if_needed(re.escape(selector))
1113
- )
1114
- )
1115
- return element is not None
1116
1379
 
1117
1380
  def is_element_visible(self, selector):
1118
1381
  selector = self.__convert_to_css_if_xpath(selector)
1119
1382
  element = None
1120
1383
  if ":contains(" not in selector:
1121
1384
  try:
1122
- element = self.loop.run_until_complete(
1123
- self.page.js_dumps(
1124
- """window.getComputedStyle(document.querySelector"""
1125
- """('%s'))"""
1126
- % js_utils.escape_quotes_if_needed(re.escape(selector))
1127
- )
1128
- )
1385
+ element = self.select(selector, timeout=0.01)
1129
1386
  except Exception:
1130
1387
  return False
1131
1388
  if not element:
1132
1389
  return False
1133
- return element.get("display") != "none"
1390
+ try:
1391
+ position = element.get_position()
1392
+ return (position.width != 0 or position.height != 0)
1393
+ except Exception:
1394
+ return False
1134
1395
  else:
1135
1396
  with suppress(Exception):
1136
1397
  tag_name = selector.split(":contains(")[0].split(" ")[-1]
@@ -1160,9 +1421,66 @@ class CDPMethods():
1160
1421
  raise Exception("Element {%s} not found!" % selector)
1161
1422
  return True
1162
1423
 
1424
+ def assert_element_absent(self, selector, timeout=settings.SMALL_TIMEOUT):
1425
+ start_ms = time.time() * 1000.0
1426
+ stop_ms = start_ms + (timeout * 1000.0)
1427
+ for i in range(int(timeout * 10)):
1428
+ if not self.is_element_present(selector):
1429
+ return True
1430
+ now_ms = time.time() * 1000.0
1431
+ if now_ms >= stop_ms:
1432
+ break
1433
+ time.sleep(0.1)
1434
+ plural = "s"
1435
+ if timeout == 1:
1436
+ plural = ""
1437
+ raise Exception(
1438
+ "Element {%s} was still present after %s second%s!"
1439
+ % (selector, timeout, plural)
1440
+ )
1441
+
1442
+ def assert_element_not_visible(
1443
+ self, selector, timeout=settings.SMALL_TIMEOUT
1444
+ ):
1445
+ start_ms = time.time() * 1000.0
1446
+ stop_ms = start_ms + (timeout * 1000.0)
1447
+ for i in range(int(timeout * 10)):
1448
+ if not self.is_element_present(selector):
1449
+ return True
1450
+ elif not self.is_element_visible(selector):
1451
+ return True
1452
+ now_ms = time.time() * 1000.0
1453
+ if now_ms >= stop_ms:
1454
+ break
1455
+ time.sleep(0.1)
1456
+ plural = "s"
1457
+ if timeout == 1:
1458
+ plural = ""
1459
+ raise Exception(
1460
+ "Element {%s} was still visible after %s second%s!"
1461
+ % (selector, timeout, plural)
1462
+ )
1463
+
1464
+ def assert_title(self, title):
1465
+ expected = title.strip()
1466
+ actual = self.get_title().strip()
1467
+ error = (
1468
+ "Expected page title [%s] does not match the actual title [%s]!"
1469
+ )
1470
+ try:
1471
+ if expected != actual:
1472
+ raise Exception(error % (expected, actual))
1473
+ except Exception:
1474
+ time.sleep(2)
1475
+ expected = title.strip()
1476
+ actual = self.get_title().strip()
1477
+ if expected != actual:
1478
+ raise Exception(error % (expected, actual))
1479
+
1163
1480
  def assert_text(
1164
1481
  self, text, selector="html", timeout=settings.SMALL_TIMEOUT
1165
1482
  ):
1483
+ text = text.strip()
1166
1484
  element = None
1167
1485
  try:
1168
1486
  element = self.select(selector, timeout=timeout)
@@ -1180,6 +1498,7 @@ class CDPMethods():
1180
1498
  def assert_exact_text(
1181
1499
  self, text, selector="html", timeout=settings.SMALL_TIMEOUT
1182
1500
  ):
1501
+ text = text.strip()
1183
1502
  element = None
1184
1503
  try:
1185
1504
  element = self.select(selector, timeout=timeout)
@@ -198,6 +198,11 @@ class DriverMethods():
198
198
  In CDP Mode, the CDP-Driver controls the web browser.
199
199
  The CDP-Driver can be connected while WebDriver isn't.
200
200
  """
201
+ if shared_utils.is_windows():
202
+ return (
203
+ not hasattr(self.driver, "_is_connected")
204
+ or self.driver._is_connected
205
+ )
201
206
  try:
202
207
  self.driver.window_handles
203
208
  return True
@@ -238,6 +243,14 @@ class DriverMethods():
238
243
  return js_utils.get_user_agent(self.driver, *args, **kwargs)
239
244
 
240
245
  def highlight(self, *args, **kwargs):
246
+ if self.__is_cdp_swap_needed():
247
+ selector = None
248
+ if "selector" in kwargs:
249
+ selector = kwargs["selector"]
250
+ else:
251
+ selector = args[0]
252
+ self.driver.cdp.highlight(selector)
253
+ return
241
254
  if "scroll" in kwargs:
242
255
  kwargs.pop("scroll")
243
256
  w_args = kwargs.copy()
@@ -1592,6 +1592,9 @@ class BaseCase(unittest.TestCase):
1592
1592
  def click_link_text(self, link_text, timeout=None):
1593
1593
  """This method clicks link text on a page."""
1594
1594
  self.__check_scope()
1595
+ if self.__is_cdp_swap_needed():
1596
+ self.cdp.find_element(link_text).click()
1597
+ return
1595
1598
  self.__skip_if_esc()
1596
1599
  if not timeout:
1597
1600
  timeout = settings.SMALL_TIMEOUT
@@ -2197,6 +2200,9 @@ class BaseCase(unittest.TestCase):
2197
2200
  if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
2198
2201
  timeout = self.__get_new_timeout(timeout)
2199
2202
  selector, by = self.__recalculate_selector(selector, by)
2203
+ if self.__is_cdp_swap_needed():
2204
+ self.cdp.click_visible_elements(selector)
2205
+ return
2200
2206
  self.wait_for_ready_state_complete()
2201
2207
  if self.__needs_minimum_wait():
2202
2208
  time.sleep(0.12)
@@ -2637,6 +2643,9 @@ class BaseCase(unittest.TestCase):
2637
2643
  original_selector = selector
2638
2644
  original_by = by
2639
2645
  selector, by = self.__recalculate_selector(selector, by)
2646
+ if self.__is_cdp_swap_needed():
2647
+ self.cdp.gui_hover_element(selector)
2648
+ return
2640
2649
  self.wait_for_element_visible(
2641
2650
  original_selector, by=original_by, timeout=timeout
2642
2651
  )
@@ -2679,6 +2688,9 @@ class BaseCase(unittest.TestCase):
2679
2688
  click_selector, click_by = self.__recalculate_selector(
2680
2689
  click_selector, click_by
2681
2690
  )
2691
+ if self.__is_cdp_swap_needed():
2692
+ self.cdp.gui_hover_and_click(hover_selector, click_selector)
2693
+ return
2682
2694
  dropdown_element = self.wait_for_element_visible(
2683
2695
  original_selector, by=original_by, timeout=timeout
2684
2696
  )
@@ -3105,6 +3117,9 @@ class BaseCase(unittest.TestCase):
3105
3117
  timeout = settings.SMALL_TIMEOUT
3106
3118
  if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
3107
3119
  timeout = self.__get_new_timeout(timeout)
3120
+ if self.__is_cdp_swap_needed():
3121
+ self.cdp.select_option_by_text(dropdown_selector, option)
3122
+ return
3108
3123
  self.__select_option(
3109
3124
  dropdown_selector,
3110
3125
  option,
@@ -3419,8 +3434,8 @@ class BaseCase(unittest.TestCase):
3419
3434
  if self.__is_cdp_swap_needed():
3420
3435
  return self.cdp.get_gui_element_center(selector)
3421
3436
  element_rect = self.get_gui_element_rect(selector, by=by)
3422
- x = int(element_rect["x"]) + int(element_rect["width"] / 2) + 1
3423
- y = int(element_rect["y"]) + int(element_rect["height"] / 2) + 1
3437
+ x = element_rect["x"] + (element_rect["width"] / 2.0) + 0.5
3438
+ y = element_rect["y"] + (element_rect["height"] / 2.0) + 0.5
3424
3439
  return (x, y)
3425
3440
 
3426
3441
  def get_window_rect(self):
@@ -5959,6 +5974,9 @@ class BaseCase(unittest.TestCase):
5959
5974
  scroll - the option to scroll to the element first (Default: True)
5960
5975
  timeout - the time to wait for the element to appear """
5961
5976
  self.__check_scope()
5977
+ if self.__is_cdp_swap_needed():
5978
+ self.cdp.highlight(selector)
5979
+ return
5962
5980
  self._check_browser()
5963
5981
  self.__skip_if_esc()
5964
5982
  if isinstance(selector, WebElement):
@@ -7676,6 +7694,9 @@ class BaseCase(unittest.TestCase):
7676
7694
  but then the title switches over to the actual page title.
7677
7695
  In Recorder Mode, this assertion is skipped because the Recorder
7678
7696
  changes the page title to the selector of the hovered element."""
7697
+ if self.__is_cdp_swap_needed():
7698
+ self.cdp.assert_title(title)
7699
+ return
7679
7700
  self.wait_for_ready_state_complete()
7680
7701
  expected = title.strip()
7681
7702
  actual = self.get_page_title().strip()
@@ -8166,7 +8187,7 @@ class BaseCase(unittest.TestCase):
8166
8187
  timeout = self.__get_new_timeout(timeout)
8167
8188
  selector, by = self.__recalculate_selector(selector, by, xp_ok=False)
8168
8189
  if self.__is_cdp_swap_needed():
8169
- self.cdp.type(selector, text)
8190
+ self.cdp.set_value(selector, text)
8170
8191
  return
8171
8192
  self.wait_for_ready_state_complete()
8172
8193
  self.wait_for_element_present(selector, by=by, timeout=timeout)
@@ -8932,6 +8953,9 @@ class BaseCase(unittest.TestCase):
8932
8953
  timeout = self.__get_new_timeout(timeout)
8933
8954
  original_selector = selector
8934
8955
  selector, by = self.__recalculate_selector(selector, by)
8956
+ if self.__is_cdp_swap_needed():
8957
+ self.cdp.assert_element_absent(selector)
8958
+ return True
8935
8959
  return page_actions.wait_for_element_absent(
8936
8960
  self.driver,
8937
8961
  selector,
@@ -9966,6 +9990,9 @@ class BaseCase(unittest.TestCase):
9966
9990
  timeout = settings.SMALL_TIMEOUT
9967
9991
  if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
9968
9992
  timeout = self.__get_new_timeout(timeout)
9993
+ if self.__is_cdp_swap_needed():
9994
+ self.cdp.find_element(link_text)
9995
+ return
9969
9996
  self.wait_for_link_text_visible(link_text, timeout=timeout)
9970
9997
  if self.demo_mode:
9971
9998
  a_t = "ASSERT LINK TEXT"
@@ -10065,6 +10092,9 @@ class BaseCase(unittest.TestCase):
10065
10092
  timeout = settings.SMALL_TIMEOUT
10066
10093
  if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
10067
10094
  timeout = self.__get_new_timeout(timeout)
10095
+ if self.__is_cdp_swap_needed():
10096
+ self.cdp.assert_element_absent(selector)
10097
+ return True
10068
10098
  self.wait_for_element_absent(selector, by=by, timeout=timeout)
10069
10099
  return True
10070
10100
 
@@ -10083,6 +10113,9 @@ class BaseCase(unittest.TestCase):
10083
10113
  timeout = self.__get_new_timeout(timeout)
10084
10114
  original_selector = selector
10085
10115
  selector, by = self.__recalculate_selector(selector, by)
10116
+ if self.__is_cdp_swap_needed():
10117
+ self.cdp.assert_element_not_visible(selector)
10118
+ return True
10086
10119
  return page_actions.wait_for_element_not_visible(
10087
10120
  self.driver,
10088
10121
  selector,
@@ -93,9 +93,9 @@ def is_cdp_swap_needed(driver):
93
93
  For other webdriver methods, SeleniumBase will reconnect first.
94
94
  """
95
95
  return (
96
- driver.is_cdp_mode_active()
97
- # and hasattr(driver, "_is_connected")
98
- # and not driver._is_connected
96
+ hasattr(driver, "is_cdp_mode_active")
97
+ and driver.is_cdp_mode_active()
98
+ and hasattr(driver, "is_connected")
99
99
  and not driver.is_connected()
100
100
  )
101
101
 
@@ -5,6 +5,7 @@ import logging
5
5
  import pathlib
6
6
  import secrets
7
7
  import typing
8
+ from contextlib import suppress
8
9
  from . import cdp_util as util
9
10
  from ._contradict import ContraDict
10
11
  from .config import PathLike
@@ -768,6 +769,11 @@ class Element:
768
769
  Gets the text contents of this element and child nodes, concatenated.
769
770
  Note: This includes text in the form of script content, (text nodes).
770
771
  """
772
+ with suppress(Exception):
773
+ if self.node.node_name.lower() in ["input", "textarea"]:
774
+ input_node = self.node.shadow_roots[0].children[0].children[0]
775
+ if input_node:
776
+ return input_node.node_value
771
777
  text_nodes = util.filter_recurse_all(
772
778
  self.node, lambda n: n.node_type == 3
773
779
  )
@@ -776,6 +782,11 @@ class Element:
776
782
  @property
777
783
  def text_all(self):
778
784
  """Same as text(). Kept for backwards compatibility."""
785
+ with suppress(Exception):
786
+ if self.node.node_name.lower() in ["input", "textarea"]:
787
+ input_node = self.node.shadow_roots[0].children[0].children[0]
788
+ if input_node:
789
+ return input_node.node_value
779
790
  text_nodes = util.filter_recurse_all(
780
791
  self.node, lambda n: n.node_type == 3
781
792
  )
@@ -868,7 +879,11 @@ class Element:
868
879
  path.write_bytes(data_bytes)
869
880
  return str(path)
870
881
 
871
- async def flash_async(self, duration: typing.Union[float, int] = 0.5):
882
+ async def flash_async(
883
+ self,
884
+ duration: typing.Union[float, int] = 0.5,
885
+ color: typing.Optional[str] = "EE4488",
886
+ ):
872
887
  """
873
888
  Displays for a short time a red dot on the element.
874
889
  (Only if the element itself is visible)
@@ -892,11 +907,12 @@ class Element:
892
907
  style = (
893
908
  "position:absolute;z-index:99999999;padding:0;margin:0;"
894
909
  "left:{:.1f}px; top: {:.1f}px; opacity:0.7;"
895
- "width:8px;height:8px;border-radius:50%;background:#EE4488;"
910
+ "width:8px;height:8px;border-radius:50%;background:#{};"
896
911
  "animation:show-pointer-ani {:.2f}s ease 1;"
897
912
  ).format(
898
913
  pos.center[0] - 4, # -4 to account for drawn circle itself (w,h)
899
914
  pos.center[1] - 4,
915
+ color,
900
916
  duration,
901
917
  )
902
918
  script = (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: seleniumbase
3
- Version: 4.32.9
3
+ Version: 4.32.10a1
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
@@ -67,7 +67,7 @@ Requires-Dist: certifi>=2024.8.30
67
67
  Requires-Dist: exceptiongroup>=1.2.2
68
68
  Requires-Dist: filelock>=3.16.1
69
69
  Requires-Dist: fasteners>=0.19
70
- Requires-Dist: mycdp>=1.0.1
70
+ Requires-Dist: mycdp>=1.1.0
71
71
  Requires-Dist: pynose>=1.5.3
72
72
  Requires-Dist: platformdirs>=4.3.6
73
73
  Requires-Dist: typing-extensions>=4.12.2
@@ -117,9 +117,9 @@ Requires-Dist: pyreadline3>=3.5.3; platform_system == "Windows"
117
117
  Requires-Dist: setuptools~=70.2; python_version < "3.10"
118
118
  Requires-Dist: urllib3<2,>=1.26.20; python_version < "3.10"
119
119
  Requires-Dist: websockets~=13.1; python_version < "3.9"
120
- Requires-Dist: setuptools>=73.0.1; python_version >= "3.10"
120
+ Requires-Dist: setuptools>=75.5.0; python_version >= "3.10"
121
121
  Requires-Dist: urllib3<2.3.0,>=1.26.20; python_version >= "3.10"
122
- Requires-Dist: websockets>=14.0; python_version >= "3.9"
122
+ Requires-Dist: websockets>=14.1; python_version >= "3.9"
123
123
  Provides-Extra: allure
124
124
  Requires-Dist: allure-pytest>=2.13.5; extra == "allure"
125
125
  Requires-Dist: allure-python-commons>=2.13.5; extra == "allure"
@@ -3,7 +3,7 @@ sbase/__main__.py,sha256=G0bVB1-DM4PGwQ1KyOupaWCs4ePbChZNNWuX2htim5U,647
3
3
  sbase/steps.py,sha256=bKT_u5bJkKzYWEuAXi9NVVRYYxQRCM1_YJUrNFFRVPY,42865
4
4
  seleniumbase/__init__.py,sha256=OtJh8nGKL4xtZpw8KPqmn7Q6R-86t4cWUDyVF5MbMTo,2398
5
5
  seleniumbase/__main__.py,sha256=dn1p6dgCchmcH1zzTzzQvFwwdQQqnTGH6ULV9m4hv24,654
6
- seleniumbase/__version__.py,sha256=am_TdSeFJWZgGKFn3vmM8ge4vQM8qlkXsvTrl75KN2M,46
6
+ seleniumbase/__version__.py,sha256=mB07opo9QE8Mwmi2PHdixrHjmflPaAc2Gc-yYAxT6ps,49
7
7
  seleniumbase/behave/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  seleniumbase/behave/behave_helper.py,sha256=elkl8P9eLulRAioLstE9baYNM9N_PHBmAOcajX-pH_Y,24198
9
9
  seleniumbase/behave/behave_sb.py,sha256=-hza7Nx2U41mSObYiPMi48v3JlPh3sJO3yzP0kqZ1Gk,59174
@@ -36,7 +36,7 @@ seleniumbase/console_scripts/sb_print.py,sha256=tNy-bMDgwHJO3bZxMpmo9weSE8uhbH0C
36
36
  seleniumbase/console_scripts/sb_recorder.py,sha256=1oAA4wFzVboNhIFDwJLD3jgy9RuoavywKQG7R67bNZE,10908
37
37
  seleniumbase/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
38
  seleniumbase/core/application_manager.py,sha256=e_0sjtI8cjY5BNyZj1QBR0j6_oCScxGmSXYEpcYwuZE,576
39
- seleniumbase/core/browser_launcher.py,sha256=HG8_3PsRDx1acbA0ZW9DO_cYjkPy3OfDOvHaZnFUwJM,217440
39
+ seleniumbase/core/browser_launcher.py,sha256=WjW--f7w0hUc8Y86tsUen4s2-bh8aXlhd3ad2G2Ws1Q,219040
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,8 +50,8 @@ seleniumbase/core/proxy_helper.py,sha256=cXhu8ErK9Vjdm82RMaQj7hEq_yUWizSp6LyiD50
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=4dp20r_KSK8n8nhqzqPMTk48nXt16wzGKSW2v63j_p0,45560
54
- seleniumbase/core/sb_driver.py,sha256=-k4vHwMnuiBIkdVInTtJA-IDLrgQfyMhNxSHMIsjepw,11623
53
+ seleniumbase/core/sb_cdp.py,sha256=IwK8KeDdO1vCwzqocbok7hWDFY6qOf-aB_tL_WMVMSE,59423
54
+ seleniumbase/core/sb_driver.py,sha256=Yd9BpjnOUuZqYRGmsERVKc1W-e8qwTt7SAytLatkXPA,12070
55
55
  seleniumbase/core/session_helper.py,sha256=s9zD3PVZEWVzG2h81cCUskbNWLfdjC_LwwQjKptHCak,558
56
56
  seleniumbase/core/settings_parser.py,sha256=KokVXpCiGZhJ-D4Bo-hizPz5r-iefzWoiTANu9zNaq4,7504
57
57
  seleniumbase/core/style_sheet.py,sha256=tPpJ1xl6Kuw425Z-3Y0OgVRLGXk_ciBDREZjXk_NuPE,11395
@@ -65,14 +65,14 @@ seleniumbase/extensions/disable_csp.zip,sha256=YMifIIgEBiLrEFrS1sfW4Exh4br1V4oK1
65
65
  seleniumbase/extensions/recorder.zip,sha256=OOyzF-Ize2cSRu1CqhzSAq5vusI9hqLLd2OIApUHesI,11918
66
66
  seleniumbase/extensions/sbase_ext.zip,sha256=3s1N8zrVaMz8RQEOIoBzC3KDjtmHwVZRvVsX25Odr_s,8175
67
67
  seleniumbase/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
- seleniumbase/fixtures/base_case.py,sha256=DfOl1L5VCOaKduVqvnkBeUc4qHs3n6SEdl65CLXaEFs,711565
68
+ seleniumbase/fixtures/base_case.py,sha256=vzgC_qp8nT1-6i7UMLB8KMiqrAyJuvw61oQJDLk0EdU,712816
69
69
  seleniumbase/fixtures/constants.py,sha256=XYYMpB-ZDI756LvfhSK9RxdqQ_qO9fJVXgBqBYlQNkk,13609
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=5o4CTLcCyd717lJ_atOYcC6kPRiZFx-LJIlixRrP_cE,51061
73
73
  seleniumbase/fixtures/page_actions.py,sha256=fOCb2NB2PpEaE8gpAVu-73VjwLzfwP1R9HsRkix_z6s,66634
74
74
  seleniumbase/fixtures/page_utils.py,sha256=5m7iXpikLs80TJoRO6_gEfXE1AKeQgcH1aFbR8o1C9A,12034
75
- seleniumbase/fixtures/shared_utils.py,sha256=QdoepYzSpt0J_iKQhhJCENY9ry0hB2juXKkEVI3TSTg,7263
75
+ seleniumbase/fixtures/shared_utils.py,sha256=MwCrt58YAv_XrfNfYjo_quUTWfYArlnf-aexSZGIyRs,7271
76
76
  seleniumbase/fixtures/unittest_helper.py,sha256=sfZ92rZeBAn_sF_yQ3I6_I7h3lyU5-cV_UMegBNoEm8,1294
77
77
  seleniumbase/fixtures/words.py,sha256=FOA4mAYvl3EPVpBTvgvK6YwCL8BdlRCmed685kEe7Vg,7827
78
78
  seleniumbase/fixtures/xpath_to_css.py,sha256=lML56k656fElXJ4NJF07r35FjctrbgQkXUotNk7A-as,8876
@@ -119,7 +119,7 @@ seleniumbase/undetected/cdp_driver/browser.py,sha256=mGmpWuR206yYJoBPTNslru8CbEp
119
119
  seleniumbase/undetected/cdp_driver/cdp_util.py,sha256=Erfb62fzpvGr0QIIJOiqvGkyoyBakHOIwgbrQ7dqUgM,16625
120
120
  seleniumbase/undetected/cdp_driver/config.py,sha256=Rjvde7V-XJ0ihZdTmOmHEVWSuDWm3SprQ3njg8SN3Go,12087
121
121
  seleniumbase/undetected/cdp_driver/connection.py,sha256=sOTUGjbUqKA2hPvDcRCdqw1VQjVGJs7mbgVvzS7ldtE,23360
122
- seleniumbase/undetected/cdp_driver/element.py,sha256=9oD9GxguctunrlHV3lWXlZgb9cNEjD5x03Oy84OqyVA,39631
122
+ seleniumbase/undetected/cdp_driver/element.py,sha256=wEHtuF9oiny7cb4QMMjdtD5Yf1z3WOs2_NHEWcscusM,40289
123
123
  seleniumbase/undetected/cdp_driver/tab.py,sha256=wUNF8GHrbhaUqg57A9ZTYHKhNPjZIcOHwrz3pj1SAg0,50526
124
124
  seleniumbase/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
125
125
  seleniumbase/utilities/selenium_grid/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -135,9 +135,9 @@ seleniumbase/utilities/selenium_grid/start-grid-hub.bat,sha256=Ftq-GrAKRYH2ssDPr
135
135
  seleniumbase/utilities/selenium_grid/start-grid-hub.sh,sha256=KADv0RUHONLL2_I443QFK8PryBpDmKn5Gy0s4o0vDSM,106
136
136
  seleniumbase/utilities/selenium_ide/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
137
137
  seleniumbase/utilities/selenium_ide/convert_ide.py,sha256=pZFnqEJQEKZPyNFjkLD29s2HPQgCrWW9XJWpCPhWOoM,31691
138
- seleniumbase-4.32.9.dist-info/LICENSE,sha256=odSYtWibXBnQ1gBg6CnDZ82n8kLF_if5-2nbqnEyD8k,1085
139
- seleniumbase-4.32.9.dist-info/METADATA,sha256=nd96od-BctakXK-zGmDPiKl4Ymfsz91frtzdx2s_rtg,86461
140
- seleniumbase-4.32.9.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
141
- seleniumbase-4.32.9.dist-info/entry_points.txt,sha256=CNrh2EKNaHYEhO6pP1RJyVLB99LkDDYX7TnUK8xfjqk,623
142
- seleniumbase-4.32.9.dist-info/top_level.txt,sha256=4N97aBOQ8ETCnDnokBsWb07lJfTaq3C1ZzYRxvLMxqU,19
143
- seleniumbase-4.32.9.dist-info/RECORD,,
138
+ seleniumbase-4.32.10a1.dist-info/LICENSE,sha256=odSYtWibXBnQ1gBg6CnDZ82n8kLF_if5-2nbqnEyD8k,1085
139
+ seleniumbase-4.32.10a1.dist-info/METADATA,sha256=rXnleRderXsIB3mEybQOL3r-Kes-dpZtM9rCeJ_v_A8,86464
140
+ seleniumbase-4.32.10a1.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
141
+ seleniumbase-4.32.10a1.dist-info/entry_points.txt,sha256=CNrh2EKNaHYEhO6pP1RJyVLB99LkDDYX7TnUK8xfjqk,623
142
+ seleniumbase-4.32.10a1.dist-info/top_level.txt,sha256=4N97aBOQ8ETCnDnokBsWb07lJfTaq3C1ZzYRxvLMxqU,19
143
+ seleniumbase-4.32.10a1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.0)
2
+ Generator: setuptools (75.5.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5