Skip to content

Commit 667602c

Browse files
authored
Merge pull request #3304 from seleniumbase/cdp-mode-patch-15
CDP Mode - Patch 15
2 parents c81ab62 + 99c0f8a commit 667602c

File tree

11 files changed

+194
-127
lines changed

11 files changed

+194
-127
lines changed

examples/cdp_mode/ReadMe.md

+4
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,10 @@ sb.cdp.assert_text(text, selector="html")
419419
sb.cdp.assert_exact_text(text, selector="html")
420420
sb.cdp.assert_true()
421421
sb.cdp.assert_false()
422+
sb.cdp.assert_equal(first, second)
423+
sb.cdp.assert_not_equal(first, second)
424+
sb.cdp.assert_in(first, second)
425+
sb.cdp.assert_not_in(first, second)
422426
sb.cdp.scroll_into_view(selector)
423427
sb.cdp.scroll_to_y(y)
424428
sb.cdp.scroll_to_top()

examples/cdp_mode/raw_fingerprint.py

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from seleniumbase import SB
2+
3+
with SB(uc=True, test=True, incognito=True) as sb:
4+
url = "https://demo.fingerprint.com/playground"
5+
sb.activate_cdp_mode(url)
6+
sb.sleep(1)
7+
sb.cdp.highlight('a[href*="browser-bot-detection"]')
8+
bot_row_selector = 'table:contains("Bot") tr:nth-of-type(3)'
9+
print(sb.cdp.get_text(bot_row_selector))
10+
sb.cdp.assert_text("Bot Not detected", bot_row_selector)
11+
sb.cdp.highlight(bot_row_selector)
12+
sb.sleep(2)
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""To handle alerts in CDP Mode, reconnect and use WebDriver."""
2+
from seleniumbase import SB
3+
4+
with SB(uc=True, test=True) as sb:
5+
url = "https://the-internet.herokuapp.com/javascript_alerts"
6+
sb.activate_cdp_mode(url)
7+
sb.reconnect()
8+
sb.cdp.gui_click_element('button[onclick="jsAlert()"]')
9+
sb.sleep(1)
10+
sb.accept_alert()
11+
sb.sleep(1)
12+
sb.cdp.gui_click_element('button[onclick="jsConfirm()"]')
13+
sb.sleep(1)
14+
sb.dismiss_alert()
15+
sb.sleep(1)
16+
sb.cdp.gui_click_element('button[onclick="jsPrompt()"]')
17+
sb.sleep(1)
18+
sb.uc_gui_write("Here is my prompt answer\n")
19+
sb.sleep(1)

examples/migration/protractor/ReadMe.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
```bash
1010
$ pytest --rs -v --guest
1111
=========================== test session starts ============================
12-
platform darwin -- Python 3.11.2, pytest-7.4.0, pluggy-1.2.0 -- /Users/michael/.virtualenvs/sb_venv/bin/python
13-
metadata: {'Python': '3.11.2', 'Platform': 'macOS-13.2.1-arm64-arm-64bit', 'Packages': {'pytest': '7.4.0', 'pluggy': '1.2.0'}, 'Plugins': {'html': '2.0.1', 'rerunfailures': '12.0', 'metadata': '3.0.0', 'ordering': '0.6', 'xdist': '3.3.1', 'seleniumbase': '4.15.10'}}
12+
platform darwin -- Python 3.11.9, pytest-8.3.3, pluggy-1.5.0 -- /Users/michael/.virtualenvs/sbase11/bin/python
13+
metadata: {'Python': '3.11.9', 'Platform': 'macOS-13.2.1-arm64-arm-64bit', 'Packages': {'pytest': '8.3.3', 'pluggy': '1.5.0'}, 'Plugins': {'cov': '6.0.0', 'html': '2.0.1', 'metadata': '3.1.1', 'seleniumbase': '4.33.2', 'ordering': '0.6', 'rerunfailures': '15.0', 'xdist': '3.6.1'}}
1414
rootdir: /Users/michael/github/SeleniumBase/examples
1515
configfile: pytest.ini
16-
plugins: html-2.0.1, rerunfailures-12.0, metadata-3.0.0, ordering-0.6, xdist-3.3.1, seleniumbase-4.15.10
17-
collected 4 items
16+
plugins: html-2.0.1, metadata-3.1.1, seleniumbase-4.33.2, ordering-0.6, rerunfailures-15.0, xdist-3.6.1
17+
collected 4 items
1818

1919
example_test.py::AngularJSHomePageTests::test_greet_user PASSED
2020
example_test.py::AngularJSHomePageTests::test_todo_list PASSED

mkdocs.yml

+2
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ plugins:
7373
- CONTRIBUTING.md
7474
- SECURITY.md
7575
- examples/case_summary.md
76+
- examples/migration/raw_selenium/ReadMe.md
7677
- help_docs/chinese.md
7778
- integrations/katalon/ReadMe.md
7879
- help_docs/ReadMe.md
@@ -174,6 +175,7 @@ nav:
174175
- 📃 Desired Capabilities: help_docs/desired_capabilities.md
175176
- 📜 Useful grep commands: help_docs/useful_grep_commands.md
176177
- ⚙️ Downloading drivers: help_docs/webdriver_installation.md
178+
- ✅ Selenium Migration: examples/migration/raw_selenium/ReadMe.md
177179
- ✔️ Verifying drivers: help_docs/verify_webdriver.md
178180
- Behave-BDD Integration:
179181
- 🐝 Behave-BDD ReadMe: examples/behave_bdd/ReadMe.md

mkdocs_build/prepare.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,17 @@ def main(*args, **kwargs):
7676
scanned_dir_list = []
7777
scanned_dir_list.append("help_docs")
7878
scanned_dir_list.append("examples")
79-
scanned_dir_list.append("examples/behave_bdd")
80-
scanned_dir_list.append("examples/example_logs")
79+
scanned_dir_list.append("examples/cdp_mode")
80+
scanned_dir_list.append("examples/master_qa")
8181
scanned_dir_list.append("examples/presenter")
82+
scanned_dir_list.append("examples/behave_bdd")
8283
scanned_dir_list.append("examples/chart_maker")
84+
scanned_dir_list.append("examples/example_logs")
8385
scanned_dir_list.append("examples/tour_examples")
8486
scanned_dir_list.append("examples/visual_testing")
8587
scanned_dir_list.append("integrations/google_cloud")
8688
scanned_dir_list.append("seleniumbase/console_scripts")
89+
scanned_dir_list.append("examples/migration/raw_selenium")
8790
for scanned_dir in scanned_dir_list:
8891
for dir_ in os.listdir(ROOT_DIR / scanned_dir):
8992
files_to_process.append(os.path.join(scanned_dir, dir_))
@@ -159,6 +162,12 @@ def main(*args, **kwargs):
159162
)
160163
if alt_link_badge in line:
161164
line = line.replace(alt_link_badge, back_to_gh)
165+
changed = True
166+
if "/help_docs/uc_mode/" in line and file_.count("/") >= 2:
167+
line = line.replace(
168+
"/help_docs/uc_mode/", "/../help_docs/uc_mode/"
169+
)
170+
changed = True
162171
if "<!-- GitHub Only -->" in line:
163172
changed = True
164173
continue

seleniumbase/__version__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# seleniumbase package
2-
__version__ = "4.33.1"
2+
__version__ = "4.33.2"

seleniumbase/core/browser_launcher.py

+4
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,10 @@ def uc_open_with_cdp_mode(driver, url=None):
703703
cdp.assert_exact_text = CDPM.assert_exact_text
704704
cdp.assert_true = CDPM.assert_true
705705
cdp.assert_false = CDPM.assert_false
706+
cdp.assert_equal = CDPM.assert_equal
707+
cdp.assert_not_equal = CDPM.assert_not_equal
708+
cdp.assert_in = CDPM.assert_in
709+
cdp.assert_not_in = CDPM.assert_not_in
706710
cdp.scroll_into_view = CDPM.scroll_into_view
707711
cdp.scroll_to_y = CDPM.scroll_to_y
708712
cdp.scroll_to_top = CDPM.scroll_to_top

seleniumbase/core/sb_cdp.py

+28-21
Original file line numberDiff line numberDiff line change
@@ -135,23 +135,10 @@ def find_element(
135135
self.__add_light_pause()
136136
selector = self.__convert_to_css_if_xpath(selector)
137137
early_failure = False
138-
if (":contains(" in selector):
139-
tag_name = selector.split(":contains(")[0].split(" ")[-1]
140-
text = selector.split(":contains(")[1].split(")")[0][1:-1]
141-
with suppress(Exception):
142-
self.loop.run_until_complete(
143-
self.page.select(tag_name, timeout=timeout)
144-
)
145-
self.loop.run_until_complete(
146-
self.page.find(text, timeout=timeout)
147-
)
148-
elements = []
149-
with suppress(Exception):
150-
elements = self.find_elements_by_text(text, tag_name=tag_name)
151-
if elements:
152-
return self.__add_sync_methods(elements[0])
153-
else:
154-
early_failure = True
138+
if (":contains(") in selector:
139+
selector, _ = page_utils.recalculate_selector(
140+
selector, by="css selector", xp_ok=True
141+
)
155142
failure = False
156143
try:
157144
if early_failure:
@@ -726,12 +713,16 @@ def set_value(self, selector, text, timeout=settings.SMALL_TIMEOUT):
726713

727714
def evaluate(self, expression):
728715
"""Run a JavaScript expression and return the result."""
716+
if expression.startswith("return "):
717+
expression = expression[len("return "):]
729718
return self.loop.run_until_complete(
730719
self.page.evaluate(expression)
731720
)
732721

733722
def js_dumps(self, obj_name):
734723
"""Similar to evaluate(), but for dictionary results."""
724+
if obj_name.startswith("return "):
725+
obj_name = obj_name[len("return "):]
735726
return self.loop.run_until_complete(
736727
self.page.js_dumps(obj_name)
737728
)
@@ -1648,11 +1639,11 @@ def assert_text(
16481639
text = text.strip()
16491640
element = None
16501641
try:
1651-
element = self.select(selector, timeout=timeout)
1642+
element = self.find_element(selector, timeout=timeout)
16521643
except Exception:
16531644
raise Exception("Element {%s} not found!" % selector)
16541645
for i in range(30):
1655-
if self.is_element_visible(selector) and text in element.text_all:
1646+
if text in element.text_all:
16561647
return True
16571648
time.sleep(0.1)
16581649
raise Exception(
@@ -1683,11 +1674,27 @@ def assert_exact_text(
16831674

16841675
def assert_true(self, expression):
16851676
if not expression:
1686-
raise AssertionError("%s is not true")
1677+
raise AssertionError("%s is not true" % expression)
16871678

16881679
def assert_false(self, expression):
16891680
if expression:
1690-
raise AssertionError("%s is not false")
1681+
raise AssertionError("%s is not false" % expression)
1682+
1683+
def assert_equal(self, first, second):
1684+
if first != second:
1685+
raise AssertionError("%s is not equal to %s" % (first, second))
1686+
1687+
def assert_not_equal(self, first, second):
1688+
if first == second:
1689+
raise AssertionError("%s is equal to %s" % (first, second))
1690+
1691+
def assert_in(self, first, second):
1692+
if first not in second:
1693+
raise AssertionError("%s is not in %s" % (first, second))
1694+
1695+
def assert_not_in(self, first, second):
1696+
if first in second:
1697+
raise AssertionError("%s is in %s" % (first, second))
16911698

16921699
def scroll_into_view(self, selector):
16931700
self.find_element(selector).scroll_into_view()

seleniumbase/fixtures/base_case.py

+15-13
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ def click(
392392
original_by = by
393393
selector, by = self.__recalculate_selector(selector, by)
394394
if self.__is_cdp_swap_needed():
395-
self.cdp.click(selector)
395+
self.cdp.click(selector, timeout=timeout)
396396
return
397397
if delay and (type(delay) in [int, float]) and delay > 0:
398398
time.sleep(delay)
@@ -885,7 +885,7 @@ def update_text(
885885
timeout = self.__get_new_timeout(timeout)
886886
selector, by = self.__recalculate_selector(selector, by)
887887
if self.__is_cdp_swap_needed():
888-
self.cdp.type(selector, text)
888+
self.cdp.type(selector, text, timeout=timeout)
889889
return
890890
if self.__is_shadow_selector(selector):
891891
self.__shadow_type(selector, text, timeout)
@@ -1112,7 +1112,7 @@ def send_keys(self, selector, text, by="css selector", timeout=None):
11121112
def press_keys(self, selector, text, by="css selector", timeout=None):
11131113
"""Use send_keys() to press one key at a time."""
11141114
if self.__is_cdp_swap_needed():
1115-
self.cdp.press_keys(selector, text)
1115+
self.cdp.press_keys(selector, text, timeout=timeout)
11161116
return
11171117
self.wait_for_ready_state_complete()
11181118
element = self.wait_for_element_present(
@@ -1597,7 +1597,7 @@ def click_link_text(self, link_text, timeout=None):
15971597
"""This method clicks link text on a page."""
15981598
self.__check_scope()
15991599
if self.__is_cdp_swap_needed():
1600-
self.cdp.find_element(link_text).click()
1600+
self.cdp.find_element(link_text, timeout=timeout).click()
16011601
return
16021602
self.__skip_if_esc()
16031603
if not timeout:
@@ -3380,6 +3380,8 @@ def open_html_file(self, html_file):
33803380

33813381
def execute_script(self, script, *args, **kwargs):
33823382
self.__check_scope()
3383+
if self.__is_cdp_swap_needed():
3384+
return self.cdp.evaluate(script)
33833385
self._check_browser()
33843386
return self.driver.execute_script(script, *args, **kwargs)
33853387

@@ -6308,7 +6310,7 @@ def js_click(
63086310
If "all_matches" is False, only the first match is clicked.
63096311
If "scroll" is False, won't scroll unless running in Demo Mode."""
63106312
if self.__is_cdp_swap_needed():
6311-
self.cdp.click(selector)
6313+
self.cdp.click(selector, timeout=timeout)
63126314
return
63136315
self.wait_for_ready_state_complete()
63146316
if not timeout or timeout is True:
@@ -8245,7 +8247,7 @@ def enter_mfa_code(
82458247
timeout = settings.SMALL_TIMEOUT
82468248
if self.__is_cdp_swap_needed():
82478249
mfa_code = self.get_mfa_code(totp_key)
8248-
self.cdp.type(selector, mfa_code + "\n")
8250+
self.cdp.type(selector, mfa_code + "\n", timeout=timeout)
82498251
return
82508252
self.wait_for_element_visible(selector, by=by, timeout=timeout)
82518253
if self.recorder_mode and self.__current_url_is_recordable():
@@ -9003,7 +9005,7 @@ def wait_for_element_visible(
90039005
original_selector = selector
90049006
selector, by = self.__recalculate_selector(selector, by)
90059007
if self.__is_cdp_swap_needed():
9006-
return self.cdp.select(selector)
9008+
return self.cdp.select(selector, timeout=timeout)
90079009
if self.__is_shadow_selector(selector):
90089010
return self.__get_shadow_element(selector, timeout)
90099011
return page_actions.wait_for_element_visible(
@@ -9026,7 +9028,7 @@ def wait_for_element_clickable(
90269028
original_selector = selector
90279029
selector, by = self.__recalculate_selector(selector, by)
90289030
if self.__is_cdp_swap_needed():
9029-
return self.cdp.select(selector)
9031+
return self.cdp.select(selector, timeout=timeout)
90309032
elif self.__is_shadow_selector(selector):
90319033
# If a shadow selector, use visible instead of clickable
90329034
return self.__wait_for_shadow_element_visible(selector, timeout)
@@ -9427,7 +9429,7 @@ def wait_for_element_present(
94279429
original_selector = selector
94289430
selector, by = self.__recalculate_selector(selector, by)
94299431
if self.__is_cdp_swap_needed():
9430-
return self.cdp.select(selector)
9432+
return self.cdp.select(selector, timeout=timeout)
94319433
elif self.__is_shadow_selector(selector):
94329434
return self.__wait_for_shadow_element_present(selector, timeout)
94339435
return page_actions.wait_for_element_present(
@@ -9449,7 +9451,7 @@ def wait_for_element(self, selector, by="css selector", timeout=None):
94499451
original_selector = selector
94509452
selector, by = self.__recalculate_selector(selector, by)
94519453
if self.__is_cdp_swap_needed():
9452-
return self.cdp.select(selector)
9454+
return self.cdp.select(selector, timeout=timeout)
94539455
if self.recorder_mode and self.__current_url_is_recordable():
94549456
if self.get_session_storage_item("pause_recorder") == "no":
94559457
if by == By.XPATH:
@@ -9492,7 +9494,7 @@ def wait_for_query_selector(
94929494
timeout = self.__get_new_timeout(timeout)
94939495
css_selector = self.convert_to_css_selector(selector, by=by)
94949496
if self.__is_cdp_swap_needed():
9495-
return self.cdp.select(css_selector)
9497+
return self.cdp.select(css_selector, timeout=timeout)
94969498
return js_utils.wait_for_css_query_selector(
94979499
self.driver, css_selector, timeout
94989500
)
@@ -9713,7 +9715,7 @@ def wait_for_text_visible(
97139715
text = self.__get_type_checked_text(text)
97149716
selector, by = self.__recalculate_selector(selector, by)
97159717
if self.__is_cdp_swap_needed():
9716-
return self.cdp.find_element(selector)
9718+
return self.cdp.find_element(selector, timeout=timeout)
97179719
elif self.__is_shadow_selector(selector):
97189720
return self.__wait_for_shadow_text_visible(text, selector, timeout)
97199721
return page_actions.wait_for_text_visible(
@@ -10093,7 +10095,7 @@ def assert_link_text(self, link_text, timeout=None):
1009310095
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
1009410096
timeout = self.__get_new_timeout(timeout)
1009510097
if self.__is_cdp_swap_needed():
10096-
self.cdp.find_element(link_text)
10098+
self.cdp.find_element(link_text, timeout=timeout)
1009710099
return
1009810100
self.wait_for_link_text_visible(link_text, timeout=timeout)
1009910101
if self.demo_mode:

0 commit comments

Comments
 (0)