seleniumbase 4.32.11__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 +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
|