seleniumbase 4.32.10a3__py3-none-any.whl → 4.32.12__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/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
|