diff --git a/README.md b/README.md index ec51798ffaa..6ae64c1b2b4 100755 --- a/README.md +++ b/README.md @@ -93,6 +93,7 @@ from seleniumbase import SB with SB(uc=True, test=True) as sb: url = "https://google.com/ncr" sb.activate_cdp_mode(url) + sb.click_if_visible('button:contains("Accept all")') sb.type('[name="q"]', "SeleniumBase GitHub page") sb.click('[value="Google Search"]') sb.sleep(4) # The "AI Overview" sometimes loads diff --git a/examples/boilerplates/samples/google_test.py b/examples/boilerplates/samples/google_test.py index 1ccb7447f90..d0f67908770 100644 --- a/examples/boilerplates/samples/google_test.py +++ b/examples/boilerplates/samples/google_test.py @@ -16,6 +16,7 @@ def test_google_dot_com(self): if not self.undetectable: self.get_new_driver(undetectable=True) self.driver.get("https://google.com/ncr") + self.click_if_visible('button:contains("Accept all")') self.assert_title_contains("Google") self.sleep(0.05) self.save_screenshot_to_logs() # ("./latest_logs" folder) diff --git a/examples/boilerplates/samples/test_page_objects.py b/examples/boilerplates/samples/test_page_objects.py index 69c102d6812..787579a6f90 100644 --- a/examples/boilerplates/samples/test_page_objects.py +++ b/examples/boilerplates/samples/test_page_objects.py @@ -6,6 +6,7 @@ class GooglePage: def go_to_google(self, sb): sb.driver.get("https://google.com/ncr") + sb.click_if_visible('button:contains("Accept all")') def assert_google_title(self, sb): sb.assert_title_contains("Google") diff --git a/examples/cdp_mode/ReadMe.md b/examples/cdp_mode/ReadMe.md index 6ba8a2d2852..4e838b1bccb 100644 --- a/examples/cdp_mode/ReadMe.md +++ b/examples/cdp_mode/ReadMe.md @@ -559,9 +559,9 @@ sb.cdp.assert_equal(first, second) sb.cdp.assert_not_equal(first, second) sb.cdp.assert_in(first, second) sb.cdp.assert_not_in(first, second) +sb.cdp.js_scroll_into_view(selector) sb.cdp.scroll_into_view(selector) sb.cdp.scroll_to_y(y) -sb.cdp.scroll_by_y(y) sb.cdp.scroll_to_top() sb.cdp.scroll_to_bottom() sb.cdp.scroll_up(amount=25) @@ -730,6 +730,7 @@ element.flash(duration=0.5, color="EE4488") element.focus() element.gui_click(timeframe=0.25) element.highlight_overlay() +element.is_in_viewport() element.mouse_click() element.mouse_drag(destination) element.mouse_move() diff --git a/examples/cdp_mode/raw_homedepot.py b/examples/cdp_mode/raw_homedepot.py index 9cba9eb94f1..83c5e1cfd7c 100644 --- a/examples/cdp_mode/raw_homedepot.py +++ b/examples/cdp_mode/raw_homedepot.py @@ -1,15 +1,17 @@ from seleniumbase import SB -with SB(uc=True, test=True, ad_block=True) as sb: +with SB(uc=True, test=True, incognito=True) as sb: url = "https://www.homedepot.com/" sb.activate_cdp_mode(url) - sb.sleep(1.8) + sb.sleep(1.4) + sb.click_if_visible('[data-testid="CloseIcon"]', timeout=3) + sb.sleep(1.2) search_box = "input#typeahead-search-field-input" search = "Computer Chair" category = "Gaming Chairs" required_text = "Chair" sb.click(search_box) - sb.sleep(1.2) + sb.sleep(0.8) sb.press_keys(search_box, search) sb.sleep(0.6) sb.click("button#typeahead-search-icon-button") diff --git a/examples/cdp_mode/raw_priceline.py b/examples/cdp_mode/raw_priceline.py index a951f74b03e..063c41a4a86 100644 --- a/examples/cdp_mode/raw_priceline.py +++ b/examples/cdp_mode/raw_priceline.py @@ -31,13 +31,11 @@ sb.sleep(0.6) sb.sleep(0.8) for y in range(1, 9): - sb.scroll_to_y(y * 400) - sb.sleep(0.5) + sb.scroll_to_y(y * 200) + sb.sleep(0.4) hotel_names = sb.find_elements('h3 div[class*="TitleName"]') if not hotel_names: - hotel_names = sb.find_elements( - 'a[data-autobot-element-id*="HOTEL_NAME"]' - ) + hotel_names = sb.find_elements("h3.antialiased") price_selector = '[class*="PriceWrap"] .relative > .items-center' if sb.is_element_visible(price_selector): hotel_prices = sb.find_elements(price_selector) @@ -52,7 +50,6 @@ 'span.text-priceSuper-heading4 + div > span' ) print("Priceline Hotels in %s:" % location) - print(sb.get_text('[data-testid="POPOVER-DATE-PICKER"]')) if len(hotel_names) == 0: print("No availability over the selected dates!") count = 0 diff --git a/examples/cdp_mode/raw_stopandshop.py b/examples/cdp_mode/raw_stopandshop.py index c67ebe69957..9a976ede997 100644 --- a/examples/cdp_mode/raw_stopandshop.py +++ b/examples/cdp_mode/raw_stopandshop.py @@ -1,7 +1,7 @@ """Test Stop & Shop search. Non-US IPs might be blocked.""" from seleniumbase import SB -with SB(uc=True, test=True, incognito=True) as sb: +with SB(uc=True, test=True, guest=True) as sb: url = "https://stopandshop.com/" sb.activate_cdp_mode(url) sb.sleep(2.6) @@ -9,6 +9,7 @@ sb.refresh() sb.sleep(2.6) sb.wait_for_element("#brand-logo_link", timeout=3) + sb.click_if_visible("#optly-popup-refresh-btn") query = "Fresh Turkey" required_text = "Turkey" search_box = 'input[type="search"]' diff --git a/examples/hack_the_planet.py b/examples/hack_the_planet.py index be1d70430e4..d33c2697a51 100644 --- a/examples/hack_the_planet.py +++ b/examples/hack_the_planet.py @@ -58,6 +58,7 @@ def test_all_your_base_are_belong_to_us(self): self.highlight("#shelf-2_section span", loops=6, scroll=False) self.open("https://google.com/ncr") + self.click_if_visible('button:contains("Accept all")') self.hide_elements("iframe") if self.is_element_visible('a[href*="about.google"]'): self.set_text_content('a[href*="about.google"]', ayb) @@ -191,7 +192,7 @@ def test_all_your_base_are_belong_to_us(self): self.highlight("h1.article_title", loops=5, scroll=False) self.open("https://kubernetes.io/") - self.set_text_content('nav a[href="/docs/"]', "ALL") + self.set_text_content('nav a[href="/docs/home/"]', "ALL") self.set_text_content('nav a[href="/blog/"]', "YOUR") self.set_text_content('nav a[href="/training/"]', "BASE") self.set_text_content('nav a[href="/careers/"]', "ARE") @@ -202,7 +203,7 @@ def test_all_your_base_are_belong_to_us(self): if self.is_element_visible("h1"): self.set_text_content("h1", aybabtu) self.highlight("nav ul.navbar-nav", loops=3, scroll=False) - self.highlight('nav a[href="/docs/"]', loops=1, scroll=False) + self.highlight('nav a[href="/docs/home/"]', loops=1, scroll=False) self.highlight('nav a[href="/blog/"]', loops=1, scroll=False) self.highlight('nav a[href="/training/"]', loops=2, scroll=False) self.highlight('nav a[href="/careers/"]', loops=1, scroll=False) diff --git a/examples/presenter/uc_presentation_4.py b/examples/presenter/uc_presentation_4.py index 58fd2e8fa93..09bc30ee89a 100644 --- a/examples/presenter/uc_presentation_4.py +++ b/examples/presenter/uc_presentation_4.py @@ -799,13 +799,11 @@ def test_presentation_4(self): sb.sleep(0.6) sb.sleep(0.8) for y in range(1, 9): - sb.scroll_to_y(y * 400) - sb.sleep(0.5) + sb.scroll_to_y(y * 200) + sb.sleep(0.4) hotel_names = sb.find_elements('h3 div[class*="TitleName"]') if not hotel_names: - hotel_names = sb.find_elements( - 'a[data-autobot-element-id*="HOTEL_NAME"]' - ) + hotel_names = sb.find_elements("h3.antialiased") price_selector = '[class*="PriceWrap"] .relative > .items-center' if sb.is_element_visible(price_selector): hotel_prices = sb.find_elements(price_selector) @@ -820,7 +818,6 @@ def test_presentation_4(self): 'span.text-priceSuper-heading4 + div > span' ) print("Priceline Hotels in %s:" % location) - print(sb.get_text('[data-testid="POPOVER-DATE-PICKER"]')) if len(hotel_names) == 0: print("No availability over the selected dates!") count = 0 diff --git a/examples/raw_google.py b/examples/raw_google.py index 89485f4039b..5ec7fedbee4 100644 --- a/examples/raw_google.py +++ b/examples/raw_google.py @@ -3,6 +3,7 @@ with SB(uc=True, test=True) as sb: url = "https://google.com/ncr" sb.activate_cdp_mode(url) + sb.click_if_visible('button:contains("Accept all")') sb.type('[name="q"]', "SeleniumBase GitHub page") sb.click('[value="Google Search"]') sb.sleep(4) # The "AI Overview" sometimes loads diff --git a/examples/raw_test_scripts.py b/examples/raw_test_scripts.py index d16d5815cc3..d587e84ea4b 100644 --- a/examples/raw_test_scripts.py +++ b/examples/raw_test_scripts.py @@ -3,6 +3,7 @@ with SB(uc=True, test=True) as sb: sb.open("https://google.com/ncr") + sb.click_if_visible('button:contains("Accept all")') sb.type('[name="q"]', "SeleniumBase on GitHub") sb.click('[value="Google Search"]') sb.highlight('a[href*="github.com/seleniumbase"]') diff --git a/examples/test_hack_search.py b/examples/test_hack_search.py index 5c8c5b990d8..26c647ab501 100644 --- a/examples/test_hack_search.py +++ b/examples/test_hack_search.py @@ -14,6 +14,7 @@ def test_hack_search(self): if not self.undetectable: self.get_new_driver(undetectable=True) self.open("https://google.com/ncr") + self.click_if_visible('button:contains("Accept all")') self.hide_elements("iframe") self.assert_element('[title="Search"]') self.sleep(0.5) @@ -25,6 +26,7 @@ def test_hack_search(self): self.highlight("h1.b_logo", loops=8) source = self.get_page_source() self.assert_true("github.com/seleniumbase/SeleniumBase" in source) + self.internalize_links() self.click('a:contains("seleniumbase/SeleniumBase")') self.js_click('a[title="examples"]') self.highlight('#repo-content-turbo-frame') diff --git a/examples/tour_examples/ReadMe.md b/examples/tour_examples/ReadMe.md index d1231d6a38f..9ab0f0e9a5d 100644 --- a/examples/tour_examples/ReadMe.md +++ b/examples/tour_examples/ReadMe.md @@ -111,6 +111,7 @@ class MyTourClass(BaseCase): if not self.undetectable: self.get_new_driver(undetectable=True) self.open('https://google.com/ncr') + self.click_if_visible('button:contains("Accept all")') self.wait_for_element('input[title="Search"]') self.hide_elements("iframe") diff --git a/examples/tour_examples/bootstrap_google_tour.py b/examples/tour_examples/bootstrap_google_tour.py index 3d7b67a3457..b1c80b07e96 100644 --- a/examples/tour_examples/bootstrap_google_tour.py +++ b/examples/tour_examples/bootstrap_google_tour.py @@ -7,6 +7,7 @@ def test_google_tour(self): if not self.undetectable: self.get_new_driver(undetectable=True) self.open("https://google.com/ncr") + self.click_if_visible('button:contains("Accept all")') self.wait_for_element('[title="Search"]') self.hide_elements("iframe") @@ -33,9 +34,9 @@ def test_google_tour(self): self.play_tour(interval=3) # Tour automatically continues after 3 sec self.open("https://www.google.com/maps/@42.3591234,-71.0915634,15z") - self.wait_for_element("#searchboxinput", timeout=20) - self.wait_for_element("#minimap", timeout=20) - self.wait_for_element("#zoom", timeout=20) + self.wait_for_element('[name="q"]', timeout=20) + self.wait_for_element('[aria-label="Interactive map"]', timeout=20) + self.wait_for_element('[aria-label="Zoom in"]', timeout=20) self.wait_for_element('[aria-label="Zoom out"]') self.wait_for_element('[jsaction*="minimap.main;"]') self.sleep(0.5) diff --git a/examples/tour_examples/driverjs_maps_tour.py b/examples/tour_examples/driverjs_maps_tour.py index c1e0d9343f3..847fc8abc17 100644 --- a/examples/tour_examples/driverjs_maps_tour.py +++ b/examples/tour_examples/driverjs_maps_tour.py @@ -5,10 +5,10 @@ class MyTestClass(BaseCase): def test_create_tour(self): self.open("https://www.google.com/maps/@42.3591234,-71.0915634,15z") - self.wait_for_element("#searchboxinput", timeout=20) - self.wait_for_element("#minimap", timeout=20) - self.wait_for_element("#zoom", timeout=20) - self.wait_for_element("#widget-zoom-out") + self.wait_for_element('[name="q"]', timeout=20) + self.wait_for_element('[aria-label="Interactive map"]', timeout=20) + self.wait_for_element('[aria-label="Zoom in"]', timeout=20) + self.wait_for_element('[aria-label="Zoom out"]') self.wait_for_element('[jsaction*="minimap.main;"]') self.sleep(0.5) diff --git a/examples/tour_examples/google_tour.py b/examples/tour_examples/google_tour.py index 54749721d79..c68a1539a53 100644 --- a/examples/tour_examples/google_tour.py +++ b/examples/tour_examples/google_tour.py @@ -7,6 +7,7 @@ def test_google_tour(self): if not self.undetectable: self.get_new_driver(undetectable=True) self.open("https://google.com/ncr") + self.click_if_visible('button:contains("Accept all")') self.wait_for_element('[title="Search"]') self.hide_elements("iframe") @@ -39,9 +40,9 @@ def test_google_tour(self): self.play_tour(interval=3) # Tour automatically continues after 3 sec self.open("https://www.google.com/maps/@42.3591234,-71.0915634,15z") - self.wait_for_element("#searchboxinput") - self.wait_for_element("#minimap") - self.wait_for_element("#zoom") + self.wait_for_element('[name="q"]', timeout=20) + self.wait_for_element('[aria-label="Interactive map"]', timeout=20) + self.wait_for_element('[aria-label="Zoom in"]', timeout=20) self.wait_for_element('[aria-label="Zoom out"]') self.wait_for_element('[jsaction*="minimap.main;"]') self.sleep(0.5) diff --git a/examples/tour_examples/hopscotch_google_tour.py b/examples/tour_examples/hopscotch_google_tour.py index 9154ad40967..7bbdc1747d8 100644 --- a/examples/tour_examples/hopscotch_google_tour.py +++ b/examples/tour_examples/hopscotch_google_tour.py @@ -7,6 +7,7 @@ def test_google_tour(self): if not self.undetectable: self.get_new_driver(undetectable=True) self.open("https://google.com/ncr") + self.click_if_visible('button:contains("Accept all")') self.wait_for_element('[title="Search"]') self.hide_elements("iframe") @@ -33,9 +34,9 @@ def test_google_tour(self): self.play_tour(interval=3) # Tour automatically continues after 3 sec self.open("https://www.google.com/maps/@42.3591234,-71.0915634,15z") - self.wait_for_element("#searchboxinput", timeout=20) - self.wait_for_element("#minimap", timeout=20) - self.wait_for_element("#zoom", timeout=20) + self.wait_for_element('[name="q"]', timeout=20) + self.wait_for_element('[aria-label="Interactive map"]', timeout=20) + self.wait_for_element('[aria-label="Zoom in"]', timeout=20) self.wait_for_element('[aria-label="Zoom out"]') self.wait_for_element('[jsaction*="minimap.main;"]') self.sleep(0.5) diff --git a/examples/tour_examples/introjs_google_tour.py b/examples/tour_examples/introjs_google_tour.py index 141e007dc04..a07cfc73e70 100644 --- a/examples/tour_examples/introjs_google_tour.py +++ b/examples/tour_examples/introjs_google_tour.py @@ -7,6 +7,7 @@ def test_google_tour(self): if not self.undetectable: self.get_new_driver(undetectable=True) self.open("https://google.com/ncr") + self.click_if_visible('button:contains("Accept all")') self.wait_for_element('[title="Search"]') self.hide_elements("iframe") @@ -33,9 +34,9 @@ def test_google_tour(self): self.play_tour(interval=3) # Tour automatically continues after 3 sec self.open("https://www.google.com/maps/@42.3591234,-71.0915634,15z") - self.wait_for_element("#searchboxinput", timeout=20) - self.wait_for_element("#minimap", timeout=20) - self.wait_for_element("#zoom", timeout=20) + self.wait_for_element('[name="q"]', timeout=20) + self.wait_for_element('[aria-label="Interactive map"]', timeout=20) + self.wait_for_element('[aria-label="Zoom in"]', timeout=20) self.wait_for_element('[aria-label="Zoom out"]') self.wait_for_element('[jsaction*="minimap.main;"]') self.sleep(0.5) diff --git a/examples/tour_examples/maps_introjs_tour.py b/examples/tour_examples/maps_introjs_tour.py index 8f392fdfdf2..e3035435949 100644 --- a/examples/tour_examples/maps_introjs_tour.py +++ b/examples/tour_examples/maps_introjs_tour.py @@ -5,11 +5,12 @@ class MyTourClass(BaseCase): def test_google_maps_tour(self): self.open("https://www.google.com/maps/@42.3591234,-71.0915634,15z") - self.wait_for_element("#searchboxinput", timeout=20) - self.wait_for_element("#minimap", timeout=20) - self.wait_for_element("#zoom", timeout=20) + self.wait_for_element('[name="q"]', timeout=20) + self.wait_for_element('[aria-label="Interactive map"]', timeout=20) + self.wait_for_element('[aria-label="Zoom in"]', timeout=20) self.wait_for_element('[aria-label="Zoom out"]') self.wait_for_element('[jsaction*="minimap.main;"]') + self.sleep(0.5) self.create_tour(theme="introjs") self.add_tour_step( diff --git a/examples/tour_examples/shepherd_google_tour.py b/examples/tour_examples/shepherd_google_tour.py index e4095d82914..e2d0eee18cb 100644 --- a/examples/tour_examples/shepherd_google_tour.py +++ b/examples/tour_examples/shepherd_google_tour.py @@ -7,6 +7,7 @@ def test_google_tour(self): if not self.undetectable: self.get_new_driver(undetectable=True) self.open("https://google.com/ncr") + self.click_if_visible('button:contains("Accept all")') self.wait_for_element('[title="Search"]') self.hide_elements("iframe") @@ -33,9 +34,9 @@ def test_google_tour(self): self.play_tour(interval=3) # Tour automatically continues after 3 sec self.open("https://www.google.com/maps/@42.3591234,-71.0915634,15z") - self.wait_for_element("#searchboxinput", timeout=20) - self.wait_for_element("#minimap", timeout=20) - self.wait_for_element("#zoom", timeout=20) + self.wait_for_element('[name="q"]', timeout=20) + self.wait_for_element('[aria-label="Interactive map"]', timeout=20) + self.wait_for_element('[aria-label="Zoom in"]', timeout=20) self.wait_for_element('[aria-label="Zoom out"]') self.wait_for_element('[jsaction*="minimap.main;"]') self.sleep(0.5) diff --git a/help_docs/cdp_mode_methods.md b/help_docs/cdp_mode_methods.md index 67f86baf2d9..3e91ef9bd14 100644 --- a/help_docs/cdp_mode_methods.md +++ b/help_docs/cdp_mode_methods.md @@ -187,8 +187,8 @@ sb.cdp.assert_equal(first, second) sb.cdp.assert_not_equal(first, second) sb.cdp.assert_in(first, second) sb.cdp.assert_not_in(first, second) +sb.cdp.js_scroll_into_view(selector) sb.cdp.scroll_into_view(selector) -sb.cdp.scroll_to_y(y) sb.cdp.scroll_by_y(y) sb.cdp.scroll_to_top() sb.cdp.scroll_to_bottom() @@ -358,6 +358,7 @@ element.flash(duration=0.5, color="EE4488") element.focus() element.gui_click(timeframe=0.25) element.highlight_overlay() +element.is_in_viewport() element.mouse_click() element.mouse_drag(destination) element.mouse_move() diff --git a/seleniumbase/__version__.py b/seleniumbase/__version__.py index 9dec5ae7a68..cc3ab74ee64 100755 --- a/seleniumbase/__version__.py +++ b/seleniumbase/__version__.py @@ -1,2 +1,2 @@ # seleniumbase package -__version__ = "4.47.6" +__version__ = "4.47.7" diff --git a/seleniumbase/console_scripts/sb_mkdir.py b/seleniumbase/console_scripts/sb_mkdir.py index 97ef2075582..d843e921748 100644 --- a/seleniumbase/console_scripts/sb_mkdir.py +++ b/seleniumbase/console_scripts/sb_mkdir.py @@ -712,6 +712,9 @@ def main(): data.append(" if not self.undetectable:") data.append(" self.get_new_driver(undetectable=True)") data.append(' self.open("https://google.com/ncr")') + data.append( + " sb.click_if_visible('button:contains(\"Accept all\")')" + ) data.append(' self.assert_title_contains("Google")') data.append(" self.save_screenshot_to_logs()") data.append(' self.type(HomePage.search_box, "github.com")') diff --git a/seleniumbase/core/browser_launcher.py b/seleniumbase/core/browser_launcher.py index 2edea7ca128..5f3ccf266d5 100644 --- a/seleniumbase/core/browser_launcher.py +++ b/seleniumbase/core/browser_launcher.py @@ -942,6 +942,7 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs): cdp.assert_not_equal = CDPM.assert_not_equal cdp.assert_in = CDPM.assert_in cdp.assert_not_in = CDPM.assert_not_in + cdp.js_scroll_into_view = CDPM.js_scroll_into_view cdp.scroll_into_view = CDPM.scroll_into_view cdp.scroll_to_y = CDPM.scroll_to_y cdp.scroll_by_y = CDPM.scroll_by_y diff --git a/seleniumbase/core/sb_cdp.py b/seleniumbase/core/sb_cdp.py index 7722c0c6552..3a9e7dcc599 100644 --- a/seleniumbase/core/sb_cdp.py +++ b/seleniumbase/core/sb_cdp.py @@ -66,6 +66,7 @@ def __add_sync_methods(self, element): lambda *args, **kwargs: self.__gui_click(element, *args, **kwargs) ) element.highlight_overlay = lambda: self.__highlight_overlay(element) + element.is_in_viewport = lambda: self.__is_in_viewport(element) element.mouse_click = lambda: self.__mouse_click(element) element.click_with_offset = ( lambda *args, **kwargs: self.__mouse_click_with_offset_async( @@ -543,6 +544,11 @@ def __highlight_overlay(self, element): self.loop.run_until_complete(element.highlight_overlay_async()) ) + def __is_in_viewport(self, element): + return ( + self.loop.run_until_complete(element.is_in_viewport_async()) + ) + def __mouse_click(self, element): result = ( self.loop.run_until_complete(element.mouse_click_async()) @@ -800,9 +806,9 @@ def click(self, selector, timeout=None, scroll=True): timeout = settings.SMALL_TIMEOUT self.__slow_mode_pause_if_set() element = self.find_element(selector, timeout=timeout) - if scroll: - element.scroll_into_view() tag_name = element.tag_name + current_url = self.get_current_url() + if tag_name: tag_name = tag_name.lower().strip() if ( @@ -810,12 +816,24 @@ def click(self, selector, timeout=None, scroll=True): "a", "button", "canvas", "div", "input", "li", "span", "label" ] and "contains(" not in selector + and "://google" not in current_url + and "://www.google" not in current_url ): + if scroll: + element.scroll_into_view() try: element.mouse_click() # Simulated click (NOT PyAutoGUI) except Exception: element.click() # Standard CDP click else: + if scroll: + if "contains(" in selector: + element.scroll_into_view() + else: + try: + self.js_scroll_into_view(selector) + except Exception: + element.scroll_into_view() element.click() # Standard CDP click self.__slow_mode_pause_if_set() self.loop.run_until_complete(self.page.wait(0.2)) @@ -3109,6 +3127,17 @@ def assert_not_in(self, first, second): if first in second: raise AssertionError("%s is in %s" % (first, second)) + def js_scroll_into_view(self, selector): + css_selector = self.__convert_to_css_if_xpath(selector) + css_selector = re.escape(css_selector) # Add "\\" to special chars + css_selector = js_utils.escape_quotes_if_needed(css_selector) + js_code = ( + "document.querySelector('%s')?.scrollIntoView();" + % css_selector + ) + with suppress(Exception): + self.loop.run_until_complete(self.page.evaluate(js_code)) + def scroll_into_view(self, selector): self.find_element(selector).scroll_into_view() self.loop.run_until_complete(self.page.wait(0.1)) diff --git a/seleniumbase/plugins/sb_manager.py b/seleniumbase/plugins/sb_manager.py index 984e21dece3..fa8836c2bdc 100644 --- a/seleniumbase/plugins/sb_manager.py +++ b/seleniumbase/plugins/sb_manager.py @@ -13,6 +13,7 @@ with SB(uc=True, test=True) as sb: url = "https://google.com/ncr" sb.activate_cdp_mode(url) + sb.click_if_visible('button:contains("Accept all")') sb.type('[name="q"]', "SeleniumBase GitHub page") sb.click('[value="Google Search"]') sb.sleep(2) @@ -148,6 +149,7 @@ def SB( with SB(uc=True, test=True) as sb: url = "https://google.com/ncr" sb.activate_cdp_mode(url) + sb.click_if_visible('button:contains("Accept all")') sb.type('[name="q"]', "SeleniumBase GitHub page") sb.click('[value="Google Search"]') sb.sleep(2) diff --git a/seleniumbase/undetected/cdp_driver/element.py b/seleniumbase/undetected/cdp_driver/element.py index 93f78bfee5e..46db7e8b513 100644 --- a/seleniumbase/undetected/cdp_driver/element.py +++ b/seleniumbase/undetected/cdp_driver/element.py @@ -467,8 +467,8 @@ async def get_position_async(self, abs=False) -> Position: raise Exception("Could not find position for %s " % self) pos = Position(quads[0]) if abs: - scroll_y = (await self.tab.evaluate("window.scrollY")).value - scroll_x = (await self.tab.evaluate("window.scrollX")).value + scroll_y = (await self.tab.evaluate("window.scrollY")) + scroll_x = (await self.tab.evaluate("window.scrollX")) abs_x = pos.left + scroll_x + (pos.width / 2) abs_y = pos.top + scroll_y + (pos.height / 2) pos.abs_x = abs_x @@ -717,6 +717,31 @@ async def mouse_drag_async( ) ) + async def is_in_viewport_async(self): + try: + layout = await self.tab.send( + cdp.page.get_layout_metrics() + ) + viewport = layout[4] + v_left = viewport.page_x + v_top = viewport.page_y + v_right = v_left + viewport.client_width + v_bottom = v_top + viewport.client_height + box = await self.tab.send( + cdp.dom.get_box_model(backend_node_id=self.backend_node_id) + ) + quad = box.content + e_left = min(quad[0], quad[2], quad[4], quad[6]) + e_top = min(quad[1], quad[3], quad[5], quad[7]) + e_right = max(quad[0], quad[2], quad[4], quad[6]) + e_bottom = max(quad[1], quad[3], quad[5], quad[7]) + return ( + e_left >= v_left and e_right <= v_right + and e_top >= v_top and e_bottom <= v_bottom + ) + except Exception: + return False + async def scroll_into_view_async(self): """Scrolls element into view.""" try: diff --git a/seleniumbase/undetected/cdp_driver/tab.py b/seleniumbase/undetected/cdp_driver/tab.py index 0adfbc0d5c8..bd60df7656c 100644 --- a/seleniumbase/undetected/cdp_driver/tab.py +++ b/seleniumbase/undetected/cdp_driver/tab.py @@ -226,7 +226,6 @@ async def find( except (Exception, TypeError): pass while not item: - await self item = await self.find_element_by_text( text, best_match, return_enclosing_element )