seleniumbase 4.32.11__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 +7 -2
- seleniumbase/core/sb_cdp.py +110 -14
- seleniumbase/fixtures/base_case.py +51 -6
- seleniumbase/undetected/__init__.py +1 -1
- seleniumbase/undetected/cdp_driver/cdp_util.py +5 -1
- {seleniumbase-4.32.11.dist-info → seleniumbase-4.32.12.dist-info}/METADATA +3 -3
- {seleniumbase-4.32.11.dist-info → seleniumbase-4.32.12.dist-info}/RECORD +16 -16
- {seleniumbase-4.32.11.dist-info → seleniumbase-4.32.12.dist-info}/LICENSE +0 -0
- {seleniumbase-4.32.11.dist-info → seleniumbase-4.32.12.dist-info}/WHEEL +0 -0
- {seleniumbase-4.32.11.dist-info → seleniumbase-4.32.12.dist-info}/entry_points.txt +0 -0
- {seleniumbase-4.32.11.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
|
):
|
@@ -683,12 +683,17 @@ def uc_open_with_cdp_mode(driver, url=None):
|
|
683
683
|
cdp.is_checked = CDPM.is_checked
|
684
684
|
cdp.is_element_present = CDPM.is_element_present
|
685
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
|
686
689
|
cdp.assert_element_present = CDPM.assert_element_present
|
687
690
|
cdp.assert_element_absent = CDPM.assert_element_absent
|
688
|
-
cdp.assert_element = CDPM.assert_element
|
689
|
-
cdp.assert_element_visible = CDPM.assert_element
|
690
691
|
cdp.assert_element_not_visible = CDPM.assert_element_not_visible
|
692
|
+
cdp.assert_element_attribute = CDPM.assert_element_attribute
|
691
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
|
692
697
|
cdp.assert_text = CDPM.assert_text
|
693
698
|
cdp.assert_exact_text = CDPM.assert_exact_text
|
694
699
|
cdp.scroll_into_view = CDPM.scroll_into_view
|
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)
|
@@ -543,7 +551,7 @@ class CDPMethods():
|
|
543
551
|
if (width != 0 or height != 0):
|
544
552
|
element.click()
|
545
553
|
click_count += 1
|
546
|
-
time.sleep(0.
|
554
|
+
time.sleep(0.042)
|
547
555
|
self.__slow_mode_pause_if_set()
|
548
556
|
self.loop.run_until_complete(self.page.wait())
|
549
557
|
except Exception:
|
@@ -660,10 +668,10 @@ class CDPMethods():
|
|
660
668
|
text = text[:-1]
|
661
669
|
for key in text:
|
662
670
|
element.send_keys(key)
|
663
|
-
time.sleep(0.
|
671
|
+
time.sleep(0.042)
|
664
672
|
if submit:
|
665
673
|
element.send_keys("\r\n")
|
666
|
-
time.sleep(0.
|
674
|
+
time.sleep(0.042)
|
667
675
|
self.__slow_mode_pause_if_set()
|
668
676
|
self.loop.run_until_complete(self.page.wait())
|
669
677
|
|
@@ -733,7 +741,7 @@ class CDPMethods():
|
|
733
741
|
return
|
734
742
|
elif self.get_window()[1].window_state.value == "minimized":
|
735
743
|
self.loop.run_until_complete(self.page.maximize())
|
736
|
-
time.sleep(0.
|
744
|
+
time.sleep(0.042)
|
737
745
|
return self.loop.run_until_complete(self.page.maximize())
|
738
746
|
|
739
747
|
def minimize(self):
|
@@ -743,7 +751,7 @@ class CDPMethods():
|
|
743
751
|
def medimize(self):
|
744
752
|
if self.get_window()[1].window_state.value == "minimized":
|
745
753
|
self.loop.run_until_complete(self.page.medimize())
|
746
|
-
time.sleep(0.
|
754
|
+
time.sleep(0.042)
|
747
755
|
return self.loop.run_until_complete(self.page.medimize())
|
748
756
|
|
749
757
|
def set_window_rect(self, x, y, width, height):
|
@@ -752,7 +760,7 @@ class CDPMethods():
|
|
752
760
|
self.page.set_window_size(
|
753
761
|
left=x, top=y, width=width, height=height)
|
754
762
|
)
|
755
|
-
time.sleep(0.
|
763
|
+
time.sleep(0.042)
|
756
764
|
return self.loop.run_until_complete(
|
757
765
|
self.page.set_window_size(
|
758
766
|
left=x, top=y, width=width, height=height)
|
@@ -1117,7 +1125,7 @@ class CDPMethods():
|
|
1117
1125
|
)
|
1118
1126
|
with gui_lock:
|
1119
1127
|
pyautogui.press(key)
|
1120
|
-
time.sleep(0.
|
1128
|
+
time.sleep(0.042)
|
1121
1129
|
self.__slow_mode_pause_if_set()
|
1122
1130
|
self.loop.run_until_complete(self.page.wait())
|
1123
1131
|
|
@@ -1131,7 +1139,7 @@ class CDPMethods():
|
|
1131
1139
|
with gui_lock:
|
1132
1140
|
for key in keys:
|
1133
1141
|
pyautogui.press(key)
|
1134
|
-
time.sleep(0.
|
1142
|
+
time.sleep(0.042)
|
1135
1143
|
self.__slow_mode_pause_if_set()
|
1136
1144
|
self.loop.run_until_complete(self.page.wait())
|
1137
1145
|
|
@@ -1472,25 +1480,53 @@ class CDPMethods():
|
|
1472
1480
|
return True
|
1473
1481
|
return False
|
1474
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
|
+
|
1475
1496
|
def assert_element(self, selector, timeout=settings.SMALL_TIMEOUT):
|
1497
|
+
"""Same as assert_element_visible()"""
|
1476
1498
|
try:
|
1477
1499
|
self.select(selector, timeout=timeout)
|
1478
1500
|
except Exception:
|
1479
|
-
raise Exception("Element {%s} not found!" % selector)
|
1501
|
+
raise Exception("Element {%s} was not found!" % selector)
|
1480
1502
|
for i in range(30):
|
1481
1503
|
if self.is_element_visible(selector):
|
1482
1504
|
return True
|
1483
1505
|
time.sleep(0.1)
|
1484
|
-
raise Exception("Element {%s} not visible!" % selector)
|
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)
|
1514
|
+
for i in range(30):
|
1515
|
+
if self.is_element_visible(selector):
|
1516
|
+
return True
|
1517
|
+
time.sleep(0.1)
|
1518
|
+
raise Exception("Element {%s} was not visible!" % selector)
|
1485
1519
|
|
1486
1520
|
def assert_element_present(self, selector, timeout=settings.SMALL_TIMEOUT):
|
1521
|
+
"""Assert element is present in the DOM. (Visibility NOT required)"""
|
1487
1522
|
try:
|
1488
1523
|
self.select(selector, timeout=timeout)
|
1489
1524
|
except Exception:
|
1490
|
-
raise Exception("Element {%s} not found!" % selector)
|
1525
|
+
raise Exception("Element {%s} was not found!" % selector)
|
1491
1526
|
return True
|
1492
1527
|
|
1493
1528
|
def assert_element_absent(self, selector, timeout=settings.SMALL_TIMEOUT):
|
1529
|
+
"""Assert element is not present in the DOM."""
|
1494
1530
|
start_ms = time.time() * 1000.0
|
1495
1531
|
stop_ms = start_ms + (timeout * 1000.0)
|
1496
1532
|
for i in range(int(timeout * 10)):
|
@@ -1511,6 +1547,7 @@ class CDPMethods():
|
|
1511
1547
|
def assert_element_not_visible(
|
1512
1548
|
self, selector, timeout=settings.SMALL_TIMEOUT
|
1513
1549
|
):
|
1550
|
+
"""Assert element is not visible on page. (May still be in DOM)"""
|
1514
1551
|
start_ms = time.time() * 1000.0
|
1515
1552
|
stop_ms = start_ms + (timeout * 1000.0)
|
1516
1553
|
for i in range(int(timeout * 10)):
|
@@ -1530,6 +1567,21 @@ class CDPMethods():
|
|
1530
1567
|
% (selector, timeout, plural)
|
1531
1568
|
)
|
1532
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
|
+
|
1533
1585
|
def assert_title(self, title):
|
1534
1586
|
expected = title.strip()
|
1535
1587
|
actual = self.get_title().strip()
|
@@ -1541,11 +1593,55 @@ class CDPMethods():
|
|
1541
1593
|
raise Exception(error % (expected, actual))
|
1542
1594
|
except Exception:
|
1543
1595
|
time.sleep(2)
|
1544
|
-
expected = title.strip()
|
1545
1596
|
actual = self.get_title().strip()
|
1546
1597
|
if expected != actual:
|
1547
1598
|
raise Exception(error % (expected, actual))
|
1548
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
|
+
|
1549
1645
|
def assert_text(
|
1550
1646
|
self, text, selector="html", timeout=settings.SMALL_TIMEOUT
|
1551
1647
|
):
|
@@ -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
|
)
|
@@ -4547,6 +4551,11 @@ class BaseCase(unittest.TestCase):
|
|
4547
4551
|
def get_cookies(self):
|
4548
4552
|
return self.driver.get_cookies()
|
4549
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
|
+
|
4550
4559
|
def add_cookie(self, cookie_dict, expiry=False):
|
4551
4560
|
"""Usage examples:
|
4552
4561
|
self.add_cookie({'name': 'foo', 'value': 'bar'})
|
@@ -5429,7 +5438,10 @@ class BaseCase(unittest.TestCase):
|
|
5429
5438
|
new_file = True
|
5430
5439
|
sb_config._recorded_actions[filename] = []
|
5431
5440
|
data.append("from seleniumbase import BaseCase")
|
5432
|
-
|
5441
|
+
if "--uc" in sys.argv:
|
5442
|
+
data.append('BaseCase.main(__name__, __file__, "--uc")')
|
5443
|
+
else:
|
5444
|
+
data.append("BaseCase.main(__name__, __file__)")
|
5433
5445
|
data.append("")
|
5434
5446
|
data.append("")
|
5435
5447
|
data.append("class %s(BaseCase):" % classname)
|
@@ -5439,7 +5451,13 @@ class BaseCase(unittest.TestCase):
|
|
5439
5451
|
data.append("class %s(BaseCase):" % classname)
|
5440
5452
|
data.append(" def %s(self):" % methodname)
|
5441
5453
|
if len(sb_actions) > 0:
|
5454
|
+
if "--uc" in sys.argv:
|
5455
|
+
data.append(" self.activate_cdp_mode()")
|
5442
5456
|
for action in sb_actions:
|
5457
|
+
if "--uc" in sys.argv:
|
5458
|
+
action = action.replace(
|
5459
|
+
"self.type(", "self.press_keys("
|
5460
|
+
)
|
5443
5461
|
data.append(" " + action)
|
5444
5462
|
else:
|
5445
5463
|
data.append(" pass")
|
@@ -5617,6 +5635,9 @@ class BaseCase(unittest.TestCase):
|
|
5617
5635
|
data.append(" Scenario: %s" % scenario_test)
|
5618
5636
|
if len(behave_actions) > 0:
|
5619
5637
|
count = 0
|
5638
|
+
if "--uc" in sys.argv:
|
5639
|
+
data.append(" Given Activate CDP Mode")
|
5640
|
+
count += 1
|
5620
5641
|
for action in behave_actions:
|
5621
5642
|
if count == 0:
|
5622
5643
|
data.append(" Given " + action)
|
@@ -7645,7 +7666,10 @@ class BaseCase(unittest.TestCase):
|
|
7645
7666
|
if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
|
7646
7667
|
timeout = self.__get_new_timeout(timeout)
|
7647
7668
|
selector, by = self.__recalculate_selector(selector, by)
|
7648
|
-
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):
|
7649
7673
|
return self.__wait_for_shadow_attribute_present(
|
7650
7674
|
selector, attribute, value=value, timeout=timeout
|
7651
7675
|
)
|
@@ -7670,6 +7694,9 @@ class BaseCase(unittest.TestCase):
|
|
7670
7694
|
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
|
7671
7695
|
timeout = self.__get_new_timeout(timeout)
|
7672
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
|
7673
7700
|
self.wait_for_attribute(
|
7674
7701
|
selector, attribute, value=value, by=by, timeout=timeout
|
7675
7702
|
)
|
@@ -7768,6 +7795,9 @@ class BaseCase(unittest.TestCase):
|
|
7768
7795
|
but then the title switches over to the actual page title.
|
7769
7796
|
In Recorder Mode, this assertion is skipped because the Recorder
|
7770
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
|
7771
7801
|
self.wait_for_ready_state_complete()
|
7772
7802
|
expected = substring.strip()
|
7773
7803
|
actual = self.get_page_title().strip()
|
@@ -7811,6 +7841,9 @@ class BaseCase(unittest.TestCase):
|
|
7811
7841
|
|
7812
7842
|
def assert_url(self, url):
|
7813
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
|
7814
7847
|
self.wait_for_ready_state_complete()
|
7815
7848
|
expected = url.strip()
|
7816
7849
|
actual = self.get_current_url().strip()
|
@@ -7846,6 +7879,9 @@ class BaseCase(unittest.TestCase):
|
|
7846
7879
|
|
7847
7880
|
def assert_url_contains(self, substring):
|
7848
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
|
7849
7885
|
self.wait_for_ready_state_complete()
|
7850
7886
|
expected = substring.strip()
|
7851
7887
|
actual = self.get_current_url().strip()
|
@@ -8044,6 +8080,8 @@ class BaseCase(unittest.TestCase):
|
|
8044
8080
|
|
8045
8081
|
def is_online(self):
|
8046
8082
|
"""Return True if connected to the Internet."""
|
8083
|
+
if self.__is_cdp_swap_needed():
|
8084
|
+
return self.cdp.evaluate("navigator.onLine;")
|
8047
8085
|
return self.execute_script("return navigator.onLine;")
|
8048
8086
|
|
8049
8087
|
def is_connected(self):
|
@@ -8952,7 +8990,9 @@ class BaseCase(unittest.TestCase):
|
|
8952
8990
|
timeout = self.__get_new_timeout(timeout)
|
8953
8991
|
original_selector = selector
|
8954
8992
|
selector, by = self.__recalculate_selector(selector, by)
|
8955
|
-
if self.
|
8993
|
+
if self.__is_cdp_swap_needed():
|
8994
|
+
return self.cdp.select(selector)
|
8995
|
+
elif self.__is_shadow_selector(selector):
|
8956
8996
|
# If a shadow selector, use visible instead of clickable
|
8957
8997
|
return self.__wait_for_shadow_element_visible(selector, timeout)
|
8958
8998
|
return page_actions.wait_for_element_clickable(
|
@@ -9353,7 +9393,7 @@ class BaseCase(unittest.TestCase):
|
|
9353
9393
|
selector, by = self.__recalculate_selector(selector, by)
|
9354
9394
|
if self.__is_cdp_swap_needed():
|
9355
9395
|
return self.cdp.select(selector)
|
9356
|
-
|
9396
|
+
elif self.__is_shadow_selector(selector):
|
9357
9397
|
return self.__wait_for_shadow_element_present(selector, timeout)
|
9358
9398
|
return page_actions.wait_for_element_present(
|
9359
9399
|
self.driver,
|
@@ -9416,6 +9456,8 @@ class BaseCase(unittest.TestCase):
|
|
9416
9456
|
if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT:
|
9417
9457
|
timeout = self.__get_new_timeout(timeout)
|
9418
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)
|
9419
9461
|
return js_utils.wait_for_css_query_selector(
|
9420
9462
|
self.driver, css_selector, timeout
|
9421
9463
|
)
|
@@ -9637,7 +9679,7 @@ class BaseCase(unittest.TestCase):
|
|
9637
9679
|
selector, by = self.__recalculate_selector(selector, by)
|
9638
9680
|
if self.__is_cdp_swap_needed():
|
9639
9681
|
return self.cdp.find_element(selector)
|
9640
|
-
|
9682
|
+
elif self.__is_shadow_selector(selector):
|
9641
9683
|
return self.__wait_for_shadow_text_visible(text, selector, timeout)
|
9642
9684
|
return page_actions.wait_for_text_visible(
|
9643
9685
|
self.driver, text, selector, by, timeout
|
@@ -10160,6 +10202,9 @@ class BaseCase(unittest.TestCase):
|
|
10160
10202
|
timeout = settings.SMALL_TIMEOUT
|
10161
10203
|
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
|
10162
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
|
10163
10208
|
self.wait_for_element_not_visible(selector, by=by, timeout=timeout)
|
10164
10209
|
if self.recorder_mode and self.__current_url_is_recordable():
|
10165
10210
|
if self.get_session_storage_item("pause_recorder") == "no":
|
@@ -14496,7 +14541,7 @@ class BaseCase(unittest.TestCase):
|
|
14496
14541
|
message = (
|
14497
14542
|
"Expected value {%s} for attribute {%s} of element "
|
14498
14543
|
"{%s} was not present after %s second%s! "
|
14499
|
-
"(
|
14544
|
+
"(Actual value was {%s})"
|
14500
14545
|
% (
|
14501
14546
|
value,
|
14502
14547
|
attribute,
|
@@ -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
|
@@ -50,7 +50,7 @@ seleniumbase/core/proxy_helper.py,sha256=cXhu8ErK9Vjdm82RMaQj7hEq_yUWizSp6LyiD50
|
|
50
50
|
seleniumbase/core/recorder_helper.py,sha256=fNGjbapXmEsht54x1o6Igk198QdnPxDDnjUOzQxNhNQ,25055
|
51
51
|
seleniumbase/core/report_helper.py,sha256=AIl6Qava2yW1uSzbLpJBlPlYDz0KE-rVhogh8hsGWBo,12201
|
52
52
|
seleniumbase/core/s3_manager.py,sha256=bkeI8I4y19ebWuQG1oEZV5qJbotC6eN8vin31OCNWJk,3521
|
53
|
-
seleniumbase/core/sb_cdp.py,sha256=
|
53
|
+
seleniumbase/core/sb_cdp.py,sha256=hYnEXSTB_nM-rJSsLkPUbE2Di1ij_2Kb-Fbmso3zC4g,66948
|
54
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
|
@@ -65,7 +65,7 @@ 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=
|
68
|
+
seleniumbase/fixtures/base_case.py,sha256=Pz5y5R3EeOYiUgK1Zutc8QYlQI7Lb3_uzGAGBhuQi5g,715596
|
69
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
|
@@ -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
|