seleniumbase 4.32.10a3__py3-none-any.whl → 4.32.12__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- sbase/steps.py +7 -0
- seleniumbase/__version__.py +1 -1
- seleniumbase/common/decorators.py +14 -6
- seleniumbase/console_scripts/sb_mkrec.py +3 -1
- seleniumbase/console_scripts/sb_recorder.py +3 -0
- seleniumbase/core/browser_launcher.py +28 -7
- seleniumbase/core/log_helper.py +12 -18
- seleniumbase/core/sb_cdp.py +213 -32
- seleniumbase/core/sb_driver.py +5 -2
- seleniumbase/fixtures/base_case.py +91 -29
- seleniumbase/fixtures/constants.py +1 -0
- seleniumbase/fixtures/js_utils.py +1 -5
- seleniumbase/fixtures/page_actions.py +0 -2
- seleniumbase/fixtures/shared_utils.py +11 -0
- seleniumbase/plugins/sb_manager.py +2 -2
- seleniumbase/undetected/__init__.py +1 -1
- seleniumbase/undetected/cdp_driver/cdp_util.py +5 -1
- {seleniumbase-4.32.10a3.dist-info → seleniumbase-4.32.12.dist-info}/METADATA +3 -3
- {seleniumbase-4.32.10a3.dist-info → seleniumbase-4.32.12.dist-info}/RECORD +23 -23
- {seleniumbase-4.32.10a3.dist-info → seleniumbase-4.32.12.dist-info}/LICENSE +0 -0
- {seleniumbase-4.32.10a3.dist-info → seleniumbase-4.32.12.dist-info}/WHEEL +0 -0
- {seleniumbase-4.32.10a3.dist-info → seleniumbase-4.32.12.dist-info}/entry_points.txt +0 -0
- {seleniumbase-4.32.10a3.dist-info → seleniumbase-4.32.12.dist-info}/top_level.txt +0 -0
sbase/steps.py
CHANGED
@@ -1189,3 +1189,10 @@ def set_attributes(context, selector, attribute, value):
|
|
1189
1189
|
if attribute.endswith("'") or attribute.endswith('"'):
|
1190
1190
|
attribute = attribute[:-1]
|
1191
1191
|
sb.set_attributes(selector, attribute, value)
|
1192
|
+
|
1193
|
+
|
1194
|
+
@step("Activate CDP Mode")
|
1195
|
+
@step("User activates CDP Mode")
|
1196
|
+
def activate_cdp_mode(context):
|
1197
|
+
sb = context.sb
|
1198
|
+
sb.activate_cdp_mode()
|
seleniumbase/__version__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
# seleniumbase package
|
2
|
-
__version__ = "4.32.
|
2
|
+
__version__ = "4.32.12"
|
@@ -1,11 +1,18 @@
|
|
1
|
+
import colorama
|
1
2
|
import logging
|
2
3
|
import math
|
4
|
+
import sys
|
3
5
|
import time
|
4
6
|
import warnings
|
5
7
|
from contextlib import contextmanager
|
6
8
|
from functools import wraps
|
7
9
|
from seleniumbase.common.exceptions import TimeoutException
|
8
10
|
|
11
|
+
c1 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
|
12
|
+
cr = colorama.Style.RESET_ALL
|
13
|
+
if "linux" in sys.platform:
|
14
|
+
c1 = cr = ""
|
15
|
+
|
9
16
|
|
10
17
|
@contextmanager
|
11
18
|
def print_runtime(description=None, limit=None):
|
@@ -44,19 +51,20 @@ def print_runtime(description=None, limit=None):
|
|
44
51
|
end_time = time.time()
|
45
52
|
run_time = end_time - start_time
|
46
53
|
name = description
|
54
|
+
info = c1 + "<info>" + cr
|
47
55
|
# Print times with a statistically significant number of decimal places
|
48
56
|
if run_time < 0.0001:
|
49
|
-
print("
|
57
|
+
print("%s - {%s} ran for %.7f seconds." % (info, name, run_time))
|
50
58
|
elif run_time < 0.001:
|
51
|
-
print("
|
59
|
+
print("%s - {%s} ran for %.6f seconds." % (info, name, run_time))
|
52
60
|
elif run_time < 0.01:
|
53
|
-
print("
|
61
|
+
print("%s - {%s} ran for %.5f seconds." % (info, name, run_time))
|
54
62
|
elif run_time < 0.1:
|
55
|
-
print("
|
63
|
+
print("%s - {%s} ran for %.4f seconds." % (info, name, run_time))
|
56
64
|
elif run_time < 1:
|
57
|
-
print("
|
65
|
+
print("%s - {%s} ran for %.3f seconds." % (info, name, run_time))
|
58
66
|
else:
|
59
|
-
print("
|
67
|
+
print("%s - {%s} ran for %.2f seconds." % (info, name, run_time))
|
60
68
|
if limit and limit > 0 and run_time > limit:
|
61
69
|
message = (
|
62
70
|
"\n {%s} duration of %.2fs exceeded the time limit of %.2fs!"
|
@@ -144,7 +144,9 @@ def main():
|
|
144
144
|
elif option.lower() in ("--gui", "--headed"):
|
145
145
|
if "linux" in sys.platform:
|
146
146
|
force_gui = True
|
147
|
-
elif option.lower() in (
|
147
|
+
elif option.lower() in (
|
148
|
+
"--uc", "--cdp", "--undetected", "--undetectable"
|
149
|
+
):
|
148
150
|
use_uc = True
|
149
151
|
elif option.lower() in ("--rec-behave", "--behave", "--gherkin"):
|
150
152
|
rec_behave = True
|
@@ -9,6 +9,7 @@ Usage:
|
|
9
9
|
|
10
10
|
Options:
|
11
11
|
--uc / --undetected (Use undetectable mode.)
|
12
|
+
--cdp (Same as "--uc" and "--undetectable".)
|
12
13
|
--behave (Also output Behave/Gherkin files.)
|
13
14
|
|
14
15
|
Output:
|
@@ -151,6 +152,7 @@ def do_recording(file_name, url, overwrite_enabled, use_chrome, window):
|
|
151
152
|
command += " --edge"
|
152
153
|
if (
|
153
154
|
"--uc" in command_args
|
155
|
+
or "--cdp" in command_args
|
154
156
|
or "--undetected" in command_args
|
155
157
|
or "--undetectable" in command_args
|
156
158
|
):
|
@@ -193,6 +195,7 @@ def do_playback(file_name, use_chrome, window, demo_mode=False):
|
|
193
195
|
command_args = sys.argv[2:]
|
194
196
|
if (
|
195
197
|
"--uc" in command_args
|
198
|
+
or "--cdp" in command_args
|
196
199
|
or "--undetected" in command_args
|
197
200
|
or "--undetectable" in command_args
|
198
201
|
):
|
@@ -544,6 +544,8 @@ def uc_open_with_cdp_mode(driver, url=None):
|
|
544
544
|
)
|
545
545
|
loop.run_until_complete(driver.cdp_base.wait(0))
|
546
546
|
|
547
|
+
gui_lock = fasteners.InterProcessLock(constants.MultiBrowser.PYAUTOGUILOCK)
|
548
|
+
|
547
549
|
if (
|
548
550
|
"chrome-extension://" in str(driver.cdp_base.main_tab)
|
549
551
|
and len(driver.cdp_base.tabs) >= 2
|
@@ -553,7 +555,8 @@ def uc_open_with_cdp_mode(driver, url=None):
|
|
553
555
|
|
554
556
|
for tab in driver.cdp_base.tabs[-1::-1]:
|
555
557
|
if "chrome-extension://" not in str(tab):
|
556
|
-
|
558
|
+
with gui_lock:
|
559
|
+
loop.run_until_complete(tab.activate())
|
557
560
|
break
|
558
561
|
|
559
562
|
page_tab = None
|
@@ -566,14 +569,20 @@ def uc_open_with_cdp_mode(driver, url=None):
|
|
566
569
|
break
|
567
570
|
if page_tab:
|
568
571
|
loop.run_until_complete(page_tab.aopen())
|
569
|
-
|
572
|
+
with gui_lock:
|
573
|
+
loop.run_until_complete(page_tab.activate())
|
570
574
|
|
571
575
|
loop.run_until_complete(driver.cdp_base.update_targets())
|
572
576
|
page = loop.run_until_complete(driver.cdp_base.get(url))
|
573
|
-
|
577
|
+
with gui_lock:
|
578
|
+
loop.run_until_complete(page.activate())
|
574
579
|
loop.run_until_complete(page.wait())
|
575
580
|
if not safe_url:
|
576
581
|
time.sleep(constants.UC.CDP_MODE_OPEN_WAIT)
|
582
|
+
if IS_WINDOWS:
|
583
|
+
time.sleep(constants.UC.EXTRA_WINDOWS_WAIT)
|
584
|
+
else:
|
585
|
+
time.sleep(0.012)
|
577
586
|
cdp = types.SimpleNamespace()
|
578
587
|
CDPM = sb_cdp.CDPMethods(loop, page, driver)
|
579
588
|
cdp.get = CDPM.get
|
@@ -590,6 +599,9 @@ def uc_open_with_cdp_mode(driver, url=None):
|
|
590
599
|
cdp.select = CDPM.select
|
591
600
|
cdp.select_all = CDPM.select_all
|
592
601
|
cdp.find_elements = CDPM.find_elements
|
602
|
+
cdp.find_visible_elements = CDPM.find_visible_elements
|
603
|
+
cdp.click_nth_element = CDPM.click_nth_element
|
604
|
+
cdp.click_nth_visible_element = CDPM.click_nth_visible_element
|
593
605
|
cdp.click_link = CDPM.click_link
|
594
606
|
cdp.tile_windows = CDPM.tile_windows
|
595
607
|
cdp.get_all_cookies = CDPM.get_all_cookies
|
@@ -609,7 +621,6 @@ def uc_open_with_cdp_mode(driver, url=None):
|
|
609
621
|
cdp.remove_element = CDPM.remove_element
|
610
622
|
cdp.remove_from_dom = CDPM.remove_from_dom
|
611
623
|
cdp.remove_elements = CDPM.remove_elements
|
612
|
-
cdp.scroll_into_view = CDPM.scroll_into_view
|
613
624
|
cdp.send_keys = CDPM.send_keys
|
614
625
|
cdp.press_keys = CDPM.press_keys
|
615
626
|
cdp.type = CDPM.type
|
@@ -672,16 +683,25 @@ def uc_open_with_cdp_mode(driver, url=None):
|
|
672
683
|
cdp.is_checked = CDPM.is_checked
|
673
684
|
cdp.is_element_present = CDPM.is_element_present
|
674
685
|
cdp.is_element_visible = CDPM.is_element_visible
|
686
|
+
cdp.wait_for_element_visible = CDPM.wait_for_element_visible
|
687
|
+
cdp.assert_element = CDPM.assert_element
|
688
|
+
cdp.assert_element_visible = CDPM.assert_element_visible
|
675
689
|
cdp.assert_element_present = CDPM.assert_element_present
|
676
690
|
cdp.assert_element_absent = CDPM.assert_element_absent
|
677
|
-
cdp.assert_element = CDPM.assert_element
|
678
|
-
cdp.assert_element_visible = CDPM.assert_element
|
679
691
|
cdp.assert_element_not_visible = CDPM.assert_element_not_visible
|
692
|
+
cdp.assert_element_attribute = CDPM.assert_element_attribute
|
680
693
|
cdp.assert_title = CDPM.assert_title
|
694
|
+
cdp.assert_title_contains = CDPM.assert_title_contains
|
695
|
+
cdp.assert_url = CDPM.assert_url
|
696
|
+
cdp.assert_url_contains = CDPM.assert_url_contains
|
681
697
|
cdp.assert_text = CDPM.assert_text
|
682
698
|
cdp.assert_exact_text = CDPM.assert_exact_text
|
683
|
-
cdp.
|
699
|
+
cdp.scroll_into_view = CDPM.scroll_into_view
|
700
|
+
cdp.scroll_to_y = CDPM.scroll_to_y
|
701
|
+
cdp.scroll_to_top = CDPM.scroll_to_top
|
702
|
+
cdp.scroll_to_bottom = CDPM.scroll_to_bottom
|
684
703
|
cdp.scroll_up = CDPM.scroll_up
|
704
|
+
cdp.scroll_down = CDPM.scroll_down
|
685
705
|
cdp.save_screenshot = CDPM.save_screenshot
|
686
706
|
cdp.page = page # async world
|
687
707
|
cdp.driver = driver.cdp_base # async world
|
@@ -1255,6 +1275,7 @@ def _uc_gui_click_captcha(
|
|
1255
1275
|
with suppress(Exception):
|
1256
1276
|
_uc_gui_click_x_y(driver, x, y, timeframe=0.32)
|
1257
1277
|
if __is_cdp_swap_needed(driver):
|
1278
|
+
time.sleep(float(constants.UC.RECONNECT_TIME) / 2.0)
|
1258
1279
|
return
|
1259
1280
|
reconnect_time = (float(constants.UC.RECONNECT_TIME) / 2.0) + 0.6
|
1260
1281
|
if IS_LINUX:
|
seleniumbase/core/log_helper.py
CHANGED
@@ -3,6 +3,7 @@ import os
|
|
3
3
|
import shutil
|
4
4
|
import sys
|
5
5
|
import time
|
6
|
+
from contextlib import suppress
|
6
7
|
from seleniumbase import config as sb_config
|
7
8
|
from seleniumbase.config import settings
|
8
9
|
from seleniumbase.fixtures import constants
|
@@ -281,14 +282,13 @@ def log_test_failure_data(test, test_logpath, driver, browser, url=None):
|
|
281
282
|
sb_config._report_time = the_time
|
282
283
|
sb_config._report_traceback = traceback_message
|
283
284
|
sb_config._report_exception = exc_message
|
284
|
-
|
285
|
+
with suppress(Exception):
|
285
286
|
if not os.path.exists(test_logpath):
|
286
287
|
os.makedirs(test_logpath)
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
log_file.close()
|
288
|
+
with suppress(Exception):
|
289
|
+
log_file = codecs.open(basic_file_path, "w+", encoding="utf-8")
|
290
|
+
log_file.writelines("\r\n".join(data_to_save))
|
291
|
+
log_file.close()
|
292
292
|
|
293
293
|
|
294
294
|
def log_skipped_test_data(test, test_logpath, driver, browser, reason):
|
@@ -297,16 +297,12 @@ def log_skipped_test_data(test, test_logpath, driver, browser, reason):
|
|
297
297
|
browser_version = None
|
298
298
|
driver_version = None
|
299
299
|
driver_name = None
|
300
|
-
|
300
|
+
with suppress(Exception):
|
301
301
|
browser_version = get_browser_version(driver)
|
302
|
-
|
303
|
-
pass
|
304
|
-
try:
|
302
|
+
with suppress(Exception):
|
305
303
|
driver_name, driver_version = get_driver_name_and_version(
|
306
304
|
driver, browser
|
307
305
|
)
|
308
|
-
except Exception:
|
309
|
-
pass
|
310
306
|
if browser_version:
|
311
307
|
headless = ""
|
312
308
|
if test.headless and browser in ["chrome", "edge", "firefox"]:
|
@@ -368,13 +364,11 @@ def log_page_source(test_logpath, driver, source=None):
|
|
368
364
|
"unresponsive, or closed prematurely!</h4>"
|
369
365
|
)
|
370
366
|
)
|
371
|
-
|
367
|
+
with suppress(Exception):
|
372
368
|
if not os.path.exists(test_logpath):
|
373
369
|
os.makedirs(test_logpath)
|
374
|
-
except Exception:
|
375
|
-
pass
|
376
370
|
html_file_path = os.path.join(test_logpath, html_file_name)
|
377
|
-
html_file = codecs.open(html_file_path, "w+", "utf-8")
|
371
|
+
html_file = codecs.open(html_file_path, "w+", encoding="utf-8")
|
378
372
|
html_file.write(page_source)
|
379
373
|
html_file.close()
|
380
374
|
|
@@ -543,7 +537,7 @@ def log_folder_setup(log_path, archive_logs=False):
|
|
543
537
|
try:
|
544
538
|
os.makedirs(log_path)
|
545
539
|
except Exception:
|
546
|
-
pass #
|
540
|
+
pass # Only reachable during multi-threaded runs
|
547
541
|
else:
|
548
542
|
saved_folder = "%s/../%s/" % (log_path, constants.Logs.SAVED)
|
549
543
|
archived_folder = os.path.realpath(saved_folder) + "/"
|
@@ -551,7 +545,7 @@ def log_folder_setup(log_path, archive_logs=False):
|
|
551
545
|
try:
|
552
546
|
os.makedirs(archived_folder)
|
553
547
|
except Exception:
|
554
|
-
pass #
|
548
|
+
pass # Only reachable during multi-threaded runs
|
555
549
|
archived_logs = "%slogs_%s" % (archived_folder, int(time.time()))
|
556
550
|
if len(os.listdir(log_path)) > 0:
|
557
551
|
try:
|
seleniumbase/core/sb_cdp.py
CHANGED
@@ -20,8 +20,16 @@ class CDPMethods():
|
|
20
20
|
self.driver = driver
|
21
21
|
|
22
22
|
def __slow_mode_pause_if_set(self):
|
23
|
-
if
|
24
|
-
|
23
|
+
if (
|
24
|
+
(hasattr(sb_config, "demo_mode") and sb_config.demo_mode)
|
25
|
+
or "--demo" in sys.argv
|
26
|
+
):
|
27
|
+
time.sleep(0.48)
|
28
|
+
elif (
|
29
|
+
(hasattr(sb_config, "slow_mode") and sb_config.slow_mode)
|
30
|
+
or "--slow" in sys.argv
|
31
|
+
):
|
32
|
+
time.sleep(0.24)
|
25
33
|
|
26
34
|
def __add_light_pause(self):
|
27
35
|
time.sleep(0.007)
|
@@ -89,6 +97,10 @@ class CDPMethods():
|
|
89
97
|
safe_url = False
|
90
98
|
if not safe_url:
|
91
99
|
time.sleep(constants.UC.CDP_MODE_OPEN_WAIT)
|
100
|
+
if shared_utils.is_windows():
|
101
|
+
time.sleep(constants.UC.EXTRA_WINDOWS_WAIT)
|
102
|
+
else:
|
103
|
+
time.sleep(0.012)
|
92
104
|
self.__slow_mode_pause_if_set()
|
93
105
|
self.loop.run_until_complete(self.page.wait())
|
94
106
|
|
@@ -248,6 +260,45 @@ class CDPMethods():
|
|
248
260
|
def find_elements(self, selector, timeout=settings.SMALL_TIMEOUT):
|
249
261
|
return self.select_all(selector, timeout=timeout)
|
250
262
|
|
263
|
+
def find_visible_elements(self, selector, timeout=settings.SMALL_TIMEOUT):
|
264
|
+
visible_elements = []
|
265
|
+
elements = self.select_all(selector, timeout=timeout)
|
266
|
+
for element in elements:
|
267
|
+
with suppress(Exception):
|
268
|
+
position = element.get_position()
|
269
|
+
if (position.width != 0 or position.height != 0):
|
270
|
+
visible_elements.append(element)
|
271
|
+
return visible_elements
|
272
|
+
|
273
|
+
def click_nth_element(self, selector, number):
|
274
|
+
elements = self.select_all(selector)
|
275
|
+
if len(elements) < number:
|
276
|
+
raise Exception(
|
277
|
+
"Not enough matching {%s} elements to "
|
278
|
+
"click number %s!" % (selector, number)
|
279
|
+
)
|
280
|
+
number = number - 1
|
281
|
+
if number < 0:
|
282
|
+
number = 0
|
283
|
+
element = elements[number]
|
284
|
+
element.click()
|
285
|
+
|
286
|
+
def click_nth_visible_element(self, selector, number):
|
287
|
+
"""Finds all matching page elements and clicks the nth visible one.
|
288
|
+
Example: self.click_nth_visible_element('[type="checkbox"]', 5)
|
289
|
+
(Clicks the 5th visible checkbox on the page.)"""
|
290
|
+
elements = self.find_visible_elements(selector)
|
291
|
+
if len(elements) < number:
|
292
|
+
raise Exception(
|
293
|
+
"Not enough matching {%s} elements to "
|
294
|
+
"click number %s!" % (selector, number)
|
295
|
+
)
|
296
|
+
number = number - 1
|
297
|
+
if number < 0:
|
298
|
+
number = 0
|
299
|
+
element = elements[number]
|
300
|
+
element.click()
|
301
|
+
|
251
302
|
def click_link(self, link_text):
|
252
303
|
self.find_elements_by_text(link_text, "a")[0].click()
|
253
304
|
|
@@ -475,18 +526,36 @@ class CDPMethods():
|
|
475
526
|
self.__slow_mode_pause_if_set()
|
476
527
|
self.loop.run_until_complete(self.page.wait())
|
477
528
|
|
478
|
-
def click_visible_elements(self, selector):
|
529
|
+
def click_visible_elements(self, selector, limit=0):
|
530
|
+
"""Finds all matching page elements and clicks visible ones in order.
|
531
|
+
If a click reloads or opens a new page, the clicking will stop.
|
532
|
+
If no matching elements appear, an Exception will be raised.
|
533
|
+
If "limit" is set and > 0, will only click that many elements.
|
534
|
+
Also clicks elements that become visible from previous clicks.
|
535
|
+
Works best for actions such as clicking all checkboxes on a page.
|
536
|
+
Example: self.click_visible_elements('input[type="checkbox"]')"""
|
479
537
|
elements = self.select_all(selector)
|
538
|
+
click_count = 0
|
480
539
|
for element in elements:
|
540
|
+
if limit and limit > 0 and click_count >= limit:
|
541
|
+
return
|
481
542
|
try:
|
482
|
-
|
483
|
-
|
543
|
+
width = 0
|
544
|
+
height = 0
|
545
|
+
try:
|
546
|
+
position = element.get_position()
|
547
|
+
width = position.width
|
548
|
+
height = position.height
|
549
|
+
except Exception:
|
550
|
+
continue
|
551
|
+
if (width != 0 or height != 0):
|
484
552
|
element.click()
|
485
|
-
|
553
|
+
click_count += 1
|
554
|
+
time.sleep(0.042)
|
486
555
|
self.__slow_mode_pause_if_set()
|
487
556
|
self.loop.run_until_complete(self.page.wait())
|
488
557
|
except Exception:
|
489
|
-
|
558
|
+
break
|
490
559
|
|
491
560
|
def mouse_click(self, selector, timeout=settings.SMALL_TIMEOUT):
|
492
561
|
"""(Attempt simulating a mouse click)"""
|
@@ -578,9 +647,6 @@ class CDPMethods():
|
|
578
647
|
with suppress(Exception):
|
579
648
|
self.loop.run_until_complete(self.page.evaluate(js_code))
|
580
649
|
|
581
|
-
def scroll_into_view(self, selector):
|
582
|
-
self.find_element(selector).scroll_into_view()
|
583
|
-
|
584
650
|
def send_keys(self, selector, text, timeout=settings.SMALL_TIMEOUT):
|
585
651
|
self.__slow_mode_pause_if_set()
|
586
652
|
element = self.select(selector, timeout=timeout)
|
@@ -602,10 +668,10 @@ class CDPMethods():
|
|
602
668
|
text = text[:-1]
|
603
669
|
for key in text:
|
604
670
|
element.send_keys(key)
|
605
|
-
time.sleep(0.
|
671
|
+
time.sleep(0.042)
|
606
672
|
if submit:
|
607
673
|
element.send_keys("\r\n")
|
608
|
-
time.sleep(0.
|
674
|
+
time.sleep(0.042)
|
609
675
|
self.__slow_mode_pause_if_set()
|
610
676
|
self.loop.run_until_complete(self.page.wait())
|
611
677
|
|
@@ -675,7 +741,7 @@ class CDPMethods():
|
|
675
741
|
return
|
676
742
|
elif self.get_window()[1].window_state.value == "minimized":
|
677
743
|
self.loop.run_until_complete(self.page.maximize())
|
678
|
-
time.sleep(0.
|
744
|
+
time.sleep(0.042)
|
679
745
|
return self.loop.run_until_complete(self.page.maximize())
|
680
746
|
|
681
747
|
def minimize(self):
|
@@ -685,7 +751,7 @@ class CDPMethods():
|
|
685
751
|
def medimize(self):
|
686
752
|
if self.get_window()[1].window_state.value == "minimized":
|
687
753
|
self.loop.run_until_complete(self.page.medimize())
|
688
|
-
time.sleep(0.
|
754
|
+
time.sleep(0.042)
|
689
755
|
return self.loop.run_until_complete(self.page.medimize())
|
690
756
|
|
691
757
|
def set_window_rect(self, x, y, width, height):
|
@@ -694,7 +760,7 @@ class CDPMethods():
|
|
694
760
|
self.page.set_window_size(
|
695
761
|
left=x, top=y, width=width, height=height)
|
696
762
|
)
|
697
|
-
time.sleep(0.
|
763
|
+
time.sleep(0.042)
|
698
764
|
return self.loop.run_until_complete(
|
699
765
|
self.page.set_window_size(
|
700
766
|
left=x, top=y, width=width, height=height)
|
@@ -1059,7 +1125,7 @@ class CDPMethods():
|
|
1059
1125
|
)
|
1060
1126
|
with gui_lock:
|
1061
1127
|
pyautogui.press(key)
|
1062
|
-
time.sleep(0.
|
1128
|
+
time.sleep(0.042)
|
1063
1129
|
self.__slow_mode_pause_if_set()
|
1064
1130
|
self.loop.run_until_complete(self.page.wait())
|
1065
1131
|
|
@@ -1073,7 +1139,7 @@ class CDPMethods():
|
|
1073
1139
|
with gui_lock:
|
1074
1140
|
for key in keys:
|
1075
1141
|
pyautogui.press(key)
|
1076
|
-
time.sleep(0.
|
1142
|
+
time.sleep(0.042)
|
1077
1143
|
self.__slow_mode_pause_if_set()
|
1078
1144
|
self.loop.run_until_complete(self.page.wait())
|
1079
1145
|
|
@@ -1237,6 +1303,7 @@ class CDPMethods():
|
|
1237
1303
|
|
1238
1304
|
def gui_drag_and_drop(self, drag_selector, drop_selector, timeframe=0.35):
|
1239
1305
|
self.__slow_mode_pause_if_set()
|
1306
|
+
self.bring_active_window_to_front()
|
1240
1307
|
x1, y1 = self.get_gui_element_center(drag_selector)
|
1241
1308
|
self.__add_light_pause()
|
1242
1309
|
x2, y2 = self.get_gui_element_center(drop_selector)
|
@@ -1326,10 +1393,14 @@ class CDPMethods():
|
|
1326
1393
|
|
1327
1394
|
def gui_hover_element(self, selector, timeframe=0.25):
|
1328
1395
|
self.__slow_mode_pause_if_set()
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1396
|
+
element_rect = self.get_gui_element_rect(selector)
|
1397
|
+
width = element_rect["width"]
|
1398
|
+
height = element_rect["height"]
|
1399
|
+
if width > 0 and height > 0:
|
1400
|
+
x, y = self.get_gui_element_center(selector)
|
1401
|
+
self.bring_active_window_to_front()
|
1402
|
+
self.__gui_hover_x_y(x, y, timeframe=timeframe)
|
1403
|
+
self.__slow_mode_pause_if_set()
|
1333
1404
|
self.loop.run_until_complete(self.page.wait())
|
1334
1405
|
|
1335
1406
|
def gui_hover_and_click(self, hover_selector, click_selector):
|
@@ -1337,6 +1408,7 @@ class CDPMethods():
|
|
1337
1408
|
constants.MultiBrowser.PYAUTOGUILOCK
|
1338
1409
|
)
|
1339
1410
|
with gui_lock:
|
1411
|
+
self.bring_active_window_to_front()
|
1340
1412
|
self.gui_hover_element(hover_selector)
|
1341
1413
|
time.sleep(0.15)
|
1342
1414
|
self.gui_hover_element(click_selector)
|
@@ -1408,25 +1480,53 @@ class CDPMethods():
|
|
1408
1480
|
return True
|
1409
1481
|
return False
|
1410
1482
|
|
1483
|
+
def wait_for_element_visible(
|
1484
|
+
self, selector, timeout=settings.SMALL_TIMEOUT
|
1485
|
+
):
|
1486
|
+
try:
|
1487
|
+
self.select(selector, timeout=timeout)
|
1488
|
+
except Exception:
|
1489
|
+
raise Exception("Element {%s} was not found!" % selector)
|
1490
|
+
for i in range(30):
|
1491
|
+
if self.is_element_visible(selector):
|
1492
|
+
return self.select(selector)
|
1493
|
+
time.sleep(0.1)
|
1494
|
+
raise Exception("Element {%s} was not visible!" % selector)
|
1495
|
+
|
1411
1496
|
def assert_element(self, selector, timeout=settings.SMALL_TIMEOUT):
|
1497
|
+
"""Same as assert_element_visible()"""
|
1412
1498
|
try:
|
1413
1499
|
self.select(selector, timeout=timeout)
|
1414
1500
|
except Exception:
|
1415
|
-
raise Exception("Element {%s} not found!" % selector)
|
1501
|
+
raise Exception("Element {%s} was not found!" % selector)
|
1502
|
+
for i in range(30):
|
1503
|
+
if self.is_element_visible(selector):
|
1504
|
+
return True
|
1505
|
+
time.sleep(0.1)
|
1506
|
+
raise Exception("Element {%s} was not visible!" % selector)
|
1507
|
+
|
1508
|
+
def assert_element_visible(self, selector, timeout=settings.SMALL_TIMEOUT):
|
1509
|
+
"""Same as assert_element()"""
|
1510
|
+
try:
|
1511
|
+
self.select(selector, timeout=timeout)
|
1512
|
+
except Exception:
|
1513
|
+
raise Exception("Element {%s} was not found!" % selector)
|
1416
1514
|
for i in range(30):
|
1417
1515
|
if self.is_element_visible(selector):
|
1418
1516
|
return True
|
1419
1517
|
time.sleep(0.1)
|
1420
|
-
raise Exception("Element {%s} not visible!" % selector)
|
1518
|
+
raise Exception("Element {%s} was not visible!" % selector)
|
1421
1519
|
|
1422
1520
|
def assert_element_present(self, selector, timeout=settings.SMALL_TIMEOUT):
|
1521
|
+
"""Assert element is present in the DOM. (Visibility NOT required)"""
|
1423
1522
|
try:
|
1424
1523
|
self.select(selector, timeout=timeout)
|
1425
1524
|
except Exception:
|
1426
|
-
raise Exception("Element {%s} not found!" % selector)
|
1525
|
+
raise Exception("Element {%s} was not found!" % selector)
|
1427
1526
|
return True
|
1428
1527
|
|
1429
1528
|
def assert_element_absent(self, selector, timeout=settings.SMALL_TIMEOUT):
|
1529
|
+
"""Assert element is not present in the DOM."""
|
1430
1530
|
start_ms = time.time() * 1000.0
|
1431
1531
|
stop_ms = start_ms + (timeout * 1000.0)
|
1432
1532
|
for i in range(int(timeout * 10)):
|
@@ -1447,6 +1547,7 @@ class CDPMethods():
|
|
1447
1547
|
def assert_element_not_visible(
|
1448
1548
|
self, selector, timeout=settings.SMALL_TIMEOUT
|
1449
1549
|
):
|
1550
|
+
"""Assert element is not visible on page. (May still be in DOM)"""
|
1450
1551
|
start_ms = time.time() * 1000.0
|
1451
1552
|
stop_ms = start_ms + (timeout * 1000.0)
|
1452
1553
|
for i in range(int(timeout * 10)):
|
@@ -1466,6 +1567,21 @@ class CDPMethods():
|
|
1466
1567
|
% (selector, timeout, plural)
|
1467
1568
|
)
|
1468
1569
|
|
1570
|
+
def assert_element_attribute(self, selector, attribute, value=None):
|
1571
|
+
attributes = self.get_element_attributes(selector)
|
1572
|
+
if attribute not in attributes:
|
1573
|
+
raise Exception(
|
1574
|
+
"Attribute {%s} was not found in element {%s}!"
|
1575
|
+
% (attribute, selector)
|
1576
|
+
)
|
1577
|
+
if value and attributes[attribute] != value:
|
1578
|
+
raise Exception(
|
1579
|
+
"Expected value {%s} of attribute {%s} "
|
1580
|
+
"was not found in element {%s}! "
|
1581
|
+
"(Actual value was {%s})"
|
1582
|
+
% (value, attribute, selector, attributes[attribute])
|
1583
|
+
)
|
1584
|
+
|
1469
1585
|
def assert_title(self, title):
|
1470
1586
|
expected = title.strip()
|
1471
1587
|
actual = self.get_title().strip()
|
@@ -1477,11 +1593,55 @@ class CDPMethods():
|
|
1477
1593
|
raise Exception(error % (expected, actual))
|
1478
1594
|
except Exception:
|
1479
1595
|
time.sleep(2)
|
1480
|
-
expected = title.strip()
|
1481
1596
|
actual = self.get_title().strip()
|
1482
1597
|
if expected != actual:
|
1483
1598
|
raise Exception(error % (expected, actual))
|
1484
1599
|
|
1600
|
+
def assert_title_contains(self, substring):
|
1601
|
+
expected = substring.strip()
|
1602
|
+
actual = self.get_title().strip()
|
1603
|
+
error = (
|
1604
|
+
"Expected title substring [%s] does not appear "
|
1605
|
+
"in the actual page title [%s]!"
|
1606
|
+
)
|
1607
|
+
try:
|
1608
|
+
if expected not in actual:
|
1609
|
+
raise Exception(error % (expected, actual))
|
1610
|
+
except Exception:
|
1611
|
+
time.sleep(2)
|
1612
|
+
actual = self.get_title().strip()
|
1613
|
+
if expected not in actual:
|
1614
|
+
raise Exception(error % (expected, actual))
|
1615
|
+
|
1616
|
+
def assert_url(self, url):
|
1617
|
+
expected = url.strip()
|
1618
|
+
actual = self.get_current_url().strip()
|
1619
|
+
error = "Expected URL [%s] does not match the actual URL [%s]!"
|
1620
|
+
try:
|
1621
|
+
if expected != actual:
|
1622
|
+
raise Exception(error % (expected, actual))
|
1623
|
+
except Exception:
|
1624
|
+
time.sleep(2)
|
1625
|
+
actual = self.get_current_url().strip()
|
1626
|
+
if expected != actual:
|
1627
|
+
raise Exception(error % (expected, actual))
|
1628
|
+
|
1629
|
+
def assert_url_contains(self, substring):
|
1630
|
+
expected = substring.strip()
|
1631
|
+
actual = self.get_current_url().strip()
|
1632
|
+
error = (
|
1633
|
+
"Expected URL substring [%s] does not appear "
|
1634
|
+
"in the full URL [%s]!"
|
1635
|
+
)
|
1636
|
+
try:
|
1637
|
+
if expected not in actual:
|
1638
|
+
raise Exception(error % (expected, actual))
|
1639
|
+
except Exception:
|
1640
|
+
time.sleep(2)
|
1641
|
+
actual = self.get_current_url().strip()
|
1642
|
+
if expected not in actual:
|
1643
|
+
raise Exception(error % (expected, actual))
|
1644
|
+
|
1485
1645
|
def assert_text(
|
1486
1646
|
self, text, selector="html", timeout=settings.SMALL_TIMEOUT
|
1487
1647
|
):
|
@@ -1521,15 +1681,36 @@ class CDPMethods():
|
|
1521
1681
|
% (text, element.text_all, selector)
|
1522
1682
|
)
|
1523
1683
|
|
1524
|
-
def
|
1525
|
-
self.
|
1526
|
-
|
1527
|
-
|
1684
|
+
def scroll_into_view(self, selector):
|
1685
|
+
self.find_element(selector).scroll_into_view()
|
1686
|
+
self.loop.run_until_complete(self.page.wait())
|
1687
|
+
|
1688
|
+
def scroll_to_y(self, y):
|
1689
|
+
y = int(y)
|
1690
|
+
js_code = "window.scrollTo(0, %s);" % y
|
1691
|
+
with suppress(Exception):
|
1692
|
+
self.loop.run_until_complete(self.page.evaluate(js_code))
|
1693
|
+
self.loop.run_until_complete(self.page.wait())
|
1694
|
+
|
1695
|
+
def scroll_to_top(self):
|
1696
|
+
js_code = "window.scrollTo(0, 0);"
|
1697
|
+
with suppress(Exception):
|
1698
|
+
self.loop.run_until_complete(self.page.evaluate(js_code))
|
1699
|
+
self.loop.run_until_complete(self.page.wait())
|
1700
|
+
|
1701
|
+
def scroll_to_bottom(self):
|
1702
|
+
js_code = "window.scrollTo(0, 10000);"
|
1703
|
+
with suppress(Exception):
|
1704
|
+
self.loop.run_until_complete(self.page.evaluate(js_code))
|
1705
|
+
self.loop.run_until_complete(self.page.wait())
|
1528
1706
|
|
1529
1707
|
def scroll_up(self, amount=25):
|
1530
|
-
self.loop.run_until_complete(
|
1531
|
-
|
1532
|
-
|
1708
|
+
self.loop.run_until_complete(self.page.scroll_up(amount))
|
1709
|
+
self.loop.run_until_complete(self.page.wait())
|
1710
|
+
|
1711
|
+
def scroll_down(self, amount=25):
|
1712
|
+
self.loop.run_until_complete(self.page.scroll_down(amount))
|
1713
|
+
self.loop.run_until_complete(self.page.wait())
|
1533
1714
|
|
1534
1715
|
def save_screenshot(self, name, folder=None, selector=None):
|
1535
1716
|
filename = name
|
seleniumbase/core/sb_driver.py
CHANGED
@@ -249,8 +249,11 @@ class DriverMethods():
|
|
249
249
|
selector = kwargs["selector"]
|
250
250
|
else:
|
251
251
|
selector = args[0]
|
252
|
-
|
253
|
-
|
252
|
+
if ":contains(" not in selector:
|
253
|
+
self.driver.cdp.highlight(selector)
|
254
|
+
return
|
255
|
+
else:
|
256
|
+
self.driver.connect()
|
254
257
|
if "scroll" in kwargs:
|
255
258
|
kwargs.pop("scroll")
|
256
259
|
w_args = kwargs.copy()
|
@@ -1310,9 +1310,13 @@ class BaseCase(unittest.TestCase):
|
|
1310
1310
|
return self.get_page_title()
|
1311
1311
|
|
1312
1312
|
def get_user_agent(self):
|
1313
|
+
if self.__is_cdp_swap_needed():
|
1314
|
+
return self.cdp.get_user_agent()
|
1313
1315
|
return self.execute_script("return navigator.userAgent;")
|
1314
1316
|
|
1315
1317
|
def get_locale_code(self):
|
1318
|
+
if self.__is_cdp_swap_needed():
|
1319
|
+
return self.cdp.get_locale_code()
|
1316
1320
|
return self.execute_script(
|
1317
1321
|
"return navigator.language || navigator.languages[0];"
|
1318
1322
|
)
|
@@ -2166,7 +2170,6 @@ class BaseCase(unittest.TestCase):
|
|
2166
2170
|
if limit and limit > 0 and len(elements) > limit:
|
2167
2171
|
elements = elements[:limit]
|
2168
2172
|
return elements
|
2169
|
-
|
2170
2173
|
self.wait_for_ready_state_complete()
|
2171
2174
|
time.sleep(0.05)
|
2172
2175
|
elements = self.driver.find_elements(by=by, value=selector)
|
@@ -2178,6 +2181,11 @@ class BaseCase(unittest.TestCase):
|
|
2178
2181
|
"""Returns a list of matching WebElements that are visible.
|
2179
2182
|
If "limit" is set and > 0, will only return that many elements."""
|
2180
2183
|
selector, by = self.__recalculate_selector(selector, by)
|
2184
|
+
if self.__is_cdp_swap_needed():
|
2185
|
+
elements = self.cdp.find_visible_elements(selector)
|
2186
|
+
if limit and limit > 0 and len(elements) > limit:
|
2187
|
+
elements = elements[:limit]
|
2188
|
+
return elements
|
2181
2189
|
self.wait_for_ready_state_complete()
|
2182
2190
|
time.sleep(0.05)
|
2183
2191
|
return page_actions.find_visible_elements(
|
@@ -2201,7 +2209,7 @@ class BaseCase(unittest.TestCase):
|
|
2201
2209
|
timeout = self.__get_new_timeout(timeout)
|
2202
2210
|
selector, by = self.__recalculate_selector(selector, by)
|
2203
2211
|
if self.__is_cdp_swap_needed():
|
2204
|
-
self.cdp.click_visible_elements(selector)
|
2212
|
+
self.cdp.click_visible_elements(selector, limit)
|
2205
2213
|
return
|
2206
2214
|
self.wait_for_ready_state_complete()
|
2207
2215
|
if self.__needs_minimum_wait():
|
@@ -2283,13 +2291,16 @@ class BaseCase(unittest.TestCase):
|
|
2283
2291
|
):
|
2284
2292
|
"""Finds all matching page elements and clicks the nth visible one.
|
2285
2293
|
Example: self.click_nth_visible_element('[type="checkbox"]', 5)
|
2286
|
-
|
2294
|
+
(Clicks the 5th visible checkbox on the page.)"""
|
2287
2295
|
self.__check_scope()
|
2288
2296
|
if not timeout:
|
2289
2297
|
timeout = settings.SMALL_TIMEOUT
|
2290
2298
|
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
|
2291
2299
|
timeout = self.__get_new_timeout(timeout)
|
2292
2300
|
selector, by = self.__recalculate_selector(selector, by)
|
2301
|
+
if self.__is_cdp_swap_needed():
|
2302
|
+
self.cdp.click_nth_visible_element(selector, number)
|
2303
|
+
return
|
2293
2304
|
self.wait_for_ready_state_complete()
|
2294
2305
|
self.wait_for_element_present(selector, by=by, timeout=timeout)
|
2295
2306
|
elements = self.find_visible_elements(selector, by=by)
|
@@ -2897,6 +2908,9 @@ class BaseCase(unittest.TestCase):
|
|
2897
2908
|
drop_selector, drop_by = self.__recalculate_selector(
|
2898
2909
|
drop_selector, drop_by
|
2899
2910
|
)
|
2911
|
+
if self.__is_cdp_swap_needed():
|
2912
|
+
self.cdp.gui_drag_and_drop(drag_selector, drop_selector)
|
2913
|
+
return
|
2900
2914
|
drag_element = self.wait_for_element_clickable(
|
2901
2915
|
drag_selector, by=drag_by, timeout=timeout
|
2902
2916
|
)
|
@@ -4537,6 +4551,11 @@ class BaseCase(unittest.TestCase):
|
|
4537
4551
|
def get_cookies(self):
|
4538
4552
|
return self.driver.get_cookies()
|
4539
4553
|
|
4554
|
+
def get_cookie_string(self):
|
4555
|
+
if self.__is_cdp_swap_needed():
|
4556
|
+
return self.cdp.get_cookie_string()
|
4557
|
+
return self.execute_script("return document.cookie;")
|
4558
|
+
|
4540
4559
|
def add_cookie(self, cookie_dict, expiry=False):
|
4541
4560
|
"""Usage examples:
|
4542
4561
|
self.add_cookie({'name': 'foo', 'value': 'bar'})
|
@@ -5419,7 +5438,10 @@ class BaseCase(unittest.TestCase):
|
|
5419
5438
|
new_file = True
|
5420
5439
|
sb_config._recorded_actions[filename] = []
|
5421
5440
|
data.append("from seleniumbase import BaseCase")
|
5422
|
-
|
5441
|
+
if "--uc" in sys.argv:
|
5442
|
+
data.append('BaseCase.main(__name__, __file__, "--uc")')
|
5443
|
+
else:
|
5444
|
+
data.append("BaseCase.main(__name__, __file__)")
|
5423
5445
|
data.append("")
|
5424
5446
|
data.append("")
|
5425
5447
|
data.append("class %s(BaseCase):" % classname)
|
@@ -5429,7 +5451,13 @@ class BaseCase(unittest.TestCase):
|
|
5429
5451
|
data.append("class %s(BaseCase):" % classname)
|
5430
5452
|
data.append(" def %s(self):" % methodname)
|
5431
5453
|
if len(sb_actions) > 0:
|
5454
|
+
if "--uc" in sys.argv:
|
5455
|
+
data.append(" self.activate_cdp_mode()")
|
5432
5456
|
for action in sb_actions:
|
5457
|
+
if "--uc" in sys.argv:
|
5458
|
+
action = action.replace(
|
5459
|
+
"self.type(", "self.press_keys("
|
5460
|
+
)
|
5433
5461
|
data.append(" " + action)
|
5434
5462
|
else:
|
5435
5463
|
data.append(" pass")
|
@@ -5607,6 +5635,9 @@ class BaseCase(unittest.TestCase):
|
|
5607
5635
|
data.append(" Scenario: %s" % scenario_test)
|
5608
5636
|
if len(behave_actions) > 0:
|
5609
5637
|
count = 0
|
5638
|
+
if "--uc" in sys.argv:
|
5639
|
+
data.append(" Given Activate CDP Mode")
|
5640
|
+
count += 1
|
5610
5641
|
for action in behave_actions:
|
5611
5642
|
if count == 0:
|
5612
5643
|
data.append(" Given " + action)
|
@@ -6144,6 +6175,9 @@ class BaseCase(unittest.TestCase):
|
|
6144
6175
|
original_selector = selector
|
6145
6176
|
original_by = by
|
6146
6177
|
selector, by = self.__recalculate_selector(selector, by)
|
6178
|
+
if self.__is_cdp_swap_needed() and ":contains(" not in selector:
|
6179
|
+
self.cdp.scroll_into_view(selector)
|
6180
|
+
return
|
6147
6181
|
element = self.wait_for_element_visible(
|
6148
6182
|
original_selector, by=original_by, timeout=timeout
|
6149
6183
|
)
|
@@ -6190,24 +6224,36 @@ class BaseCase(unittest.TestCase):
|
|
6190
6224
|
def scroll_to_top(self):
|
6191
6225
|
"""Scroll to the top of the page."""
|
6192
6226
|
self.__check_scope()
|
6227
|
+
if self.__is_cdp_swap_needed():
|
6228
|
+
self.cdp.scroll_to_top()
|
6229
|
+
return
|
6193
6230
|
scroll_script = "window.scrollTo(0, 0);"
|
6194
|
-
|
6231
|
+
with suppress(Exception):
|
6195
6232
|
self.execute_script(scroll_script)
|
6196
6233
|
time.sleep(0.012)
|
6197
|
-
return True
|
6198
|
-
except Exception:
|
6199
|
-
return False
|
6200
6234
|
|
6201
6235
|
def scroll_to_bottom(self):
|
6202
6236
|
"""Scroll to the bottom of the page."""
|
6203
6237
|
self.__check_scope()
|
6238
|
+
if self.__is_cdp_swap_needed():
|
6239
|
+
self.cdp.scroll_to_bottom()
|
6240
|
+
return
|
6204
6241
|
scroll_script = "window.scrollTo(0, 10000);"
|
6205
|
-
|
6242
|
+
with suppress(Exception):
|
6243
|
+
self.execute_script(scroll_script)
|
6244
|
+
time.sleep(0.012)
|
6245
|
+
|
6246
|
+
def scroll_to_y(self, y):
|
6247
|
+
"""Scroll to y position on the page."""
|
6248
|
+
self.__check_scope()
|
6249
|
+
y = int(y)
|
6250
|
+
if self.__is_cdp_swap_needed():
|
6251
|
+
self.cdp.scroll_to_y(y)
|
6252
|
+
return
|
6253
|
+
scroll_script = "window.scrollTo(0, %s);" % y
|
6254
|
+
with suppress(Exception):
|
6206
6255
|
self.execute_script(scroll_script)
|
6207
6256
|
time.sleep(0.012)
|
6208
|
-
return True
|
6209
|
-
except Exception:
|
6210
|
-
return False
|
6211
6257
|
|
6212
6258
|
def click_xpath(self, xpath):
|
6213
6259
|
"""Technically, self.click() automatically detects xpath selectors,
|
@@ -7620,7 +7666,10 @@ class BaseCase(unittest.TestCase):
|
|
7620
7666
|
if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
|
7621
7667
|
timeout = self.__get_new_timeout(timeout)
|
7622
7668
|
selector, by = self.__recalculate_selector(selector, by)
|
7623
|
-
if self.
|
7669
|
+
if self.__is_cdp_swap_needed():
|
7670
|
+
self.cdp.assert_element_attribute(selector, attribute, value)
|
7671
|
+
return
|
7672
|
+
elif self.__is_shadow_selector(selector):
|
7624
7673
|
return self.__wait_for_shadow_attribute_present(
|
7625
7674
|
selector, attribute, value=value, timeout=timeout
|
7626
7675
|
)
|
@@ -7645,6 +7694,9 @@ class BaseCase(unittest.TestCase):
|
|
7645
7694
|
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
|
7646
7695
|
timeout = self.__get_new_timeout(timeout)
|
7647
7696
|
selector, by = self.__recalculate_selector(selector, by)
|
7697
|
+
if self.__is_cdp_swap_needed():
|
7698
|
+
self.cdp.assert_element_attribute(selector, attribute, value)
|
7699
|
+
return
|
7648
7700
|
self.wait_for_attribute(
|
7649
7701
|
selector, attribute, value=value, by=by, timeout=timeout
|
7650
7702
|
)
|
@@ -7743,6 +7795,9 @@ class BaseCase(unittest.TestCase):
|
|
7743
7795
|
but then the title switches over to the actual page title.
|
7744
7796
|
In Recorder Mode, this assertion is skipped because the Recorder
|
7745
7797
|
changes the page title to the selector of the hovered element."""
|
7798
|
+
if self.__is_cdp_swap_needed():
|
7799
|
+
self.cdp.assert_title_contains(substring)
|
7800
|
+
return
|
7746
7801
|
self.wait_for_ready_state_complete()
|
7747
7802
|
expected = substring.strip()
|
7748
7803
|
actual = self.get_page_title().strip()
|
@@ -7786,6 +7841,9 @@ class BaseCase(unittest.TestCase):
|
|
7786
7841
|
|
7787
7842
|
def assert_url(self, url):
|
7788
7843
|
"""Asserts that the web page URL matches the expected URL."""
|
7844
|
+
if self.__is_cdp_swap_needed():
|
7845
|
+
self.cdp.assert_url(url)
|
7846
|
+
return
|
7789
7847
|
self.wait_for_ready_state_complete()
|
7790
7848
|
expected = url.strip()
|
7791
7849
|
actual = self.get_current_url().strip()
|
@@ -7821,6 +7879,9 @@ class BaseCase(unittest.TestCase):
|
|
7821
7879
|
|
7822
7880
|
def assert_url_contains(self, substring):
|
7823
7881
|
"""Asserts that the URL substring appears in the full URL."""
|
7882
|
+
if self.__is_cdp_swap_needed():
|
7883
|
+
self.cdp.assert_url_contains(substring)
|
7884
|
+
return
|
7824
7885
|
self.wait_for_ready_state_complete()
|
7825
7886
|
expected = substring.strip()
|
7826
7887
|
actual = self.get_current_url().strip()
|
@@ -8019,6 +8080,8 @@ class BaseCase(unittest.TestCase):
|
|
8019
8080
|
|
8020
8081
|
def is_online(self):
|
8021
8082
|
"""Return True if connected to the Internet."""
|
8083
|
+
if self.__is_cdp_swap_needed():
|
8084
|
+
return self.cdp.evaluate("navigator.onLine;")
|
8022
8085
|
return self.execute_script("return navigator.onLine;")
|
8023
8086
|
|
8024
8087
|
def is_connected(self):
|
@@ -8927,7 +8990,9 @@ class BaseCase(unittest.TestCase):
|
|
8927
8990
|
timeout = self.__get_new_timeout(timeout)
|
8928
8991
|
original_selector = selector
|
8929
8992
|
selector, by = self.__recalculate_selector(selector, by)
|
8930
|
-
if self.
|
8993
|
+
if self.__is_cdp_swap_needed():
|
8994
|
+
return self.cdp.select(selector)
|
8995
|
+
elif self.__is_shadow_selector(selector):
|
8931
8996
|
# If a shadow selector, use visible instead of clickable
|
8932
8997
|
return self.__wait_for_shadow_element_visible(selector, timeout)
|
8933
8998
|
return page_actions.wait_for_element_clickable(
|
@@ -9328,7 +9393,7 @@ class BaseCase(unittest.TestCase):
|
|
9328
9393
|
selector, by = self.__recalculate_selector(selector, by)
|
9329
9394
|
if self.__is_cdp_swap_needed():
|
9330
9395
|
return self.cdp.select(selector)
|
9331
|
-
|
9396
|
+
elif self.__is_shadow_selector(selector):
|
9332
9397
|
return self.__wait_for_shadow_element_present(selector, timeout)
|
9333
9398
|
return page_actions.wait_for_element_present(
|
9334
9399
|
self.driver,
|
@@ -9391,6 +9456,8 @@ class BaseCase(unittest.TestCase):
|
|
9391
9456
|
if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
|
9392
9457
|
timeout = self.__get_new_timeout(timeout)
|
9393
9458
|
css_selector = self.convert_to_css_selector(selector, by=by)
|
9459
|
+
if self.__is_cdp_swap_needed():
|
9460
|
+
return self.cdp.select(css_selector)
|
9394
9461
|
return js_utils.wait_for_css_query_selector(
|
9395
9462
|
self.driver, css_selector, timeout
|
9396
9463
|
)
|
@@ -9612,7 +9679,7 @@ class BaseCase(unittest.TestCase):
|
|
9612
9679
|
selector, by = self.__recalculate_selector(selector, by)
|
9613
9680
|
if self.__is_cdp_swap_needed():
|
9614
9681
|
return self.cdp.find_element(selector)
|
9615
|
-
|
9682
|
+
elif self.__is_shadow_selector(selector):
|
9616
9683
|
return self.__wait_for_shadow_text_visible(text, selector, timeout)
|
9617
9684
|
return page_actions.wait_for_text_visible(
|
9618
9685
|
self.driver, text, selector, by, timeout
|
@@ -10135,6 +10202,9 @@ class BaseCase(unittest.TestCase):
|
|
10135
10202
|
timeout = settings.SMALL_TIMEOUT
|
10136
10203
|
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
|
10137
10204
|
timeout = self.__get_new_timeout(timeout)
|
10205
|
+
if self.__is_cdp_swap_needed():
|
10206
|
+
self.cdp.assert_element_not_visible(selector)
|
10207
|
+
return True
|
10138
10208
|
self.wait_for_element_not_visible(selector, by=by, timeout=timeout)
|
10139
10209
|
if self.recorder_mode and self.__current_url_is_recordable():
|
10140
10210
|
if self.get_session_storage_item("pause_recorder") == "no":
|
@@ -14471,7 +14541,7 @@ class BaseCase(unittest.TestCase):
|
|
14471
14541
|
message = (
|
14472
14542
|
"Expected value {%s} for attribute {%s} of element "
|
14473
14543
|
"{%s} was not present after %s second%s! "
|
14474
|
-
"(
|
14544
|
+
"(Actual value was {%s})"
|
14475
14545
|
% (
|
14476
14546
|
value,
|
14477
14547
|
attribute,
|
@@ -15420,7 +15490,8 @@ class BaseCase(unittest.TestCase):
|
|
15420
15490
|
elif hasattr(self, "_using_sb_fixture") and self._using_sb_fixture:
|
15421
15491
|
test_id = sb_config._latest_display_id
|
15422
15492
|
test_id = test_id.replace(".py::", ".").replace("::", ".")
|
15423
|
-
test_id = test_id.replace("/", ".").replace("
|
15493
|
+
test_id = test_id.replace("/", ".").replace("\\", ".")
|
15494
|
+
test_id = test_id.replace(" ", "_")
|
15424
15495
|
# Linux filename length limit for `codecs.open(filename)` = 255
|
15425
15496
|
# 255 - len("latest_logs/") - len("/basic_test_info.txt") = 223
|
15426
15497
|
if len(test_id) <= 223:
|
@@ -16117,11 +16188,7 @@ class BaseCase(unittest.TestCase):
|
|
16117
16188
|
# This test already called tearDown()
|
16118
16189
|
return
|
16119
16190
|
if hasattr(self, "recorder_mode") and self.recorder_mode:
|
16120
|
-
|
16121
|
-
try:
|
16122
|
-
self.driver.window_handles
|
16123
|
-
except Exception:
|
16124
|
-
self.driver.connect()
|
16191
|
+
page_actions._reconnect_if_disconnected(self.driver)
|
16125
16192
|
try:
|
16126
16193
|
self.__process_recorded_actions()
|
16127
16194
|
except Exception as e:
|
@@ -16162,12 +16229,7 @@ class BaseCase(unittest.TestCase):
|
|
16162
16229
|
)
|
16163
16230
|
raise Exception(message)
|
16164
16231
|
# *** Start tearDown() officially ***
|
16165
|
-
|
16166
|
-
try:
|
16167
|
-
self.driver.window_handles
|
16168
|
-
except Exception:
|
16169
|
-
with suppress(Exception):
|
16170
|
-
self.driver.connect()
|
16232
|
+
page_actions._reconnect_if_disconnected(self.driver)
|
16171
16233
|
self.__slow_mode_pause_if_active()
|
16172
16234
|
has_exception = self.__has_exception()
|
16173
16235
|
sb_config._has_exception = has_exception
|
@@ -10,6 +10,7 @@ from seleniumbase import config as sb_config
|
|
10
10
|
from seleniumbase.config import settings
|
11
11
|
from seleniumbase.fixtures import constants
|
12
12
|
from seleniumbase.fixtures import css_to_xpath
|
13
|
+
from seleniumbase.fixtures import shared_utils
|
13
14
|
from seleniumbase.fixtures import xpath_to_css
|
14
15
|
|
15
16
|
|
@@ -24,9 +25,6 @@ def wait_for_ready_state_complete(driver, timeout=settings.LARGE_TIMEOUT):
|
|
24
25
|
(Previously, tests would fail immediately if exceeding the timeout.)"""
|
25
26
|
if hasattr(settings, "SKIP_JS_WAITS") and settings.SKIP_JS_WAITS:
|
26
27
|
return
|
27
|
-
if sb_config.time_limit and not sb_config.recorder_mode:
|
28
|
-
from seleniumbase.fixtures import shared_utils
|
29
|
-
|
30
28
|
start_ms = time.time() * 1000.0
|
31
29
|
stop_ms = start_ms + (timeout * 1000.0)
|
32
30
|
for x in range(int(timeout * 10)):
|
@@ -243,8 +241,6 @@ def escape_quotes_if_needed(string):
|
|
243
241
|
def is_in_frame(driver):
|
244
242
|
# Returns True if the driver has switched to a frame.
|
245
243
|
# Returns False if the driver was on default content.
|
246
|
-
from seleniumbase.fixtures import shared_utils
|
247
|
-
|
248
244
|
if shared_utils.is_cdp_swap_needed(driver):
|
249
245
|
return False
|
250
246
|
in_basic_frame = driver.execute_script(
|
@@ -1555,8 +1555,6 @@ def _reconnect_if_disconnected(driver):
|
|
1555
1555
|
if (
|
1556
1556
|
hasattr(driver, "_is_using_uc")
|
1557
1557
|
and driver._is_using_uc
|
1558
|
-
and hasattr(driver, "_is_connected")
|
1559
|
-
and not driver._is_connected
|
1560
1558
|
and hasattr(driver, "is_connected")
|
1561
1559
|
and not driver.is_connected()
|
1562
1560
|
):
|
@@ -84,6 +84,17 @@ def fix_url_as_needed(url):
|
|
84
84
|
return url
|
85
85
|
|
86
86
|
|
87
|
+
def reconnect_if_disconnected(driver):
|
88
|
+
if (
|
89
|
+
hasattr(driver, "_is_using_uc")
|
90
|
+
and driver._is_using_uc
|
91
|
+
and hasattr(driver, "is_connected")
|
92
|
+
and not driver.is_connected()
|
93
|
+
):
|
94
|
+
with suppress(Exception):
|
95
|
+
driver.connect()
|
96
|
+
|
97
|
+
|
87
98
|
def is_cdp_swap_needed(driver):
|
88
99
|
"""
|
89
100
|
When someone is using CDP Mode with a disconnected webdriver,
|
@@ -1202,7 +1202,7 @@ def SB(
|
|
1202
1202
|
from seleniumbase.core import download_helper
|
1203
1203
|
from seleniumbase.core import proxy_helper
|
1204
1204
|
|
1205
|
-
log_helper.log_folder_setup(constants.Logs.LATEST +
|
1205
|
+
log_helper.log_folder_setup(constants.Logs.LATEST + os.sep)
|
1206
1206
|
log_helper.clear_empty_logs()
|
1207
1207
|
download_helper.reset_downloads_folder()
|
1208
1208
|
if not sb_config.multi_proxy:
|
@@ -1228,7 +1228,7 @@ def SB(
|
|
1228
1228
|
the_traceback = traceback.format_exc().strip()
|
1229
1229
|
try:
|
1230
1230
|
p2 = the_traceback.split(', in ')[1].split('", line ')[0]
|
1231
|
-
filename = p2.split(
|
1231
|
+
filename = p2.split(os.sep)[-1]
|
1232
1232
|
sb.cm_filename = filename
|
1233
1233
|
except Exception:
|
1234
1234
|
sb.cm_filename = None
|
@@ -455,7 +455,7 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
|
|
455
455
|
if self.service.is_connectable():
|
456
456
|
self.stop_client()
|
457
457
|
self.service.stop()
|
458
|
-
|
458
|
+
self._is_connected = False
|
459
459
|
|
460
460
|
def connect(self):
|
461
461
|
"""Starts the chromedriver service that runs in the background
|
@@ -211,7 +211,11 @@ async def start(
|
|
211
211
|
expert=expert,
|
212
212
|
**kwargs,
|
213
213
|
)
|
214
|
-
|
214
|
+
try:
|
215
|
+
return await Browser.create(config)
|
216
|
+
except Exception:
|
217
|
+
time.sleep(0.15)
|
218
|
+
return await Browser.create(config)
|
215
219
|
|
216
220
|
|
217
221
|
async def start_async(*args, **kwargs) -> Browser:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: seleniumbase
|
3
|
-
Version: 4.32.
|
3
|
+
Version: 4.32.12
|
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
|
@@ -59,7 +59,7 @@ Classifier: Topic :: Utilities
|
|
59
59
|
Requires-Python: >=3.8
|
60
60
|
Description-Content-Type: text/markdown
|
61
61
|
License-File: LICENSE
|
62
|
-
Requires-Dist: pip>=24.
|
62
|
+
Requires-Dist: pip>=24.3.1
|
63
63
|
Requires-Dist: packaging>=24.2
|
64
64
|
Requires-Dist: wheel>=0.45.0
|
65
65
|
Requires-Dist: attrs>=24.2.0
|
@@ -127,7 +127,7 @@ Requires-Dist: allure-behave>=2.13.5; extra == "allure"
|
|
127
127
|
Provides-Extra: coverage
|
128
128
|
Requires-Dist: coverage>=7.6.1; python_version < "3.9" and extra == "coverage"
|
129
129
|
Requires-Dist: pytest-cov>=5.0.0; python_version < "3.9" and extra == "coverage"
|
130
|
-
Requires-Dist: coverage>=7.6.
|
130
|
+
Requires-Dist: coverage>=7.6.7; python_version >= "3.9" and extra == "coverage"
|
131
131
|
Requires-Dist: pytest-cov>=6.0.0; python_version >= "3.9" and extra == "coverage"
|
132
132
|
Provides-Extra: flake8
|
133
133
|
Requires-Dist: mccabe==0.7.0; extra == "flake8"
|
@@ -1,15 +1,15 @@
|
|
1
1
|
sbase/__init__.py,sha256=02izDj786GVBT0bpSq2Q2O8uwSxtyT09pnobZz91ML8,605
|
2
2
|
sbase/__main__.py,sha256=G0bVB1-DM4PGwQ1KyOupaWCs4ePbChZNNWuX2htim5U,647
|
3
|
-
sbase/steps.py,sha256=
|
3
|
+
sbase/steps.py,sha256=_WvAjydKqZfTdnZW9LPKkRty-g-lfdUPmLqnZj6ulcs,43013
|
4
4
|
seleniumbase/__init__.py,sha256=OtJh8nGKL4xtZpw8KPqmn7Q6R-86t4cWUDyVF5MbMTo,2398
|
5
5
|
seleniumbase/__main__.py,sha256=dn1p6dgCchmcH1zzTzzQvFwwdQQqnTGH6ULV9m4hv24,654
|
6
|
-
seleniumbase/__version__.py,sha256=
|
6
|
+
seleniumbase/__version__.py,sha256=8RXHuvmxJAt6kjpfvDeMQuCQ2ZFJUK225_rPJF4FZ3I,47
|
7
7
|
seleniumbase/behave/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
8
|
seleniumbase/behave/behave_helper.py,sha256=elkl8P9eLulRAioLstE9baYNM9N_PHBmAOcajX-pH_Y,24198
|
9
9
|
seleniumbase/behave/behave_sb.py,sha256=-hza7Nx2U41mSObYiPMi48v3JlPh3sJO3yzP0kqZ1Gk,59174
|
10
10
|
seleniumbase/behave/steps.py,sha256=8-N-NB2tnDsxaP4LSg-uSBgbwZYMS6ZEL1oggO1PCoU,390
|
11
11
|
seleniumbase/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
|
-
seleniumbase/common/decorators.py,sha256=
|
12
|
+
seleniumbase/common/decorators.py,sha256=DYdjtF8Y7YJj0JS33WtmsIn4yddPoniNwcPyrgt522o,7857
|
13
13
|
seleniumbase/common/encryption.py,sha256=IfAuE0hdrd3y-_qAQUWdSOKRGQ4QN24uTOBiQ9Eeq2s,5593
|
14
14
|
seleniumbase/common/exceptions.py,sha256=SbdHOTbg7ycrioWleAVw9kG9vBtDfbYoj3e7ikkYYz0,3257
|
15
15
|
seleniumbase/common/obfuscate.py,sha256=VrwPbVigPH_Jk6ADCk5_miMoq1VK4M9SKnYScDkk-DQ,1204
|
@@ -30,13 +30,13 @@ seleniumbase/console_scripts/sb_mkchart.py,sha256=ep9g-9CSIwaOJKVxhB3xjRQpfsuApy
|
|
30
30
|
seleniumbase/console_scripts/sb_mkdir.py,sha256=csqyWGEUdT2slLnQU3p9gnu5qE26TSVi_ZE3wttH_SQ,29778
|
31
31
|
seleniumbase/console_scripts/sb_mkfile.py,sha256=OWYd4yFccmjrd-gNn1t1una-HDRU2_N2-r4Tg3nHsj0,17744
|
32
32
|
seleniumbase/console_scripts/sb_mkpres.py,sha256=EWFRVacjYTX49y-fEiYTZacM9_01IxuuaO4nMjHrIGo,11015
|
33
|
-
seleniumbase/console_scripts/sb_mkrec.py,sha256=
|
33
|
+
seleniumbase/console_scripts/sb_mkrec.py,sha256=PrizjTmyrROYPO0yDm-zQS3QSfsZNeAmcJKKUvfgLhc,11966
|
34
34
|
seleniumbase/console_scripts/sb_objectify.py,sha256=nGxtVGL_nHj0bLHvk86znV3EABsE2_tjF74lgto1_Mk,122020
|
35
35
|
seleniumbase/console_scripts/sb_print.py,sha256=tNy-bMDgwHJO3bZxMpmo9weSE8uhbH0CUpP4VZqWxvI,30558
|
36
|
-
seleniumbase/console_scripts/sb_recorder.py,sha256=
|
36
|
+
seleniumbase/console_scripts/sb_recorder.py,sha256=fnHb5-kh11Hit-E9Ha-e4QXzqLcZvtij6mb5qNd4B1Q,11032
|
37
37
|
seleniumbase/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
38
38
|
seleniumbase/core/application_manager.py,sha256=e_0sjtI8cjY5BNyZj1QBR0j6_oCScxGmSXYEpcYwuZE,576
|
39
|
-
seleniumbase/core/browser_launcher.py,sha256=
|
39
|
+
seleniumbase/core/browser_launcher.py,sha256=Jr4MM0CCXqrwlZalpr-N89D5XKtWPOPS3g9rnHm5j-s,220223
|
40
40
|
seleniumbase/core/capabilities_parser.py,sha256=meIS2uHapTCq2ldfNAToC7r0cKmZDRXuYNKExM1GHDY,6038
|
41
41
|
seleniumbase/core/colored_traceback.py,sha256=DrRWfg7XEnKcgY59Xj7Jdk09H-XqHYBSUpB-DiZt6iY,2020
|
42
42
|
seleniumbase/core/create_db_tables.sql,sha256=VWPtrdiW_HQ6yETHjqTu-VIrTwvd8I8o1NfBeaVSHpU,972
|
@@ -44,14 +44,14 @@ seleniumbase/core/detect_b_ver.py,sha256=RxeGRMbBUTMrXh5KsS1P1SH7eEKYbzL1vQw1gTd
|
|
44
44
|
seleniumbase/core/download_helper.py,sha256=qSR54kQISucF4RQaLCOuuerSu6DR41juGi_30HVvWYY,2943
|
45
45
|
seleniumbase/core/encoded_images.py,sha256=rDKJ4cNJSuKiRcFViYU7bjyTS9_moI57gUPRXVg3u2k,14209
|
46
46
|
seleniumbase/core/jqc_helper.py,sha256=2DDQr9Q2jSSZqFzX588jLlUM9oJvyrRWq2aORSIPUdI,10322
|
47
|
-
seleniumbase/core/log_helper.py,sha256=
|
47
|
+
seleniumbase/core/log_helper.py,sha256=T_nPPSRSjhqt6TTzVE6pN1owVvIeRBNF5pWK6sl4dMY,22609
|
48
48
|
seleniumbase/core/mysql.py,sha256=8Fzj3p5dhtDWfMpFqFYxpSwa9s1UltiHsWJ56_aPOqk,3993
|
49
49
|
seleniumbase/core/proxy_helper.py,sha256=cXhu8ErK9Vjdm82RMaQj7hEq_yUWizSp6LyiD50Ieu4,8020
|
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=
|
54
|
-
seleniumbase/core/sb_driver.py,sha256=
|
53
|
+
seleniumbase/core/sb_cdp.py,sha256=hYnEXSTB_nM-rJSsLkPUbE2Di1ij_2Kb-Fbmso3zC4g,66948
|
54
|
+
seleniumbase/core/sb_driver.py,sha256=xMgtvBitEMr73RkqgQLT-3IvkP6sh7cJv-caCUPoO-o,12179
|
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=
|
69
|
-
seleniumbase/fixtures/constants.py,sha256=
|
68
|
+
seleniumbase/fixtures/base_case.py,sha256=Pz5y5R3EeOYiUgK1Zutc8QYlQI7Lb3_uzGAGBhuQi5g,715596
|
69
|
+
seleniumbase/fixtures/constants.py,sha256=e1LppavlrAcI4XBJMq7u5j8SffaQ7SPQps1y0YvZYfY,13649
|
70
70
|
seleniumbase/fixtures/css_to_xpath.py,sha256=9ouDB1xl4MJ2os6JOgTIAyHKOQfuxtxvXC3O5hSnEKA,1954
|
71
71
|
seleniumbase/fixtures/errors.py,sha256=KyxuEVx_e3MPhVrJfNIa_3ltMpbCFxfy_jxK8RFNTns,555
|
72
|
-
seleniumbase/fixtures/js_utils.py,sha256=
|
73
|
-
seleniumbase/fixtures/page_actions.py,sha256=
|
72
|
+
seleniumbase/fixtures/js_utils.py,sha256=2l4UY_zUBsMviRoJpLA0z3XxhGeLMWj0Mv07FUR_jzg,50939
|
73
|
+
seleniumbase/fixtures/page_actions.py,sha256=dbp63c-7asYZyd8aOu57Y3dxQQozp_VJsP5h74s1kBA,66552
|
74
74
|
seleniumbase/fixtures/page_utils.py,sha256=5m7iXpikLs80TJoRO6_gEfXE1AKeQgcH1aFbR8o1C9A,12034
|
75
|
-
seleniumbase/fixtures/shared_utils.py,sha256=
|
75
|
+
seleniumbase/fixtures/shared_utils.py,sha256=WbPb15IvIWzRtMInKG8DUzJ26UZU-PixdOwTCjXQirU,7545
|
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
|
@@ -90,7 +90,7 @@ seleniumbase/plugins/driver_manager.py,sha256=s20s0pJYaNrG0WNwyIC04oUMRVFjtm6V_n
|
|
90
90
|
seleniumbase/plugins/page_source.py,sha256=loTnXxOj4kxEukuTZEiGyvKBhY3KDVDMnNlHHheTBDE,1889
|
91
91
|
seleniumbase/plugins/pytest_plugin.py,sha256=Up96HY6q3hcPo4LQoEcKqt1hm2OmY5GZz_nMXTqDSXQ,97185
|
92
92
|
seleniumbase/plugins/s3_logging_plugin.py,sha256=WDfertQgGOW_SRJpFMaekYD6vBVW9VO62POtXXy2HCM,2319
|
93
|
-
seleniumbase/plugins/sb_manager.py,sha256=
|
93
|
+
seleniumbase/plugins/sb_manager.py,sha256=lVCPDL0Y1ig2TAOZUlJmMZs2ij-SqhYhaEd_SYZyRfQ,54256
|
94
94
|
seleniumbase/plugins/screen_shots.py,sha256=1hrXw-hzuZ1BR6Yh7AyWX2ABnvnP73-RCbwdz958gj4,1127
|
95
95
|
seleniumbase/plugins/selenium_plugin.py,sha256=GhGW2ATy2kM7UH7NrZ2je402nN2LMlVHpM-yxlU3I9E,59069
|
96
96
|
seleniumbase/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -106,7 +106,7 @@ seleniumbase/translate/portuguese.py,sha256=x3P4qxp56UiI41GoaL7JbUvFRYsgXU1EKjTg
|
|
106
106
|
seleniumbase/translate/russian.py,sha256=TyN9n0b4GRWDEYnHRGw1rfNAscdDmP3F3Y3aySM3C7s,27978
|
107
107
|
seleniumbase/translate/spanish.py,sha256=hh3xgW1Pq122SHYVvJAxFaXhFrjniOVncVbJbfWqOUM,25528
|
108
108
|
seleniumbase/translate/translator.py,sha256=wPhZH6e5NhmebYL1kP2eGxUcVy1gfTb6XCH8ATEPpxE,49238
|
109
|
-
seleniumbase/undetected/__init__.py,sha256=
|
109
|
+
seleniumbase/undetected/__init__.py,sha256=PSaAVgWU-yU1zwts2-UIJMWS6Mwo1YwAw0pMlSx6jVM,22998
|
110
110
|
seleniumbase/undetected/cdp.py,sha256=RLpwZnhUvmK9tgXcZIBBQedwk2q7Jj_EXZkmzI8WUqk,4023
|
111
111
|
seleniumbase/undetected/dprocess.py,sha256=83EV8ZHJWHG1TSUv9JNClBhdgiBXlkCc6mJ--HsoP3k,1681
|
112
112
|
seleniumbase/undetected/options.py,sha256=BoNuwhrG7oOvuLvTwkvsWCF36pMkS1tHCG-XpP4_EkI,3001
|
@@ -116,7 +116,7 @@ seleniumbase/undetected/webelement.py,sha256=_s6evgUkdWJpwOnzX4qR9i796PoVbz3txlz
|
|
116
116
|
seleniumbase/undetected/cdp_driver/__init__.py,sha256=c0TjMwPfVFyoqYOJ7PQ-Jln_L_dpN3ebHyaD-juQoM0,64
|
117
117
|
seleniumbase/undetected/cdp_driver/_contradict.py,sha256=6thDYeoEGiC7Q3tXLgoD_AhxecCFnATzBSjNympyRHA,3184
|
118
118
|
seleniumbase/undetected/cdp_driver/browser.py,sha256=mGmpWuR206yYJoBPTNslru8CbEpQuvvIHdjBylSkoKg,30020
|
119
|
-
seleniumbase/undetected/cdp_driver/cdp_util.py,sha256=
|
119
|
+
seleniumbase/undetected/cdp_driver/cdp_util.py,sha256=YhtD2Tm6PLIy9VKbgk8lHdGniS3mObyX4yAC1aG0TgQ,16733
|
120
120
|
seleniumbase/undetected/cdp_driver/config.py,sha256=Rjvde7V-XJ0ihZdTmOmHEVWSuDWm3SprQ3njg8SN3Go,12087
|
121
121
|
seleniumbase/undetected/cdp_driver/connection.py,sha256=sOTUGjbUqKA2hPvDcRCdqw1VQjVGJs7mbgVvzS7ldtE,23360
|
122
122
|
seleniumbase/undetected/cdp_driver/element.py,sha256=wEHtuF9oiny7cb4QMMjdtD5Yf1z3WOs2_NHEWcscusM,40289
|
@@ -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.
|
139
|
-
seleniumbase-4.32.
|
140
|
-
seleniumbase-4.32.
|
141
|
-
seleniumbase-4.32.
|
142
|
-
seleniumbase-4.32.
|
143
|
-
seleniumbase-4.32.
|
138
|
+
seleniumbase-4.32.12.dist-info/LICENSE,sha256=odSYtWibXBnQ1gBg6CnDZ82n8kLF_if5-2nbqnEyD8k,1085
|
139
|
+
seleniumbase-4.32.12.dist-info/METADATA,sha256=P11mc7CmOJAkPcUrEMuLMWKMI5JJObPPtOTUQONNBns,86464
|
140
|
+
seleniumbase-4.32.12.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
|
141
|
+
seleniumbase-4.32.12.dist-info/entry_points.txt,sha256=CNrh2EKNaHYEhO6pP1RJyVLB99LkDDYX7TnUK8xfjqk,623
|
142
|
+
seleniumbase-4.32.12.dist-info/top_level.txt,sha256=4N97aBOQ8ETCnDnokBsWb07lJfTaq3C1ZzYRxvLMxqU,19
|
143
|
+
seleniumbase-4.32.12.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|