seleniumbase 4.24.10__py3-none-any.whl → 4.33.15__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.
- sbase/__init__.py +1 -0
- sbase/steps.py +7 -0
- seleniumbase/__init__.py +16 -7
- seleniumbase/__version__.py +1 -1
- seleniumbase/behave/behave_sb.py +97 -32
- seleniumbase/common/decorators.py +16 -7
- seleniumbase/config/proxy_list.py +3 -3
- seleniumbase/config/settings.py +4 -0
- seleniumbase/console_scripts/logo_helper.py +47 -8
- seleniumbase/console_scripts/run.py +345 -335
- seleniumbase/console_scripts/sb_behave_gui.py +5 -12
- seleniumbase/console_scripts/sb_caseplans.py +6 -13
- seleniumbase/console_scripts/sb_commander.py +5 -12
- seleniumbase/console_scripts/sb_install.py +62 -54
- seleniumbase/console_scripts/sb_mkchart.py +13 -20
- seleniumbase/console_scripts/sb_mkdir.py +11 -17
- seleniumbase/console_scripts/sb_mkfile.py +69 -43
- seleniumbase/console_scripts/sb_mkpres.py +13 -20
- seleniumbase/console_scripts/sb_mkrec.py +88 -21
- seleniumbase/console_scripts/sb_objectify.py +30 -30
- seleniumbase/console_scripts/sb_print.py +5 -12
- seleniumbase/console_scripts/sb_recorder.py +16 -11
- seleniumbase/core/browser_launcher.py +1658 -221
- seleniumbase/core/detect_b_ver.py +7 -8
- seleniumbase/core/log_helper.py +42 -27
- seleniumbase/core/mysql.py +1 -4
- seleniumbase/core/proxy_helper.py +35 -30
- seleniumbase/core/recorder_helper.py +24 -5
- seleniumbase/core/sb_cdp.py +1951 -0
- seleniumbase/core/sb_driver.py +162 -8
- seleniumbase/core/settings_parser.py +6 -0
- seleniumbase/core/style_sheet.py +10 -0
- seleniumbase/extensions/recorder.zip +0 -0
- seleniumbase/fixtures/base_case.py +1234 -632
- seleniumbase/fixtures/constants.py +10 -1
- seleniumbase/fixtures/js_utils.py +171 -144
- seleniumbase/fixtures/page_actions.py +177 -13
- seleniumbase/fixtures/page_utils.py +25 -53
- seleniumbase/fixtures/shared_utils.py +97 -11
- seleniumbase/js_code/active_css_js.py +1 -1
- seleniumbase/js_code/recorder_js.py +1 -1
- seleniumbase/plugins/base_plugin.py +2 -3
- seleniumbase/plugins/driver_manager.py +340 -65
- seleniumbase/plugins/pytest_plugin.py +276 -47
- seleniumbase/plugins/sb_manager.py +412 -99
- seleniumbase/plugins/selenium_plugin.py +122 -17
- seleniumbase/translate/translator.py +0 -7
- seleniumbase/undetected/__init__.py +59 -52
- seleniumbase/undetected/cdp.py +0 -1
- seleniumbase/undetected/cdp_driver/__init__.py +1 -0
- seleniumbase/undetected/cdp_driver/_contradict.py +110 -0
- seleniumbase/undetected/cdp_driver/browser.py +829 -0
- seleniumbase/undetected/cdp_driver/cdp_util.py +458 -0
- seleniumbase/undetected/cdp_driver/config.py +334 -0
- seleniumbase/undetected/cdp_driver/connection.py +639 -0
- seleniumbase/undetected/cdp_driver/element.py +1168 -0
- seleniumbase/undetected/cdp_driver/tab.py +1323 -0
- seleniumbase/undetected/dprocess.py +4 -7
- seleniumbase/undetected/options.py +6 -8
- seleniumbase/undetected/patcher.py +11 -13
- seleniumbase/undetected/reactor.py +0 -1
- seleniumbase/undetected/webelement.py +16 -3
- {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/LICENSE +1 -1
- {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/METADATA +299 -252
- {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/RECORD +68 -70
- {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/WHEEL +1 -1
- sbase/ReadMe.txt +0 -2
- seleniumbase/ReadMe.md +0 -25
- seleniumbase/common/ReadMe.md +0 -71
- seleniumbase/console_scripts/ReadMe.md +0 -731
- seleniumbase/drivers/ReadMe.md +0 -27
- seleniumbase/extensions/ReadMe.md +0 -12
- seleniumbase/masterqa/ReadMe.md +0 -61
- seleniumbase/resources/ReadMe.md +0 -31
- seleniumbase/resources/favicon.ico +0 -0
- seleniumbase/utilities/selenium_grid/ReadMe.md +0 -84
- seleniumbase/utilities/selenium_ide/ReadMe.md +0 -111
- {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/entry_points.txt +0 -0
- {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/top_level.txt +0 -0
@@ -18,8 +18,10 @@ By.TAG_NAME # "tag name"
|
|
18
18
|
By.PARTIAL_LINK_TEXT # "partial link text"
|
19
19
|
"""
|
20
20
|
import codecs
|
21
|
+
import fasteners
|
21
22
|
import os
|
22
23
|
import time
|
24
|
+
from contextlib import suppress
|
23
25
|
from selenium.common.exceptions import ElementNotInteractableException
|
24
26
|
from selenium.common.exceptions import ElementNotVisibleException
|
25
27
|
from selenium.common.exceptions import NoAlertPresentException
|
@@ -32,6 +34,7 @@ from selenium.webdriver.common.keys import Keys
|
|
32
34
|
from seleniumbase.common.exceptions import LinkTextNotFoundException
|
33
35
|
from seleniumbase.common.exceptions import TextNotVisibleException
|
34
36
|
from seleniumbase.config import settings
|
37
|
+
from seleniumbase.fixtures import constants
|
35
38
|
from seleniumbase.fixtures import page_utils
|
36
39
|
from seleniumbase.fixtures import shared_utils
|
37
40
|
|
@@ -46,6 +49,8 @@ def is_element_present(driver, selector, by="css selector"):
|
|
46
49
|
@Returns
|
47
50
|
Boolean (is element present)
|
48
51
|
"""
|
52
|
+
if __is_cdp_swap_needed(driver):
|
53
|
+
return driver.cdp.is_element_present(selector)
|
49
54
|
selector, by = page_utils.swap_selector_and_by_if_reversed(selector, by)
|
50
55
|
try:
|
51
56
|
driver.find_element(by=by, value=selector)
|
@@ -64,6 +69,8 @@ def is_element_visible(driver, selector, by="css selector"):
|
|
64
69
|
@Returns
|
65
70
|
Boolean (is element visible)
|
66
71
|
"""
|
72
|
+
if __is_cdp_swap_needed(driver):
|
73
|
+
return driver.cdp.is_element_visible(selector)
|
67
74
|
selector, by = page_utils.swap_selector_and_by_if_reversed(selector, by)
|
68
75
|
try:
|
69
76
|
element = driver.find_element(by=by, value=selector)
|
@@ -82,6 +89,7 @@ def is_element_clickable(driver, selector, by="css selector"):
|
|
82
89
|
@Returns
|
83
90
|
Boolean (is element clickable)
|
84
91
|
"""
|
92
|
+
_reconnect_if_disconnected(driver)
|
85
93
|
try:
|
86
94
|
element = driver.find_element(by=by, value=selector)
|
87
95
|
if element.is_displayed() and element.is_enabled():
|
@@ -101,6 +109,7 @@ def is_element_enabled(driver, selector, by="css selector"):
|
|
101
109
|
@Returns
|
102
110
|
Boolean (is element enabled)
|
103
111
|
"""
|
112
|
+
_reconnect_if_disconnected(driver)
|
104
113
|
try:
|
105
114
|
element = driver.find_element(by=by, value=selector)
|
106
115
|
return element.is_enabled()
|
@@ -119,6 +128,7 @@ def is_text_visible(driver, text, selector="html", by="css selector"):
|
|
119
128
|
@Returns
|
120
129
|
Boolean (is text visible)
|
121
130
|
"""
|
131
|
+
_reconnect_if_disconnected(driver)
|
122
132
|
selector, by = page_utils.swap_selector_and_by_if_reversed(selector, by)
|
123
133
|
text = str(text)
|
124
134
|
try:
|
@@ -148,6 +158,7 @@ def is_exact_text_visible(driver, text, selector, by="css selector"):
|
|
148
158
|
@Returns
|
149
159
|
Boolean (is text visible)
|
150
160
|
"""
|
161
|
+
_reconnect_if_disconnected(driver)
|
151
162
|
selector, by = page_utils.swap_selector_and_by_if_reversed(selector, by)
|
152
163
|
text = str(text)
|
153
164
|
try:
|
@@ -182,6 +193,7 @@ def is_attribute_present(
|
|
182
193
|
@Returns
|
183
194
|
Boolean (is attribute present)
|
184
195
|
"""
|
196
|
+
_reconnect_if_disconnected(driver)
|
185
197
|
try:
|
186
198
|
element = driver.find_element(by=by, value=selector)
|
187
199
|
found_value = element.get_attribute(attribute)
|
@@ -208,6 +220,7 @@ def is_non_empty_text_visible(driver, selector, by="css selector"):
|
|
208
220
|
@Returns
|
209
221
|
Boolean (is any text visible in the element with the selector)
|
210
222
|
"""
|
223
|
+
_reconnect_if_disconnected(driver)
|
211
224
|
try:
|
212
225
|
element = driver.find_element(by=by, value=selector)
|
213
226
|
element_text = element.text
|
@@ -232,6 +245,7 @@ def hover_on_element(driver, selector, by="css selector"):
|
|
232
245
|
selector - the locator for identifying the page element (required)
|
233
246
|
by - the type of selector being used (Default: "css selector")
|
234
247
|
"""
|
248
|
+
_reconnect_if_disconnected(driver)
|
235
249
|
element = driver.find_element(by=by, value=selector)
|
236
250
|
hover = ActionChains(driver).move_to_element(element)
|
237
251
|
hover.perform()
|
@@ -242,6 +256,7 @@ def hover_element(driver, element):
|
|
242
256
|
"""
|
243
257
|
Similar to hover_on_element(), but uses found element, not a selector.
|
244
258
|
"""
|
259
|
+
_reconnect_if_disconnected(driver)
|
245
260
|
hover = ActionChains(driver).move_to_element(element)
|
246
261
|
hover.perform()
|
247
262
|
return element
|
@@ -273,6 +288,7 @@ def hover_and_click(
|
|
273
288
|
timeout - number of seconds to wait for click element to appear after hover
|
274
289
|
js_click - the option to use js_click() instead of click() on the last part
|
275
290
|
"""
|
291
|
+
_reconnect_if_disconnected(driver)
|
276
292
|
start_ms = time.time() * 1000.0
|
277
293
|
stop_ms = start_ms + (timeout * 1000.0)
|
278
294
|
element = driver.find_element(by=hover_by, value=hover_selector)
|
@@ -312,6 +328,7 @@ def hover_element_and_click(
|
|
312
328
|
"""
|
313
329
|
Similar to hover_and_click(), but assumes top element is already found.
|
314
330
|
"""
|
331
|
+
_reconnect_if_disconnected(driver)
|
315
332
|
start_ms = time.time() * 1000.0
|
316
333
|
stop_ms = start_ms + (timeout * 1000.0)
|
317
334
|
hover = ActionChains(driver).move_to_element(element)
|
@@ -344,6 +361,7 @@ def hover_element_and_double_click(
|
|
344
361
|
click_by="css selector",
|
345
362
|
timeout=settings.SMALL_TIMEOUT,
|
346
363
|
):
|
364
|
+
_reconnect_if_disconnected(driver)
|
347
365
|
start_ms = time.time() * 1000.0
|
348
366
|
stop_ms = start_ms + (timeout * 1000.0)
|
349
367
|
hover = ActionChains(driver).move_to_element(element)
|
@@ -395,6 +413,7 @@ def wait_for_element_present(
|
|
395
413
|
@Returns
|
396
414
|
A web element object
|
397
415
|
"""
|
416
|
+
_reconnect_if_disconnected(driver)
|
398
417
|
element = None
|
399
418
|
start_ms = time.time() * 1000.0
|
400
419
|
stop_ms = start_ms + (timeout * 1000.0)
|
@@ -454,6 +473,7 @@ def wait_for_element_visible(
|
|
454
473
|
@Returns
|
455
474
|
A web element object
|
456
475
|
"""
|
476
|
+
_reconnect_if_disconnected(driver)
|
457
477
|
element = None
|
458
478
|
is_present = False
|
459
479
|
start_ms = time.time() * 1000.0
|
@@ -535,6 +555,7 @@ def wait_for_text_visible(
|
|
535
555
|
@Returns
|
536
556
|
A web element object that contains the text searched for
|
537
557
|
"""
|
558
|
+
_reconnect_if_disconnected(driver)
|
538
559
|
element = None
|
539
560
|
is_present = False
|
540
561
|
full_text = None
|
@@ -645,6 +666,7 @@ def wait_for_exact_text_visible(
|
|
645
666
|
@Returns
|
646
667
|
A web element object that contains the text searched for
|
647
668
|
"""
|
669
|
+
_reconnect_if_disconnected(driver)
|
648
670
|
element = None
|
649
671
|
is_present = False
|
650
672
|
actual_text = None
|
@@ -755,6 +777,7 @@ def wait_for_attribute(
|
|
755
777
|
@Returns
|
756
778
|
A web element object that contains the expected attribute/value
|
757
779
|
"""
|
780
|
+
_reconnect_if_disconnected(driver)
|
758
781
|
element = None
|
759
782
|
element_present = False
|
760
783
|
attribute_present = False
|
@@ -841,6 +864,7 @@ def wait_for_element_clickable(
|
|
841
864
|
@Returns
|
842
865
|
A web element object
|
843
866
|
"""
|
867
|
+
_reconnect_if_disconnected(driver)
|
844
868
|
element = None
|
845
869
|
is_present = False
|
846
870
|
is_visible = False
|
@@ -935,6 +959,7 @@ def wait_for_element_absent(
|
|
935
959
|
timeout - the time to wait for elements in seconds
|
936
960
|
original_selector - handle pre-converted ":contains(TEXT)" selector
|
937
961
|
"""
|
962
|
+
_reconnect_if_disconnected(driver)
|
938
963
|
start_ms = time.time() * 1000.0
|
939
964
|
stop_ms = start_ms + (timeout * 1000.0)
|
940
965
|
for x in range(int(timeout * 10)):
|
@@ -982,6 +1007,7 @@ def wait_for_element_not_visible(
|
|
982
1007
|
timeout - the time to wait for the element in seconds
|
983
1008
|
original_selector - handle pre-converted ":contains(TEXT)" selector
|
984
1009
|
"""
|
1010
|
+
_reconnect_if_disconnected(driver)
|
985
1011
|
start_ms = time.time() * 1000.0
|
986
1012
|
stop_ms = start_ms + (timeout * 1000.0)
|
987
1013
|
for x in range(int(timeout * 10)):
|
@@ -1017,7 +1043,7 @@ def wait_for_element_not_visible(
|
|
1017
1043
|
def wait_for_text_not_visible(
|
1018
1044
|
driver,
|
1019
1045
|
text,
|
1020
|
-
selector,
|
1046
|
+
selector="html",
|
1021
1047
|
by="css selector",
|
1022
1048
|
timeout=settings.LARGE_TIMEOUT,
|
1023
1049
|
):
|
@@ -1034,6 +1060,7 @@ def wait_for_text_not_visible(
|
|
1034
1060
|
@Returns
|
1035
1061
|
A web element object that contains the text searched for
|
1036
1062
|
"""
|
1063
|
+
_reconnect_if_disconnected(driver)
|
1037
1064
|
text = str(text)
|
1038
1065
|
start_ms = time.time() * 1000.0
|
1039
1066
|
stop_ms = start_ms + (timeout * 1000.0)
|
@@ -1060,7 +1087,7 @@ def wait_for_text_not_visible(
|
|
1060
1087
|
def wait_for_exact_text_not_visible(
|
1061
1088
|
driver,
|
1062
1089
|
text,
|
1063
|
-
selector,
|
1090
|
+
selector="html",
|
1064
1091
|
by="css selector",
|
1065
1092
|
timeout=settings.LARGE_TIMEOUT,
|
1066
1093
|
):
|
@@ -1077,6 +1104,7 @@ def wait_for_exact_text_not_visible(
|
|
1077
1104
|
@Returns
|
1078
1105
|
A web element object that contains the text searched for
|
1079
1106
|
"""
|
1107
|
+
_reconnect_if_disconnected(driver)
|
1080
1108
|
text = str(text)
|
1081
1109
|
start_ms = time.time() * 1000.0
|
1082
1110
|
stop_ms = start_ms + (timeout * 1000.0)
|
@@ -1119,6 +1147,7 @@ def wait_for_non_empty_text_visible(
|
|
1119
1147
|
@Returns
|
1120
1148
|
The web element object that has text
|
1121
1149
|
"""
|
1150
|
+
_reconnect_if_disconnected(driver)
|
1122
1151
|
start_ms = time.time() * 1000.0
|
1123
1152
|
stop_ms = start_ms + (timeout * 1000.0)
|
1124
1153
|
element = None
|
@@ -1236,6 +1265,7 @@ def find_visible_elements(driver, selector, by="css selector", limit=0):
|
|
1236
1265
|
by - the type of selector being used (Default: "css selector")
|
1237
1266
|
limit - the maximum number of elements to return if > 0.
|
1238
1267
|
"""
|
1268
|
+
_reconnect_if_disconnected(driver)
|
1239
1269
|
elements = driver.find_elements(by=by, value=selector)
|
1240
1270
|
if limit and limit > 0 and len(elements) > limit:
|
1241
1271
|
elements = elements[:limit]
|
@@ -1273,6 +1303,7 @@ def save_screenshot(
|
|
1273
1303
|
If the folder provided doesn't exist, it will get created.
|
1274
1304
|
The screenshot will be in PNG format: (*.png)
|
1275
1305
|
"""
|
1306
|
+
_reconnect_if_disconnected(driver)
|
1276
1307
|
if not name.endswith(".png"):
|
1277
1308
|
name = name + ".png"
|
1278
1309
|
if folder:
|
@@ -1311,6 +1342,8 @@ def save_page_source(driver, name, folder=None):
|
|
1311
1342
|
"""
|
1312
1343
|
from seleniumbase.core import log_helper
|
1313
1344
|
|
1345
|
+
if not __is_cdp_swap_needed(driver):
|
1346
|
+
_reconnect_if_disconnected(driver) # If disconnected without CDP
|
1314
1347
|
if not name.endswith(".html"):
|
1315
1348
|
name = name + ".html"
|
1316
1349
|
if folder:
|
@@ -1321,7 +1354,11 @@ def save_page_source(driver, name, folder=None):
|
|
1321
1354
|
html_file_path = os.path.join(file_path, name)
|
1322
1355
|
else:
|
1323
1356
|
html_file_path = name
|
1324
|
-
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
|
1325
1362
|
html_file = codecs.open(html_file_path, "w+", "utf-8")
|
1326
1363
|
rendered_source = log_helper.get_html_source_with_base_href(
|
1327
1364
|
driver, page_source
|
@@ -1337,6 +1374,7 @@ def wait_for_and_accept_alert(driver, timeout=settings.LARGE_TIMEOUT):
|
|
1337
1374
|
driver - the webdriver object (required)
|
1338
1375
|
timeout - the time to wait for the alert in seconds
|
1339
1376
|
"""
|
1377
|
+
_reconnect_if_disconnected(driver)
|
1340
1378
|
alert = wait_for_and_switch_to_alert(driver, timeout)
|
1341
1379
|
alert_text = alert.text
|
1342
1380
|
alert.accept()
|
@@ -1350,6 +1388,7 @@ def wait_for_and_dismiss_alert(driver, timeout=settings.LARGE_TIMEOUT):
|
|
1350
1388
|
driver - the webdriver object (required)
|
1351
1389
|
timeout - the time to wait for the alert in seconds
|
1352
1390
|
"""
|
1391
|
+
_reconnect_if_disconnected(driver)
|
1353
1392
|
alert = wait_for_and_switch_to_alert(driver, timeout)
|
1354
1393
|
alert_text = alert.text
|
1355
1394
|
alert.dismiss()
|
@@ -1365,6 +1404,7 @@ def wait_for_and_switch_to_alert(driver, timeout=settings.LARGE_TIMEOUT):
|
|
1365
1404
|
driver - the webdriver object (required)
|
1366
1405
|
timeout - the time to wait for the alert in seconds
|
1367
1406
|
"""
|
1407
|
+
_reconnect_if_disconnected(driver)
|
1368
1408
|
start_ms = time.time() * 1000.0
|
1369
1409
|
stop_ms = start_ms + (timeout * 1000.0)
|
1370
1410
|
for x in range(int(timeout * 10)):
|
@@ -1392,6 +1432,7 @@ def switch_to_frame(driver, frame, timeout=settings.SMALL_TIMEOUT):
|
|
1392
1432
|
frame - the frame element, name, id, index, or selector
|
1393
1433
|
timeout - the time to wait for the alert in seconds
|
1394
1434
|
"""
|
1435
|
+
_reconnect_if_disconnected(driver)
|
1395
1436
|
start_ms = time.time() * 1000.0
|
1396
1437
|
stop_ms = start_ms + (timeout * 1000.0)
|
1397
1438
|
for x in range(int(timeout * 10)):
|
@@ -1407,12 +1448,10 @@ def switch_to_frame(driver, frame, timeout=settings.SMALL_TIMEOUT):
|
|
1407
1448
|
else:
|
1408
1449
|
by = "css selector"
|
1409
1450
|
if is_element_visible(driver, frame, by=by):
|
1410
|
-
|
1451
|
+
with suppress(Exception):
|
1411
1452
|
element = driver.find_element(by=by, value=frame)
|
1412
1453
|
driver.switch_to.frame(element)
|
1413
1454
|
return True
|
1414
|
-
except Exception:
|
1415
|
-
pass
|
1416
1455
|
now_ms = time.time() * 1000.0
|
1417
1456
|
if now_ms >= stop_ms:
|
1418
1457
|
break
|
@@ -1428,7 +1467,28 @@ def switch_to_frame(driver, frame, timeout=settings.SMALL_TIMEOUT):
|
|
1428
1467
|
timeout_exception(Exception, message)
|
1429
1468
|
|
1430
1469
|
|
1431
|
-
def
|
1470
|
+
def __switch_to_window(driver, window_handle, uc_lock=True):
|
1471
|
+
if (
|
1472
|
+
hasattr(driver, "_is_using_uc")
|
1473
|
+
and driver._is_using_uc
|
1474
|
+
and uc_lock
|
1475
|
+
):
|
1476
|
+
gui_lock = fasteners.InterProcessLock(
|
1477
|
+
constants.MultiBrowser.PYAUTOGUILOCK
|
1478
|
+
)
|
1479
|
+
with gui_lock:
|
1480
|
+
driver.switch_to.window(window_handle)
|
1481
|
+
else:
|
1482
|
+
driver.switch_to.window(window_handle)
|
1483
|
+
return True
|
1484
|
+
|
1485
|
+
|
1486
|
+
def switch_to_window(
|
1487
|
+
driver,
|
1488
|
+
window,
|
1489
|
+
timeout=settings.SMALL_TIMEOUT,
|
1490
|
+
uc_lock=True,
|
1491
|
+
):
|
1432
1492
|
"""
|
1433
1493
|
Wait for a window to appear, and switch to it. This should be usable
|
1434
1494
|
as a drop-in replacement for driver.switch_to.window().
|
@@ -1436,7 +1496,9 @@ def switch_to_window(driver, window, timeout=settings.SMALL_TIMEOUT):
|
|
1436
1496
|
driver - the webdriver object (required)
|
1437
1497
|
window - the window index or window handle
|
1438
1498
|
timeout - the time to wait for the window in seconds
|
1499
|
+
uc_lock - if UC Mode and True, switch_to_window() uses thread-locking
|
1439
1500
|
"""
|
1501
|
+
_reconnect_if_disconnected(driver)
|
1440
1502
|
if window == -1:
|
1441
1503
|
window = len(driver.window_handles) - 1
|
1442
1504
|
start_ms = time.time() * 1000.0
|
@@ -1451,7 +1513,7 @@ def switch_to_window(driver, window, timeout=settings.SMALL_TIMEOUT):
|
|
1451
1513
|
shared_utils.check_if_time_limit_exceeded()
|
1452
1514
|
try:
|
1453
1515
|
window_handle = driver.window_handles[window]
|
1454
|
-
driver
|
1516
|
+
__switch_to_window(driver, window_handle, uc_lock=uc_lock)
|
1455
1517
|
return True
|
1456
1518
|
except IndexError:
|
1457
1519
|
now_ms = time.time() * 1000.0
|
@@ -1472,7 +1534,7 @@ def switch_to_window(driver, window, timeout=settings.SMALL_TIMEOUT):
|
|
1472
1534
|
for x in range(int(timeout * 10)):
|
1473
1535
|
shared_utils.check_if_time_limit_exceeded()
|
1474
1536
|
try:
|
1475
|
-
driver
|
1537
|
+
__switch_to_window(driver, window_handle, uc_lock=uc_lock)
|
1476
1538
|
return True
|
1477
1539
|
except NoSuchWindowException:
|
1478
1540
|
now_ms = time.time() * 1000.0
|
@@ -1490,11 +1552,34 @@ def switch_to_window(driver, window, timeout=settings.SMALL_TIMEOUT):
|
|
1490
1552
|
timeout_exception(Exception, message)
|
1491
1553
|
|
1492
1554
|
|
1555
|
+
############
|
1556
|
+
|
1557
|
+
# Special methods for use with UC Mode
|
1558
|
+
|
1559
|
+
def _reconnect_if_disconnected(driver):
|
1560
|
+
if (
|
1561
|
+
hasattr(driver, "_is_using_uc")
|
1562
|
+
and driver._is_using_uc
|
1563
|
+
and hasattr(driver, "is_connected")
|
1564
|
+
and not driver.is_connected()
|
1565
|
+
):
|
1566
|
+
with suppress(Exception):
|
1567
|
+
driver.connect()
|
1568
|
+
|
1569
|
+
|
1570
|
+
def __is_cdp_swap_needed(driver):
|
1571
|
+
"""If the driver is disconnected, use a CDP method when available."""
|
1572
|
+
return shared_utils.is_cdp_swap_needed(driver)
|
1573
|
+
|
1574
|
+
|
1493
1575
|
############
|
1494
1576
|
|
1495
1577
|
# Support methods for direct use from driver
|
1496
1578
|
|
1497
1579
|
def open_url(driver, url):
|
1580
|
+
if __is_cdp_swap_needed(driver):
|
1581
|
+
driver.cdp.open(url)
|
1582
|
+
return
|
1498
1583
|
url = str(url).strip() # Remove leading and trailing whitespace
|
1499
1584
|
if not page_utils.looks_like_a_page_url(url):
|
1500
1585
|
if page_utils.is_valid_url("https://" + url):
|
@@ -1504,6 +1589,9 @@ def open_url(driver, url):
|
|
1504
1589
|
|
1505
1590
|
def click(driver, selector, by="css selector", timeout=settings.SMALL_TIMEOUT):
|
1506
1591
|
selector, by = page_utils.recalculate_selector(selector, by)
|
1592
|
+
if __is_cdp_swap_needed(driver):
|
1593
|
+
driver.cdp.click(selector)
|
1594
|
+
return
|
1507
1595
|
element = wait_for_element_clickable(
|
1508
1596
|
driver, selector, by=by, timeout=timeout
|
1509
1597
|
)
|
@@ -1511,6 +1599,9 @@ def click(driver, selector, by="css selector", timeout=settings.SMALL_TIMEOUT):
|
|
1511
1599
|
|
1512
1600
|
|
1513
1601
|
def click_link(driver, link_text, timeout=settings.SMALL_TIMEOUT):
|
1602
|
+
if __is_cdp_swap_needed(driver):
|
1603
|
+
driver.cdp.click_link(link_text)
|
1604
|
+
return
|
1514
1605
|
element = wait_for_element_clickable(
|
1515
1606
|
driver, link_text, by="link text", timeout=timeout
|
1516
1607
|
)
|
@@ -1521,20 +1612,24 @@ def click_if_visible(
|
|
1521
1612
|
driver, selector, by="css selector", timeout=0
|
1522
1613
|
):
|
1523
1614
|
selector, by = page_utils.recalculate_selector(selector, by)
|
1615
|
+
if __is_cdp_swap_needed(driver):
|
1616
|
+
driver.cdp.click_if_visible(selector)
|
1617
|
+
return
|
1524
1618
|
if is_element_visible(driver, selector, by=by):
|
1525
1619
|
click(driver, selector, by=by, timeout=1)
|
1526
1620
|
elif timeout > 0:
|
1527
|
-
|
1621
|
+
with suppress(Exception):
|
1528
1622
|
wait_for_element_visible(
|
1529
1623
|
driver, selector, by=by, timeout=timeout
|
1530
1624
|
)
|
1531
|
-
except Exception:
|
1532
|
-
pass
|
1533
1625
|
if is_element_visible(driver, selector, by=by):
|
1534
1626
|
click(driver, selector, by=by, timeout=1)
|
1535
1627
|
|
1536
1628
|
|
1537
1629
|
def click_active_element(driver):
|
1630
|
+
if __is_cdp_swap_needed(driver):
|
1631
|
+
driver.cdp.click_active_element()
|
1632
|
+
return
|
1538
1633
|
driver.execute_script("document.activeElement.click();")
|
1539
1634
|
|
1540
1635
|
|
@@ -1542,6 +1637,9 @@ def js_click(
|
|
1542
1637
|
driver, selector, by="css selector", timeout=settings.SMALL_TIMEOUT
|
1543
1638
|
):
|
1544
1639
|
selector, by = page_utils.recalculate_selector(selector, by)
|
1640
|
+
if __is_cdp_swap_needed(driver):
|
1641
|
+
driver.cdp.click(selector)
|
1642
|
+
return
|
1545
1643
|
element = wait_for_element_present(
|
1546
1644
|
driver, selector, by=by, timeout=timeout
|
1547
1645
|
)
|
@@ -1567,6 +1665,9 @@ def send_keys(
|
|
1567
1665
|
driver, selector, text, by="css selector", timeout=settings.LARGE_TIMEOUT
|
1568
1666
|
):
|
1569
1667
|
selector, by = page_utils.recalculate_selector(selector, by)
|
1668
|
+
if __is_cdp_swap_needed(driver):
|
1669
|
+
driver.cdp.send_keys(selector, text)
|
1670
|
+
return
|
1570
1671
|
element = wait_for_element_present(
|
1571
1672
|
driver, selector, by=by, timeout=timeout
|
1572
1673
|
)
|
@@ -1581,6 +1682,9 @@ def press_keys(
|
|
1581
1682
|
driver, selector, text, by="css selector", timeout=settings.LARGE_TIMEOUT
|
1582
1683
|
):
|
1583
1684
|
selector, by = page_utils.recalculate_selector(selector, by)
|
1685
|
+
if __is_cdp_swap_needed(driver):
|
1686
|
+
driver.cdp.press_keys(selector, text)
|
1687
|
+
return
|
1584
1688
|
element = wait_for_element_present(
|
1585
1689
|
driver, selector, by=by, timeout=timeout
|
1586
1690
|
)
|
@@ -1597,6 +1701,9 @@ def update_text(
|
|
1597
1701
|
driver, selector, text, by="css selector", timeout=settings.LARGE_TIMEOUT
|
1598
1702
|
):
|
1599
1703
|
selector, by = page_utils.recalculate_selector(selector, by)
|
1704
|
+
if __is_cdp_swap_needed(driver):
|
1705
|
+
driver.cdp.type(selector, text)
|
1706
|
+
return
|
1600
1707
|
element = wait_for_element_clickable(
|
1601
1708
|
driver, selector, by=by, timeout=timeout
|
1602
1709
|
)
|
@@ -1610,6 +1717,9 @@ def update_text(
|
|
1610
1717
|
|
1611
1718
|
def submit(driver, selector, by="css selector"):
|
1612
1719
|
selector, by = page_utils.recalculate_selector(selector, by)
|
1720
|
+
if __is_cdp_swap_needed(driver):
|
1721
|
+
driver.cdp.send_keys(selector, "\r\n")
|
1722
|
+
return
|
1613
1723
|
element = wait_for_element_clickable(
|
1614
1724
|
driver, selector, by=by, timeout=settings.SMALL_TIMEOUT
|
1615
1725
|
)
|
@@ -1634,6 +1744,9 @@ def assert_element_visible(
|
|
1634
1744
|
elif page_utils.is_valid_by(selector):
|
1635
1745
|
original_selector = by
|
1636
1746
|
selector, by = page_utils.recalculate_selector(selector, by)
|
1747
|
+
if __is_cdp_swap_needed(driver):
|
1748
|
+
driver.cdp.assert_element(selector)
|
1749
|
+
return True
|
1637
1750
|
wait_for_element_visible(
|
1638
1751
|
driver,
|
1639
1752
|
selector,
|
@@ -1652,6 +1765,9 @@ def assert_element_present(
|
|
1652
1765
|
elif page_utils.is_valid_by(selector):
|
1653
1766
|
original_selector = by
|
1654
1767
|
selector, by = page_utils.recalculate_selector(selector, by)
|
1768
|
+
if __is_cdp_swap_needed(driver):
|
1769
|
+
driver.cdp.assert_element_present(selector)
|
1770
|
+
return True
|
1655
1771
|
wait_for_element_present(
|
1656
1772
|
driver,
|
1657
1773
|
selector,
|
@@ -1686,19 +1802,56 @@ def assert_text(
|
|
1686
1802
|
by="css selector",
|
1687
1803
|
timeout=settings.SMALL_TIMEOUT,
|
1688
1804
|
):
|
1805
|
+
selector, by = page_utils.recalculate_selector(selector, by)
|
1806
|
+
if __is_cdp_swap_needed(driver):
|
1807
|
+
driver.cdp.assert_text(text, selector)
|
1808
|
+
return True
|
1689
1809
|
wait_for_text_visible(
|
1690
1810
|
driver, text.strip(), selector, by=by, timeout=timeout
|
1691
1811
|
)
|
1692
1812
|
|
1693
1813
|
|
1694
1814
|
def assert_exact_text(
|
1695
|
-
driver,
|
1815
|
+
driver,
|
1816
|
+
text,
|
1817
|
+
selector="html",
|
1818
|
+
by="css selector",
|
1819
|
+
timeout=settings.SMALL_TIMEOUT,
|
1696
1820
|
):
|
1821
|
+
selector, by = page_utils.recalculate_selector(selector, by)
|
1822
|
+
if __is_cdp_swap_needed(driver):
|
1823
|
+
driver.cdp.assert_exact_text(text, selector)
|
1824
|
+
return True
|
1697
1825
|
wait_for_exact_text_visible(
|
1698
1826
|
driver, text.strip(), selector, by=by, timeout=timeout
|
1699
1827
|
)
|
1700
1828
|
|
1701
1829
|
|
1830
|
+
def assert_non_empty_text(
|
1831
|
+
driver,
|
1832
|
+
selector,
|
1833
|
+
by="css selector",
|
1834
|
+
timeout=settings.SMALL_TIMEOUT,
|
1835
|
+
):
|
1836
|
+
selector, by = page_utils.recalculate_selector(selector, by)
|
1837
|
+
wait_for_non_empty_text_visible(
|
1838
|
+
driver, selector, by=by, timeout=timeout
|
1839
|
+
)
|
1840
|
+
|
1841
|
+
|
1842
|
+
def assert_text_not_visible(
|
1843
|
+
driver,
|
1844
|
+
text,
|
1845
|
+
selector="html",
|
1846
|
+
by="css selector",
|
1847
|
+
timeout=settings.SMALL_TIMEOUT,
|
1848
|
+
):
|
1849
|
+
selector, by = page_utils.recalculate_selector(selector, by)
|
1850
|
+
wait_for_text_not_visible(
|
1851
|
+
driver, text.strip(), selector, by=by, timeout=timeout
|
1852
|
+
)
|
1853
|
+
|
1854
|
+
|
1702
1855
|
def wait_for_element(
|
1703
1856
|
driver,
|
1704
1857
|
selector,
|
@@ -1711,6 +1864,8 @@ def wait_for_element(
|
|
1711
1864
|
elif page_utils.is_valid_by(selector):
|
1712
1865
|
original_selector = by
|
1713
1866
|
selector, by = page_utils.recalculate_selector(selector, by)
|
1867
|
+
if __is_cdp_swap_needed(driver):
|
1868
|
+
return driver.cdp.select(selector)
|
1714
1869
|
return wait_for_element_visible(
|
1715
1870
|
driver=driver,
|
1716
1871
|
selector=selector,
|
@@ -1732,6 +1887,8 @@ def wait_for_selector(
|
|
1732
1887
|
elif page_utils.is_valid_by(selector):
|
1733
1888
|
original_selector = by
|
1734
1889
|
selector, by = page_utils.recalculate_selector(selector, by)
|
1890
|
+
if __is_cdp_swap_needed(driver):
|
1891
|
+
return driver.cdp.select(selector)
|
1735
1892
|
return wait_for_element_present(
|
1736
1893
|
driver=driver,
|
1737
1894
|
selector=selector,
|
@@ -1748,6 +1905,9 @@ def wait_for_text(
|
|
1748
1905
|
by="css selector",
|
1749
1906
|
timeout=settings.LARGE_TIMEOUT,
|
1750
1907
|
):
|
1908
|
+
selector, by = page_utils.recalculate_selector(selector, by)
|
1909
|
+
if __is_cdp_swap_needed(driver):
|
1910
|
+
return driver.cdp.find_element(selector)
|
1751
1911
|
return wait_for_text_visible(
|
1752
1912
|
driver=driver,
|
1753
1913
|
text=text,
|
@@ -1764,6 +1924,7 @@ def wait_for_exact_text(
|
|
1764
1924
|
by="css selector",
|
1765
1925
|
timeout=settings.LARGE_TIMEOUT,
|
1766
1926
|
):
|
1927
|
+
selector, by = page_utils.recalculate_selector(selector, by)
|
1767
1928
|
return wait_for_exact_text_visible(
|
1768
1929
|
driver=driver,
|
1769
1930
|
text=text,
|
@@ -1779,6 +1940,7 @@ def wait_for_non_empty_text(
|
|
1779
1940
|
by="css selector",
|
1780
1941
|
timeout=settings.LARGE_TIMEOUT,
|
1781
1942
|
):
|
1943
|
+
selector, by = page_utils.recalculate_selector(selector, by)
|
1782
1944
|
return wait_for_non_empty_text_visible(
|
1783
1945
|
driver=driver,
|
1784
1946
|
selector=selector,
|
@@ -1793,6 +1955,8 @@ def get_text(
|
|
1793
1955
|
by="css selector",
|
1794
1956
|
timeout=settings.LARGE_TIMEOUT
|
1795
1957
|
):
|
1958
|
+
if __is_cdp_swap_needed(driver):
|
1959
|
+
return driver.cdp.get_text(selector)
|
1796
1960
|
element = wait_for_element(
|
1797
1961
|
driver=driver,
|
1798
1962
|
selector=selector,
|