seleniumbase 4.31.6a4__py3-none-any.whl → 4.32.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,12 +4,17 @@ from selenium.webdriver.remote.webelement import WebElement
4
4
  from seleniumbase.fixtures import js_utils
5
5
  from seleniumbase.fixtures import page_actions
6
6
  from seleniumbase.fixtures import page_utils
7
+ from seleniumbase.fixtures import shared_utils
7
8
 
8
9
 
9
10
  class DriverMethods():
10
11
  def __init__(self, driver):
11
12
  self.driver = driver
12
13
 
14
+ def __is_cdp_swap_needed(self):
15
+ """If the driver is disconnected, use a CDP method when available."""
16
+ return shared_utils.is_cdp_swap_needed(self.driver)
17
+
13
18
  def find_element(self, by=None, value=None):
14
19
  if not value:
15
20
  value = by
@@ -45,10 +50,21 @@ class DriverMethods():
45
50
  element = self.locator(selector, by=by)
46
51
  return element.get_attribute(attribute)
47
52
 
53
+ def get_current_url(self):
54
+ if self.__is_cdp_swap_needed():
55
+ current_url = self.driver.cdp.get_current_url()
56
+ else:
57
+ current_url = self.driver.current_url
58
+ return current_url
59
+
48
60
  def get_page_source(self):
61
+ if self.__is_cdp_swap_needed():
62
+ return self.driver.cdp.get_page_source()
49
63
  return self.driver.page_source
50
64
 
51
65
  def get_title(self):
66
+ if self.__is_cdp_swap_needed():
67
+ return self.driver.cdp.get_title()
52
68
  return self.driver.title
53
69
 
54
70
  def open_url(self, *args, **kwargs):
@@ -175,6 +191,34 @@ class DriverMethods():
175
191
  def is_online(self):
176
192
  return self.driver.execute_script("return navigator.onLine;")
177
193
 
194
+ def is_connected(self):
195
+ """
196
+ Return True if WebDriver is connected to the browser.
197
+ Note that the stealthy CDP-Driver isn't a WebDriver.
198
+ In CDP Mode, the CDP-Driver controls the web browser.
199
+ The CDP-Driver can be connected while WebDriver isn't.
200
+ """
201
+ try:
202
+ self.driver.window_handles
203
+ return True
204
+ except Exception:
205
+ return False
206
+
207
+ def is_uc_mode_active(self):
208
+ """Return True if the driver is using UC Mode. False otherwise."""
209
+ return (
210
+ hasattr(self.driver, "_is_using_uc")
211
+ and self.driver._is_using_uc
212
+ )
213
+
214
+ def is_cdp_mode_active(self):
215
+ """CDP Mode is a special mode within UC Mode. Activated separately.
216
+ Return True if CDP Mode is loaded in the driver. False otherwise."""
217
+ return (
218
+ hasattr(self.driver, "_is_using_cdp")
219
+ and self.driver._is_using_cdp
220
+ )
221
+
178
222
  def js_click(self, *args, **kwargs):
179
223
  return page_actions.js_click(self.driver, *args, **kwargs)
180
224
 
@@ -223,6 +223,9 @@ class BaseCase(unittest.TestCase):
223
223
  def open(self, url):
224
224
  """Navigates the current browser window to the specified page."""
225
225
  self.__check_scope()
226
+ if self.__is_cdp_swap_needed():
227
+ self.cdp.open(url)
228
+ return
226
229
  self._check_browser()
227
230
  if self.__needs_minimum_wait():
228
231
  time.sleep(0.04)
@@ -388,6 +391,9 @@ class BaseCase(unittest.TestCase):
388
391
  original_selector = selector
389
392
  original_by = by
390
393
  selector, by = self.__recalculate_selector(selector, by)
394
+ if self.__is_cdp_swap_needed():
395
+ self.cdp.click(selector)
396
+ return
391
397
  if delay and (type(delay) in [int, float]) and delay > 0:
392
398
  time.sleep(delay)
393
399
  if page_utils.is_link_text_selector(selector) or by == By.LINK_TEXT:
@@ -878,6 +884,9 @@ class BaseCase(unittest.TestCase):
878
884
  if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
879
885
  timeout = self.__get_new_timeout(timeout)
880
886
  selector, by = self.__recalculate_selector(selector, by)
887
+ if self.__is_cdp_swap_needed():
888
+ self.cdp.type(selector, text)
889
+ return
881
890
  if self.__is_shadow_selector(selector):
882
891
  self.__shadow_type(selector, text, timeout)
883
892
  return
@@ -991,6 +1000,9 @@ class BaseCase(unittest.TestCase):
991
1000
  if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
992
1001
  timeout = self.__get_new_timeout(timeout)
993
1002
  selector, by = self.__recalculate_selector(selector, by)
1003
+ if self.__is_cdp_swap_needed():
1004
+ self.cdp.send_keys(selector, text)
1005
+ return
994
1006
  if self.__is_shadow_selector(selector):
995
1007
  self.__shadow_type(selector, text, timeout, clear_first=False)
996
1008
  return
@@ -1099,6 +1111,9 @@ class BaseCase(unittest.TestCase):
1099
1111
 
1100
1112
  def press_keys(self, selector, text, by="css selector", timeout=None):
1101
1113
  """Use send_keys() to press one key at a time."""
1114
+ if self.__is_cdp_swap_needed():
1115
+ self.cdp.press_keys(selector, text)
1116
+ return
1102
1117
  self.wait_for_ready_state_complete()
1103
1118
  element = self.wait_for_element_present(
1104
1119
  selector, by=by, timeout=timeout
@@ -1207,6 +1222,9 @@ class BaseCase(unittest.TestCase):
1207
1222
  if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
1208
1223
  timeout = self.__get_new_timeout(timeout)
1209
1224
  selector, by = self.__recalculate_selector(selector, by)
1225
+ if self.__is_cdp_swap_needed():
1226
+ self.cdp.focus(selector)
1227
+ return
1210
1228
  element = self.wait_for_element_present(
1211
1229
  selector, by=by, timeout=timeout
1212
1230
  )
@@ -1237,6 +1255,9 @@ class BaseCase(unittest.TestCase):
1237
1255
  def refresh_page(self):
1238
1256
  self.__check_scope()
1239
1257
  self.__last_page_load_url = None
1258
+ if self.__is_cdp_swap_needed():
1259
+ self.cdp.reload()
1260
+ return
1240
1261
  js_utils.clear_out_console_logs(self.driver)
1241
1262
  self.driver.refresh()
1242
1263
  self.wait_for_ready_state_complete()
@@ -1247,7 +1268,11 @@ class BaseCase(unittest.TestCase):
1247
1268
 
1248
1269
  def get_current_url(self):
1249
1270
  self.__check_scope()
1250
- current_url = self.driver.current_url
1271
+ current_url = None
1272
+ if self.__is_cdp_swap_needed():
1273
+ current_url = self.cdp.get_current_url()
1274
+ else:
1275
+ current_url = self.driver.current_url
1251
1276
  if "%" in current_url:
1252
1277
  try:
1253
1278
  from urllib.parse import unquote
@@ -1262,15 +1287,22 @@ class BaseCase(unittest.TestCase):
1262
1287
  return self.execute_script("return window.location.origin;")
1263
1288
 
1264
1289
  def get_page_source(self):
1290
+ if self.__is_cdp_swap_needed():
1291
+ return self.cdp.get_page_source()
1265
1292
  self.wait_for_ready_state_complete()
1266
1293
  if self.__needs_minimum_wait:
1267
- time.sleep(0.02)
1294
+ time.sleep(0.025)
1268
1295
  return self.driver.page_source
1269
1296
 
1270
1297
  def get_page_title(self):
1298
+ if self.__is_cdp_swap_needed():
1299
+ return self.cdp.get_title()
1271
1300
  self.wait_for_ready_state_complete()
1272
- self.wait_for_element_present("title", timeout=settings.SMALL_TIMEOUT)
1273
- time.sleep(0.03)
1301
+ with suppress(Exception):
1302
+ self.wait_for_element_present(
1303
+ "title", by="css selector", timeout=settings.MINI_TIMEOUT
1304
+ )
1305
+ time.sleep(0.025)
1274
1306
  return self.driver.title
1275
1307
 
1276
1308
  def get_title(self):
@@ -1365,7 +1397,7 @@ class BaseCase(unittest.TestCase):
1365
1397
  to convert the open() action into open_if_not_url() so that the
1366
1398
  same page isn't opened again if the user is already on the page."""
1367
1399
  self.__check_scope()
1368
- current_url = self.driver.current_url
1400
+ current_url = self.get_current_url()
1369
1401
  if current_url != url:
1370
1402
  if (
1371
1403
  "?q=" not in current_url
@@ -1377,6 +1409,8 @@ class BaseCase(unittest.TestCase):
1377
1409
 
1378
1410
  def is_element_present(self, selector, by="css selector"):
1379
1411
  """Returns whether the element exists in the HTML."""
1412
+ if self.__is_cdp_swap_needed():
1413
+ return self.cdp.is_element_present(selector)
1380
1414
  self.wait_for_ready_state_complete()
1381
1415
  selector, by = self.__recalculate_selector(selector, by)
1382
1416
  if self.__is_shadow_selector(selector):
@@ -1385,6 +1419,8 @@ class BaseCase(unittest.TestCase):
1385
1419
 
1386
1420
  def is_element_visible(self, selector, by="css selector"):
1387
1421
  """Returns whether the element is visible on the page."""
1422
+ if self.__is_cdp_swap_needed():
1423
+ return self.cdp.is_element_visible(selector)
1388
1424
  self.wait_for_ready_state_complete()
1389
1425
  selector, by = self.__recalculate_selector(selector, by)
1390
1426
  if self.__is_shadow_selector(selector):
@@ -1562,6 +1598,9 @@ class BaseCase(unittest.TestCase):
1562
1598
  if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
1563
1599
  timeout = self.__get_new_timeout(timeout)
1564
1600
  link_text = self.__get_type_checked_text(link_text)
1601
+ if self.__is_cdp_swap_needed():
1602
+ self.cdp.click_link(link_text)
1603
+ return
1565
1604
  if self.browser == "safari":
1566
1605
  if self.demo_mode:
1567
1606
  self.wait_for_link_text_present(link_text, timeout=timeout)
@@ -1794,6 +1833,8 @@ class BaseCase(unittest.TestCase):
1794
1833
  if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
1795
1834
  timeout = self.__get_new_timeout(timeout)
1796
1835
  selector, by = self.__recalculate_selector(selector, by)
1836
+ if self.__is_cdp_swap_needed():
1837
+ return self.cdp.get_text(selector)
1797
1838
  if self.__is_shadow_selector(selector):
1798
1839
  return self.__get_shadow_text(selector, timeout)
1799
1840
  self.wait_for_ready_state_complete()
@@ -1921,6 +1962,9 @@ class BaseCase(unittest.TestCase):
1921
1962
  self.set_attributes("a", "href", "https://google.com")"""
1922
1963
  self.__check_scope()
1923
1964
  selector, by = self.__recalculate_selector(selector, by)
1965
+ if self.__is_cdp_swap_needed():
1966
+ self.cdp.set_attributes(selector, attribute, value)
1967
+ return
1924
1968
  original_attribute = attribute
1925
1969
  original_value = value
1926
1970
  attribute = re.escape(attribute)
@@ -2001,6 +2045,14 @@ class BaseCase(unittest.TestCase):
2001
2045
  with suppress(Exception):
2002
2046
  self.execute_script(script)
2003
2047
 
2048
+ def internalize_links(self):
2049
+ """All `target="_blank"` links become `target="_self"`.
2050
+ This prevents those links from opening in a new tab."""
2051
+ if self.__is_cdp_swap_needed():
2052
+ self.cdp.internalize_links()
2053
+ return
2054
+ self.set_attributes('[target="_blank"]', "target", "_self")
2055
+
2004
2056
  def get_property(
2005
2057
  self, selector, property, by="css selector", timeout=None
2006
2058
  ):
@@ -2104,6 +2156,12 @@ class BaseCase(unittest.TestCase):
2104
2156
  Elements could be either hidden or visible on the page.
2105
2157
  If "limit" is set and > 0, will only return that many elements."""
2106
2158
  selector, by = self.__recalculate_selector(selector, by)
2159
+ if self.__is_cdp_swap_needed():
2160
+ elements = self.cdp.select_all(selector)
2161
+ if limit and limit > 0 and len(elements) > limit:
2162
+ elements = elements[:limit]
2163
+ return elements
2164
+
2107
2165
  self.wait_for_ready_state_complete()
2108
2166
  time.sleep(0.05)
2109
2167
  elements = self.driver.find_elements(by=by, value=selector)
@@ -2277,6 +2335,9 @@ class BaseCase(unittest.TestCase):
2277
2335
  Use click_visible_elements() to click all matching elements.
2278
2336
  If a "timeout" is provided, waits that long for the element
2279
2337
  to appear before giving up and returning without a click()."""
2338
+ if self.__is_cdp_swap_needed():
2339
+ self.cdp.click_if_visible(selector)
2340
+ return
2280
2341
  self.wait_for_ready_state_complete()
2281
2342
  if self.is_element_visible(selector, by=by):
2282
2343
  self.click(selector, by=by)
@@ -2289,6 +2350,9 @@ class BaseCase(unittest.TestCase):
2289
2350
  self.click(selector, by=by)
2290
2351
 
2291
2352
  def click_active_element(self):
2353
+ if self.__is_cdp_swap_needed():
2354
+ self.cdp.click_active_element()
2355
+ return
2292
2356
  self.wait_for_ready_state_complete()
2293
2357
  pre_action_url = None
2294
2358
  with suppress(Exception):
@@ -3311,6 +3375,8 @@ class BaseCase(unittest.TestCase):
3311
3375
  relative to the entire screen, rather than the browser window.
3312
3376
  This is specifically for PyAutoGUI actions on the full screen.
3313
3377
  (Note: There may be complications if iframes are involved.)"""
3378
+ if self.__is_cdp_swap_needed():
3379
+ return self.cdp.get_gui_element_rect(selector)
3314
3380
  element = self.wait_for_element_present(selector, by=by, timeout=1)
3315
3381
  element_rect = element.rect
3316
3382
  e_width = element_rect["width"]
@@ -3344,6 +3410,8 @@ class BaseCase(unittest.TestCase):
3344
3410
  on the entire GUI / screen, rather than on the browser window.
3345
3411
  This is specifically for PyAutoGUI actions on the full screen.
3346
3412
  (Note: There may be complications if iframes are involved.)"""
3413
+ if self.__is_cdp_swap_needed():
3414
+ return self.cdp.get_gui_element_center(selector)
3347
3415
  element_rect = self.get_gui_element_rect(selector, by=by)
3348
3416
  x = int(element_rect["x"]) + int(element_rect["width"] / 2) + 1
3349
3417
  y = int(element_rect["y"]) + int(element_rect["height"] / 2) + 1
@@ -3351,16 +3419,22 @@ class BaseCase(unittest.TestCase):
3351
3419
 
3352
3420
  def get_window_rect(self):
3353
3421
  self.__check_scope()
3422
+ if self.__is_cdp_swap_needed():
3423
+ return self.cdp.get_window_rect()
3354
3424
  self._check_browser()
3355
3425
  return self.driver.get_window_rect()
3356
3426
 
3357
3427
  def get_window_size(self):
3358
3428
  self.__check_scope()
3429
+ if self.__is_cdp_swap_needed():
3430
+ return self.cdp.get_window_size()
3359
3431
  self._check_browser()
3360
3432
  return self.driver.get_window_size()
3361
3433
 
3362
3434
  def get_window_position(self):
3363
3435
  self.__check_scope()
3436
+ if self.__is_cdp_swap_needed():
3437
+ return self.cdp.get_window_position()
3364
3438
  self._check_browser()
3365
3439
  return self.driver.get_window_position()
3366
3440
 
@@ -4138,12 +4212,16 @@ class BaseCase(unittest.TestCase):
4138
4212
  self.open(new_start_page)
4139
4213
  self.__dont_record_open = False
4140
4214
  if undetectable:
4215
+ if hasattr(new_driver, "cdp"):
4216
+ self.cdp = new_driver.cdp
4141
4217
  if hasattr(new_driver, "uc_open"):
4142
4218
  self.uc_open = new_driver.uc_open
4143
4219
  if hasattr(new_driver, "uc_open_with_tab"):
4144
4220
  self.uc_open_with_tab = new_driver.uc_open_with_tab
4145
4221
  if hasattr(new_driver, "uc_open_with_reconnect"):
4146
4222
  self.uc_open_with_reconnect = new_driver.uc_open_with_reconnect
4223
+ if hasattr(new_driver, "uc_open_with_cdp_mode"):
4224
+ self.uc_open_with_cdp_mode = new_driver.uc_open_with_cdp_mode
4147
4225
  if hasattr(new_driver, "uc_open_with_disconnect"):
4148
4226
  self.uc_open_with_disconnect = (
4149
4227
  new_driver.uc_open_with_disconnect
@@ -4207,6 +4285,9 @@ class BaseCase(unittest.TestCase):
4207
4285
  If a provided selector is not found, then takes a full-page screenshot.
4208
4286
  If the folder provided doesn't exist, it will get created.
4209
4287
  The screenshot will be in PNG format: (*.png)"""
4288
+ if self.__is_cdp_swap_needed():
4289
+ self.cdp.save_screenshot(name, folder=folder, selector=selector)
4290
+ return
4210
4291
  self.wait_for_ready_state_complete()
4211
4292
  if selector and by:
4212
4293
  selector, by = self.__recalculate_selector(selector, by)
@@ -4565,12 +4646,44 @@ class BaseCase(unittest.TestCase):
4565
4646
  script = """document.designMode = 'on';"""
4566
4647
  self.execute_script(script)
4567
4648
 
4568
- def deactivate_design_mode(self):
4649
+ def deactivate_design_mode(self, url=None):
4569
4650
  # Deactivate Chrome's Design Mode.
4570
4651
  self.wait_for_ready_state_complete()
4571
4652
  script = """document.designMode = 'off';"""
4572
4653
  self.execute_script(script)
4573
4654
 
4655
+ def activate_cdp_mode(self, url=None):
4656
+ if hasattr(self.driver, "_is_using_uc") and self.driver._is_using_uc:
4657
+ self.driver.uc_open_with_cdp_mode(url)
4658
+ else:
4659
+ # Fix Chrome-130 issues by creating a user-data-dir in advance
4660
+ if (
4661
+ (
4662
+ not self.user_data_dir
4663
+ or not os.path.exists(self.user_data_dir)
4664
+ )
4665
+ and self.browser == "chrome"
4666
+ ):
4667
+ import tempfile
4668
+ user_data_dir = os.path.normpath(tempfile.mkdtemp())
4669
+ self.user_data_dir = user_data_dir
4670
+ sb_config.user_data_dir = user_data_dir
4671
+ try:
4672
+ driver = self.get_new_driver(
4673
+ user_data_dir=user_data_dir,
4674
+ undetectable=True,
4675
+ headless2=True,
4676
+ )
4677
+ time.sleep(0.555)
4678
+ except Exception:
4679
+ pass
4680
+ finally:
4681
+ with suppress(Exception):
4682
+ driver.quit()
4683
+ self.get_new_driver(undetectable=True)
4684
+ self.driver.uc_open_with_cdp_mode(url)
4685
+ self.cdp = self.driver.cdp
4686
+
4574
4687
  def activate_recorder(self):
4575
4688
  from seleniumbase.js_code.recorder_js import recorder_js
4576
4689
 
@@ -5589,6 +5702,9 @@ class BaseCase(unittest.TestCase):
5589
5702
  """Brings the active browser window to the front (on top).
5590
5703
  Useful when multiple drivers are being used at the same time."""
5591
5704
  self.__check_scope()
5705
+ if self.__is_cdp_swap_needed():
5706
+ self.cdp.bring_active_window_to_front()
5707
+ return
5592
5708
  with suppress(Exception):
5593
5709
  if not self.__is_in_frame():
5594
5710
  # Only bring the window to the front if not in a frame
@@ -5804,6 +5920,7 @@ class BaseCase(unittest.TestCase):
5804
5920
  scroll - the option to scroll to the element first (Default: True)
5805
5921
  timeout - the time to wait for the element to appear """
5806
5922
  self.__check_scope()
5923
+ self._check_browser()
5807
5924
  self.__skip_if_esc()
5808
5925
  if isinstance(selector, WebElement):
5809
5926
  self.__highlight_element(selector, loops=loops, scroll=scroll)
@@ -6004,6 +6121,9 @@ class BaseCase(unittest.TestCase):
6004
6121
  timeout = settings.SMALL_TIMEOUT
6005
6122
  if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
6006
6123
  timeout = self.__get_new_timeout(timeout)
6124
+ if self.__is_cdp_swap_needed():
6125
+ self.cdp.scroll_into_view(selector)
6126
+ return
6007
6127
  element = self.wait_for_element_visible(selector, by, timeout=timeout)
6008
6128
  self.execute_script("arguments[0].scrollIntoView();", element)
6009
6129
 
@@ -6046,6 +6166,9 @@ class BaseCase(unittest.TestCase):
6046
6166
  Can be used to click hidden / invisible elements.
6047
6167
  If "all_matches" is False, only the first match is clicked.
6048
6168
  If "scroll" is False, won't scroll unless running in Demo Mode."""
6169
+ if self.__is_cdp_swap_needed():
6170
+ self.cdp.click(selector)
6171
+ return
6049
6172
  self.wait_for_ready_state_complete()
6050
6173
  if not timeout or timeout is True:
6051
6174
  timeout = settings.SMALL_TIMEOUT
@@ -6414,6 +6537,9 @@ class BaseCase(unittest.TestCase):
6414
6537
  def remove_element(self, selector, by="css selector"):
6415
6538
  """Remove the first element on the page that matches the selector."""
6416
6539
  self.__check_scope()
6540
+ if self.__is_cdp_swap_needed():
6541
+ self.cdp.remove_element(selector)
6542
+ return
6417
6543
  element = None
6418
6544
  with suppress(Exception):
6419
6545
  self.wait_for_element_visible("body", timeout=1.5)
@@ -6445,6 +6571,9 @@ class BaseCase(unittest.TestCase):
6445
6571
  def remove_elements(self, selector, by="css selector"):
6446
6572
  """Remove all elements on the page that match the selector."""
6447
6573
  self.__check_scope()
6574
+ if self.__is_cdp_swap_needed():
6575
+ self.cdp.remove_elements(selector)
6576
+ return
6448
6577
  with suppress(Exception):
6449
6578
  self.wait_for_element_visible("body", timeout=1.5)
6450
6579
  selector, by = self.__recalculate_selector(selector, by)
@@ -7829,6 +7958,15 @@ class BaseCase(unittest.TestCase):
7829
7958
  """Return True if connected to the Internet."""
7830
7959
  return self.execute_script("return navigator.onLine;")
7831
7960
 
7961
+ def is_connected(self):
7962
+ """
7963
+ Return True if WebDriver is connected to the browser.
7964
+ Note that the stealthy CDP-Driver isn't a WebDriver.
7965
+ In CDP Mode, the CDP-Driver controls the web browser.
7966
+ The CDP-Driver can be connected while WebDriver isn't.
7967
+ """
7968
+ return self.driver.is_connected()
7969
+
7832
7970
  def is_chromium(self):
7833
7971
  """Return True if the browser is Chrome or Edge."""
7834
7972
  self.__check_scope()
@@ -7944,6 +8082,10 @@ class BaseCase(unittest.TestCase):
7944
8082
  self.__check_scope()
7945
8083
  if not timeout:
7946
8084
  timeout = settings.SMALL_TIMEOUT
8085
+ if self.__is_cdp_swap_needed():
8086
+ mfa_code = self.get_mfa_code(totp_key)
8087
+ self.cdp.type(selector, mfa_code + "\n")
8088
+ return
7947
8089
  self.wait_for_element_visible(selector, by=by, timeout=timeout)
7948
8090
  if self.recorder_mode and self.__current_url_is_recordable():
7949
8091
  if self.get_session_storage_item("pause_recorder") == "no":
@@ -7981,6 +8123,9 @@ class BaseCase(unittest.TestCase):
7981
8123
  if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
7982
8124
  timeout = self.__get_new_timeout(timeout)
7983
8125
  selector, by = self.__recalculate_selector(selector, by, xp_ok=False)
8126
+ if self.__is_cdp_swap_needed():
8127
+ self.cdp.type(selector, text)
8128
+ return
7984
8129
  self.wait_for_ready_state_complete()
7985
8130
  self.wait_for_element_present(selector, by=by, timeout=timeout)
7986
8131
  original_selector = selector
@@ -8696,6 +8841,8 @@ class BaseCase(unittest.TestCase):
8696
8841
  timeout = self.__get_new_timeout(timeout)
8697
8842
  original_selector = selector
8698
8843
  selector, by = self.__recalculate_selector(selector, by)
8844
+ if self.__is_cdp_swap_needed():
8845
+ return self.cdp.select(selector)
8699
8846
  if self.__is_shadow_selector(selector):
8700
8847
  return self.__get_shadow_element(selector, timeout)
8701
8848
  return page_actions.wait_for_element_visible(
@@ -8751,6 +8898,9 @@ class BaseCase(unittest.TestCase):
8751
8898
  original_selector=original_selector,
8752
8899
  )
8753
8900
 
8901
+ def select_all(self, selector, by="css selector", limit=0):
8902
+ return self.find_elements(selector, by=by, limit=limit)
8903
+
8754
8904
  def assert_link(self, link_text, timeout=None):
8755
8905
  """Same as self.assert_link_text()"""
8756
8906
  self.__check_scope()
@@ -8825,6 +8975,7 @@ class BaseCase(unittest.TestCase):
8825
8975
  def _check_browser(self):
8826
8976
  """This method raises an exception if the active window is closed.
8827
8977
  (This provides a much cleaner exception message in this situation.)"""
8978
+ page_actions._reconnect_if_disconnected(self.driver)
8828
8979
  active_window = None
8829
8980
  with suppress(Exception):
8830
8981
  active_window = self.driver.current_window_handle # Fails if None
@@ -9109,6 +9260,8 @@ class BaseCase(unittest.TestCase):
9109
9260
  timeout = self.__get_new_timeout(timeout)
9110
9261
  original_selector = selector
9111
9262
  selector, by = self.__recalculate_selector(selector, by)
9263
+ if self.__is_cdp_swap_needed():
9264
+ return self.cdp.select(selector)
9112
9265
  if self.__is_shadow_selector(selector):
9113
9266
  return self.__wait_for_shadow_element_present(selector, timeout)
9114
9267
  return page_actions.wait_for_element_present(
@@ -9129,6 +9282,8 @@ class BaseCase(unittest.TestCase):
9129
9282
  timeout = self.__get_new_timeout(timeout)
9130
9283
  original_selector = selector
9131
9284
  selector, by = self.__recalculate_selector(selector, by)
9285
+ if self.__is_cdp_swap_needed():
9286
+ return self.cdp.select(selector)
9132
9287
  if self.recorder_mode and self.__current_url_is_recordable():
9133
9288
  if self.get_session_storage_item("pause_recorder") == "no":
9134
9289
  if by == By.XPATH:
@@ -9189,6 +9344,9 @@ class BaseCase(unittest.TestCase):
9189
9344
  if isinstance(selector, list):
9190
9345
  self.assert_elements_present(selector, by=by, timeout=timeout)
9191
9346
  return True
9347
+ if self.__is_cdp_swap_needed():
9348
+ self.cdp.assert_element_present(selector)
9349
+ return True
9192
9350
  if self.__is_shadow_selector(selector):
9193
9351
  self.__assert_shadow_element_present(selector)
9194
9352
  return True
@@ -9263,6 +9421,9 @@ class BaseCase(unittest.TestCase):
9263
9421
  timeout = settings.SMALL_TIMEOUT
9264
9422
  if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
9265
9423
  timeout = self.__get_new_timeout(timeout)
9424
+ if self.__is_cdp_swap_needed():
9425
+ self.cdp.assert_element(selector)
9426
+ return True
9266
9427
  if isinstance(selector, list):
9267
9428
  self.assert_elements(selector, by=by, timeout=timeout)
9268
9429
  return True
@@ -9383,6 +9544,8 @@ class BaseCase(unittest.TestCase):
9383
9544
  timeout = self.__get_new_timeout(timeout)
9384
9545
  text = self.__get_type_checked_text(text)
9385
9546
  selector, by = self.__recalculate_selector(selector, by)
9547
+ if self.__is_cdp_swap_needed():
9548
+ return self.cdp.find_element(selector)
9386
9549
  if self.__is_shadow_selector(selector):
9387
9550
  return self.__wait_for_shadow_text_visible(text, selector, timeout)
9388
9551
  return page_actions.wait_for_text_visible(
@@ -9551,6 +9714,11 @@ class BaseCase(unittest.TestCase):
9551
9714
  self.__highlight_with_assert_success(
9552
9715
  messenger_post, selector, by
9553
9716
  )
9717
+ elif self.__is_cdp_swap_needed():
9718
+ self.cdp.assert_text(text, selector)
9719
+ return True
9720
+ elif not self.is_connected():
9721
+ self.connect()
9554
9722
  elif self.__is_shadow_selector(selector):
9555
9723
  self.__assert_shadow_text_visible(text, selector, timeout)
9556
9724
  return True
@@ -9596,6 +9764,9 @@ class BaseCase(unittest.TestCase):
9596
9764
  timeout = self.__get_new_timeout(timeout)
9597
9765
  original_selector = selector
9598
9766
  selector, by = self.__recalculate_selector(selector, by)
9767
+ if self.__is_cdp_swap_needed():
9768
+ self.cdp.assert_exact_text(text, selector)
9769
+ return True
9599
9770
  if self.__is_shadow_selector(selector):
9600
9771
  self.__assert_exact_shadow_text_visible(text, selector, timeout)
9601
9772
  return True
@@ -10578,6 +10749,12 @@ class BaseCase(unittest.TestCase):
10578
10749
 
10579
10750
  ############
10580
10751
 
10752
+ def __is_cdp_swap_needed(self):
10753
+ """If the driver is disconnected, use a CDP method when available."""
10754
+ return shared_utils.is_cdp_swap_needed(self.driver)
10755
+
10756
+ ############
10757
+
10581
10758
  def __check_scope(self):
10582
10759
  if hasattr(self, "browser"): # self.browser stores the type of browser
10583
10760
  return # All good: setUp() already initialized variables in "self"
@@ -14764,6 +14941,31 @@ class BaseCase(unittest.TestCase):
14764
14941
  self.__js_start_time = int(time.time() * 1000.0)
14765
14942
  else:
14766
14943
  # Launch WebDriver for both pytest and pynose
14944
+
14945
+ # Fix Chrome-130 issues by creating a user-data-dir in advance
14946
+ if (
14947
+ self.undetectable
14948
+ and (
14949
+ not self.user_data_dir
14950
+ or not os.path.exists(self.user_data_dir)
14951
+ )
14952
+ and self.browser == "chrome"
14953
+ ):
14954
+ import tempfile
14955
+ user_data_dir = os.path.normpath(tempfile.mkdtemp())
14956
+ self.user_data_dir = user_data_dir
14957
+ sb_config.user_data_dir = user_data_dir
14958
+ try:
14959
+ driver = self.get_new_driver(
14960
+ user_data_dir=user_data_dir,
14961
+ headless2=True,
14962
+ )
14963
+ time.sleep(0.555)
14964
+ except Exception:
14965
+ pass
14966
+ finally:
14967
+ with suppress(Exception):
14968
+ driver.quit()
14767
14969
  self.driver = self.get_new_driver(
14768
14970
  browser=self.browser,
14769
14971
  headless=self.headless,
@@ -375,6 +375,7 @@ class Mobile:
375
375
 
376
376
  class UC:
377
377
  RECONNECT_TIME = 2.4 # Seconds
378
+ CDP_MODE_OPEN_WAIT = 0.9 # Seconds
378
379
 
379
380
 
380
381
  class ValidBrowsers:
@@ -243,6 +243,10 @@ def escape_quotes_if_needed(string):
243
243
  def is_in_frame(driver):
244
244
  # Returns True if the driver has switched to a frame.
245
245
  # Returns False if the driver was on default content.
246
+ from seleniumbase.fixtures import shared_utils
247
+
248
+ if shared_utils.is_cdp_swap_needed(driver):
249
+ return False
246
250
  in_basic_frame = driver.execute_script(
247
251
  """
248
252
  var frame = window.frameElement;