From 43b7e0a525180c25e8bbf3508bf664cb2c90cd20 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Mon, 18 Apr 2022 01:15:01 -0400 Subject: [PATCH 1/4] Add and update methods related to iframes --- help_docs/method_summary.md | 8 +++- seleniumbase/fixtures/base_case.py | 77 ++++++++++++++++++++++++------ 2 files changed, 70 insertions(+), 15 deletions(-) diff --git a/help_docs/method_summary.md b/help_docs/method_summary.md index e248b47ddf3..32e76ee00b4 100755 --- a/help_docs/method_summary.md +++ b/help_docs/method_summary.md @@ -207,9 +207,15 @@ self.switch_to_frame(frame, timeout=None) self.switch_to_default_content() +self.switch_to_parent_frame() + self.set_content_to_frame(frame, timeout=None) -self.set_content_to_default(nested=True) +self.set_content_to_default(nested=False) +# Duplicates: self.set_content_to_default_content(nested=False) + +self.set_content_to_parent() +# Duplicates: self.set_content_to_parent_frame() self.open_new_window(switch_to=True) # Duplicates: self.open_new_tab(switch_to=True) diff --git a/seleniumbase/fixtures/base_case.py b/seleniumbase/fixtures/base_case.py index 2f8fcfaccb2..5c08ee37b77 100755 --- a/seleniumbase/fixtures/base_case.py +++ b/seleniumbase/fixtures/base_case.py @@ -2569,9 +2569,9 @@ def switch_to_frame(self, frame, timeout=None): def switch_to_default_content(self): """Brings driver control outside the current iframe. - (If the driver control is inside an iframe, the driver control - will be set to one level above the current frame. If the driver - control is not currently in an iframe, nothing will happen.)""" + If the driver is currently set inside an iframe or nested iframes, + then the driver control will exit from all entered iframes. + If the driver is not currently set in an iframe, nothing happens.""" self.__check_scope() if self.recorder_mode and self._rec_overrides_switch: url = self.get_current_url() @@ -2589,18 +2589,39 @@ def switch_to_default_content(self): return self.driver.switch_to.default_content() + def switch_to_parent_frame(self): + """Brings driver control outside the current iframe. + If the driver is currently set inside an iframe or nested iframes, + the driver control will be set to one level above the current frame. + If the driver is not currently set in an iframe, nothing happens.""" + self.__check_scope() + if self.recorder_mode and self._rec_overrides_switch: + url = self.get_current_url() + if url and len(url) > 0: + if ("http:") in url or ("https:") in url or ("file:") in url: + r_a = self.get_session_storage_item("recorder_activated") + if r_a == "yes": + self.__set_c_from_switch = True + self.set_content_to_default(nested=True) + self.__set_c_from_switch = False + time_stamp = self.execute_script("return Date.now();") + origin = self.get_origin() + action = ["sw_pf", "", origin, time_stamp] + self.__extra_actions.append(action) + return + self.driver.switch_to.parent_frame() + def set_content_to_frame(self, frame, timeout=None): """Replaces the page html with an iframe's html from that page. - If the iFrame contains an "src" field that includes a valid URL, + If the iframe contains an "src" field that includes a valid URL, then instead of replacing the current html, this method will then - open up the "src" URL of the iFrame in a new browser tab. + open up the "src" URL of the iframe in a new browser tab. To return to default content, use: self.set_content_to_default(). This method also sets the state of the browser window so that the self.set_content_to_default() method can bring the user back to the original content displayed, which is similar to how the methods self.switch_to_frame(frame) and self.switch_to_default_content() - work together to get the user into frames and out of all of them. - """ + work together to get the user into frames and out of all of them.""" self.__check_scope() if not timeout: timeout = settings.SMALL_TIMEOUT @@ -2663,12 +2684,12 @@ def set_content_to_frame(self, frame, timeout=None): action = ["s_c_f", o_frame, origin, time_stamp] self.__extra_actions.append(action) - def set_content_to_default(self, nested=True): + def set_content_to_default(self, nested=False): """After using self.set_content_to_frame(), this reverts the page back. If self.set_content_to_frame() hasn't been called here, only refreshes. - If "nested" is set to False when the content was set to nested iFrames, - then the control will only move above the last iFrame that was entered. - """ + If "nested" is set to True when the content is set to a nested iframe, + then the page control will only exit from the current iframe entered, + instead of exiting out of all iframes entered.""" self.__check_scope() swap_cnt = self.execute_script("return document.cframe_swap;") tab_sta = self.execute_script("return document.cframe_tab;") @@ -2679,7 +2700,10 @@ def set_content_to_default(self, nested=True): action = ["sk_op", "", origin, time_stamp] self.__extra_actions.append(action) - if nested: + if not nested: + # Sets the page to the outer-most content. + # If page control was inside nested iframes, exits them all. + # If only in one iframe, has the same effect as nested=True. if ( len(self.__page_sources) > 0 and ( @@ -2705,6 +2729,9 @@ def set_content_to_default(self, nested=True): self.execute_script("document.cframe_swap = 0;") self.__page_sources = [] else: + # (If Nested is True) + # Sets the page to the content outside the current nested iframe. + # If only in one iframe, has the same effect as nested=True. just_refresh = False if swap_cnt and int(swap_cnt) > 0 and len(self.__page_sources) > 0: self.execute_script("document.cframe_swap -= 1;") @@ -2736,6 +2763,24 @@ def set_content_to_default(self, nested=True): action = ["s_c_d", nested, origin, time_stamp] self.__extra_actions.append(action) + def set_content_to_default_content(self, nested=False): + """Same as self.set_content_to_default().""" + self.set_content_to_default(nested=nested) + + def set_content_to_parent(self): + """Same as self.set_content_to_parent_frame(). + Same as self.set_content_to_default(nested=True). + Sets the page to the content outside the current nested iframe. + Reverts self.set_content_to_frame().""" + self.set_content_to_default(nested=True) + + def set_content_to_parent_frame(self): + """Same as self.set_content_to_parent(). + Same as self.set_content_to_default(nested=True). + Sets the page to the content outside the current nested iframe. + Reverts self.set_content_to_frame().""" + self.set_content_to_default(nested=True) + def open_new_window(self, switch_to=True): """Opens a new browser tab/window and switches to it by default.""" self.__check_scope() @@ -3643,6 +3688,7 @@ def __process_recorded_actions(self): ext_actions.append("as_et") ext_actions.append("sw_fr") ext_actions.append("sw_dc") + ext_actions.append("sw_pf") ext_actions.append("s_c_f") ext_actions.append("s_c_d") ext_actions.append("sh_fc") @@ -3878,6 +3924,8 @@ def __process_recorded_actions(self): sb_actions.append("self.%s('%s')" % (method, action[1])) elif action[0] == "sw_dc": sb_actions.append("self.switch_to_default_content()") + elif action[0] == "sw_pf": + sb_actions.append("self.switch_to_parent_frame()") elif action[0] == "s_c_f": method = "set_content_to_frame" if '"' not in action[1]: @@ -3888,9 +3936,10 @@ def __process_recorded_actions(self): method = "set_content_to_default" nested = action[1] if nested: + method = "set_content_to_parent" sb_actions.append("self.%s()" % method) else: - sb_actions.append("self.%s(nested=False)" % method) + sb_actions.append("self.%s()" % method) elif action[0] == "as_el": method = "assert_element" if '"' not in action[1]: @@ -7001,7 +7050,7 @@ def add_slide( image - Attach an image (from a URL link) to the slide. code - Attach code of any programming language to the slide. Language-detection will be used to add syntax formatting. - iframe - Attach an iFrame (from a URL link) to the slide. + iframe - Attach an iframe (from a URL link) to the slide. content2 - HTML content to display after adding an image or code. notes - Additional notes to include with the slide. ONLY SEEN if show_notes is set for the presentation. From 63e571b86f782ecf4324e6b185e4c0b0104c8690 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Mon, 18 Apr 2022 01:27:10 -0400 Subject: [PATCH 2/4] Better error-handling output --- seleniumbase/fixtures/base_case.py | 83 +++++++++++++++++++++------ seleniumbase/fixtures/page_actions.py | 66 +++++++++++++++++++-- 2 files changed, 128 insertions(+), 21 deletions(-) diff --git a/seleniumbase/fixtures/base_case.py b/seleniumbase/fixtures/base_case.py index 5c08ee37b77..6417388e201 100755 --- a/seleniumbase/fixtures/base_case.py +++ b/seleniumbase/fixtures/base_case.py @@ -230,7 +230,11 @@ def click( self.__shadow_click(selector, timeout) return element = page_actions.wait_for_element_visible( - self.driver, selector, by, timeout=timeout + self.driver, + selector, + by, + timeout=timeout, + original_selector=original_selector, ) self.__demo_mode_highlight_if_active(original_selector, original_by) if scroll and not self.demo_mode and not self.slow_mode: @@ -280,7 +284,11 @@ def click( self.wait_for_ready_state_complete() time.sleep(0.16) element = page_actions.wait_for_element_visible( - self.driver, selector, by, timeout=timeout + self.driver, + selector, + by, + timeout=timeout, + original_selector=original_selector, ) try: self.__scroll_to_element(element, selector, by) @@ -297,7 +305,11 @@ def click( self.wait_for_ready_state_complete() time.sleep(0.1) element = page_actions.wait_for_element_visible( - self.driver, selector, by, timeout=timeout + self.driver, + selector, + by, + timeout=timeout, + original_selector=original_selector, ) href = None new_tab = False @@ -344,7 +356,11 @@ def click( except Exception: # One more attempt to click on the element element = page_actions.wait_for_element_visible( - self.driver, selector, by, timeout=timeout + self.driver, + selector, + by, + timeout=timeout, + original_selector=original_selector, ) element.click() latest_window_count = len(self.driver.window_handles) @@ -410,7 +426,11 @@ def double_click(self, selector, by=By.CSS_SELECTOR, timeout=None): original_by = by selector, by = self.__recalculate_selector(selector, by) element = page_actions.wait_for_element_visible( - self.driver, selector, by, timeout=timeout + self.driver, + selector, + by, + timeout=timeout, + original_selector=original_selector, ) self.__demo_mode_highlight_if_active(original_selector, original_by) if not self.demo_mode and not self.slow_mode: @@ -418,7 +438,11 @@ def double_click(self, selector, by=By.CSS_SELECTOR, timeout=None): self.wait_for_ready_state_complete() # Find the element one more time in case scrolling hid it element = page_actions.wait_for_element_visible( - self.driver, selector, by, timeout=timeout + self.driver, + selector, + by, + timeout=timeout, + original_selector=original_selector, ) pre_action_url = self.driver.current_url try: @@ -1906,7 +1930,7 @@ def hover_on_element(self, selector, by=By.CSS_SELECTOR): selector = self.convert_to_css_selector(selector, By.XPATH) by = By.CSS_SELECTOR self.wait_for_element_visible( - selector, by=by, timeout=settings.SMALL_TIMEOUT + original_selector, by=original_by, timeout=settings.SMALL_TIMEOUT ) self.__demo_mode_highlight_if_active(original_selector, original_by) self.scroll_to(selector, by=by) @@ -1971,7 +1995,7 @@ def hover_and_click( click_selector, click_by ) dropdown_element = self.wait_for_element_visible( - hover_selector, by=hover_by, timeout=timeout + original_selector, by=original_by, timeout=timeout ) self.__demo_mode_highlight_if_active(original_selector, original_by) self.scroll_to(hover_selector, by=hover_by) @@ -2073,7 +2097,7 @@ def hover_and_double_click( click_selector, click_by ) dropdown_element = self.wait_for_element_visible( - hover_selector, by=hover_by, timeout=timeout + original_selector, by=original_by, timeout=timeout ) self.__demo_mode_highlight_if_active(original_selector, original_by) self.scroll_to(hover_selector, by=hover_by) @@ -4421,9 +4445,11 @@ def slow_scroll_to(self, selector, by=By.CSS_SELECTOR, timeout=None): timeout = settings.SMALL_TIMEOUT if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT: timeout = self.__get_new_timeout(timeout) + original_selector = selector + original_by = by selector, by = self.__recalculate_selector(selector, by) element = self.wait_for_element_visible( - selector, by=by, timeout=timeout + original_selector, by=original_by, timeout=timeout ) try: scroll_distance = js_utils.get_scroll_distance_to_element( @@ -4437,7 +4463,7 @@ def slow_scroll_to(self, selector, by=By.CSS_SELECTOR, timeout=None): self.wait_for_ready_state_complete() time.sleep(0.12) element = self.wait_for_element_visible( - selector, by=by, timeout=timeout + original_selector, by=original_by, timeout=timeout ) self.__slow_scroll_to_element(element) @@ -6798,11 +6824,16 @@ def wait_for_element_visible( timeout = settings.LARGE_TIMEOUT if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT: timeout = self.__get_new_timeout(timeout) + original_selector = selector selector, by = self.__recalculate_selector(selector, by) if self.__is_shadow_selector(selector): return self.__wait_for_shadow_element_visible(selector, timeout) return page_actions.wait_for_element_visible( - self.driver, selector, by, timeout + self.driver, + selector, + by, + timeout=timeout, + original_selector=original_selector, ) def wait_for_element_not_present( @@ -6819,9 +6850,14 @@ def wait_for_element_not_present( timeout = settings.LARGE_TIMEOUT if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT: timeout = self.__get_new_timeout(timeout) + original_selector = selector selector, by = self.__recalculate_selector(selector, by) return page_actions.wait_for_element_absent( - self.driver, selector, by, timeout + self.driver, + selector, + by, + timeout=timeout, + original_selector=original_selector, ) def assert_element_not_present( @@ -9230,11 +9266,16 @@ def wait_for_element_present( timeout = settings.LARGE_TIMEOUT if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT: timeout = self.__get_new_timeout(timeout) + original_selector = selector selector, by = self.__recalculate_selector(selector, by) if self.__is_shadow_selector(selector): return self.__wait_for_shadow_element_present(selector, timeout) return page_actions.wait_for_element_present( - self.driver, selector, by, timeout + self.driver, + selector, + by, + timeout=timeout, + original_selector=original_selector, ) def wait_for_element(self, selector, by=By.CSS_SELECTOR, timeout=None): @@ -9801,9 +9842,14 @@ def wait_for_element_absent( timeout = settings.LARGE_TIMEOUT if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT: timeout = self.__get_new_timeout(timeout) + original_selector = selector selector, by = self.__recalculate_selector(selector, by) return page_actions.wait_for_element_absent( - self.driver, selector, by, timeout + self.driver, + selector, + by, + timeout=timeout, + original_selector=original_selector, ) def assert_element_absent( @@ -9837,9 +9883,14 @@ def wait_for_element_not_visible( timeout = settings.LARGE_TIMEOUT if self.timeout_multiplier and timeout == settings.LARGE_TIMEOUT: timeout = self.__get_new_timeout(timeout) + original_selector = selector selector, by = self.__recalculate_selector(selector, by) return page_actions.wait_for_element_not_visible( - self.driver, selector, by, timeout + self.driver, + selector, + by, + timeout=timeout, + original_selector=original_selector, ) def assert_element_not_visible( diff --git a/seleniumbase/fixtures/page_actions.py b/seleniumbase/fixtures/page_actions.py index dae2d2b4b0f..d811a816d09 100755 --- a/seleniumbase/fixtures/page_actions.py +++ b/seleniumbase/fixtures/page_actions.py @@ -279,7 +279,11 @@ def hover_element_and_double_click( def wait_for_element_present( - driver, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT + driver, + selector, + by=By.CSS_SELECTOR, + timeout=settings.LARGE_TIMEOUT, + original_selector=None, ): """ Searches for the specified element by the given selector. Returns the @@ -291,6 +295,7 @@ def wait_for_element_present( selector - the locator for identifying the page element (required) by - the type of selector being used (Default: By.CSS_SELECTOR) timeout - the time to wait for elements in seconds + original_selector - handle pre-converted ":contains(TEXT)" selector @Returns A web element object """ @@ -311,16 +316,28 @@ def wait_for_element_present( if timeout == 1: plural = "" if not element: + if ( + original_selector + and ":contains(" in original_selector + and "contains(." in selector + ): + selector = original_selector message = "Element {%s} was not present after %s second%s!" % ( selector, timeout, plural, ) timeout_exception(NoSuchElementException, message) + else: + return element def wait_for_element_visible( - driver, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT + driver, + selector, + by=By.CSS_SELECTOR, + timeout=settings.LARGE_TIMEOUT, + original_selector=None, ): """ Searches for the specified element by the given selector. Returns the @@ -334,6 +351,7 @@ def wait_for_element_visible( selector - the locator for identifying the page element (required) by - the type of selector being used (Default: By.CSS_SELECTOR) timeout - the time to wait for elements in seconds + original_selector - handle pre-converted ":contains(TEXT)" selector @Returns A web element object """ @@ -360,6 +378,12 @@ def wait_for_element_visible( if timeout == 1: plural = "" if not element and by != By.LINK_TEXT: + if ( + original_selector + and ":contains(" in original_selector + and "contains(." in selector + ): + selector = original_selector if not is_present: # The element does not exist in the HTML message = "Element {%s} was not present after %s second%s!" % ( @@ -375,13 +399,15 @@ def wait_for_element_visible( plural, ) timeout_exception(ElementNotVisibleException, message) - if not element and by == By.LINK_TEXT: + elif not element and by == By.LINK_TEXT: message = "Link text {%s} was not visible after %s second%s!" % ( selector, timeout, plural, ) timeout_exception(ElementNotVisibleException, message) + else: + return element def wait_for_text_visible( @@ -406,6 +432,7 @@ def wait_for_text_visible( selector - the locator for identifying the page element (required) by - the type of selector being used (Default: By.CSS_SELECTOR) timeout - the time to wait for elements in seconds + browser - used to handle a special edge case when using Safari @Returns A web element object that contains the text searched for """ @@ -456,6 +483,8 @@ def wait_for_text_visible( % (text, selector, timeout, plural) ) timeout_exception(ElementNotVisibleException, message) + else: + return element def wait_for_exact_text_visible( @@ -480,6 +509,7 @@ def wait_for_exact_text_visible( selector - the locator for identifying the page element (required) by - the type of selector being used (Default: By.CSS_SELECTOR) timeout - the time to wait for elements in seconds + browser - used to handle a special edge case when using Safari @Returns A web element object that contains the text searched for """ @@ -532,6 +562,8 @@ def wait_for_exact_text_visible( "after %s second%s!" % (text, selector, timeout, plural) ) timeout_exception(ElementNotVisibleException, message) + else: + return element def wait_for_attribute( @@ -618,10 +650,16 @@ def wait_for_attribute( % (value, attribute, selector, timeout, plural, found_value) ) timeout_exception(NoSuchAttributeException, message) + else: + return element def wait_for_element_absent( - driver, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT + driver, + selector, + by=By.CSS_SELECTOR, + timeout=settings.LARGE_TIMEOUT, + original_selector=None, ): """ Searches for the specified element by the given selector. @@ -632,6 +670,7 @@ def wait_for_element_absent( selector - the locator for identifying the page element (required) by - the type of selector being used (Default: By.CSS_SELECTOR) timeout - the time to wait for elements in seconds + original_selector - handle pre-converted ":contains(TEXT)" selector """ start_ms = time.time() * 1000.0 stop_ms = start_ms + (timeout * 1000.0) @@ -648,6 +687,12 @@ def wait_for_element_absent( plural = "s" if timeout == 1: plural = "" + if ( + original_selector + and ":contains(" in original_selector + and "contains(." in selector + ): + selector = original_selector message = "Element {%s} was still present after %s second%s!" % ( selector, timeout, @@ -657,7 +702,11 @@ def wait_for_element_absent( def wait_for_element_not_visible( - driver, selector, by=By.CSS_SELECTOR, timeout=settings.LARGE_TIMEOUT + driver, + selector, + by=By.CSS_SELECTOR, + timeout=settings.LARGE_TIMEOUT, + original_selector=None, ): """ Searches for the specified element by the given selector. @@ -668,6 +717,7 @@ def wait_for_element_not_visible( selector - the locator for identifying the page element (required) by - the type of selector being used (Default: By.CSS_SELECTOR) timeout - the time to wait for the element in seconds + original_selector - handle pre-converted ":contains(TEXT)" selector """ start_ms = time.time() * 1000.0 stop_ms = start_ms + (timeout * 1000.0) @@ -687,6 +737,12 @@ def wait_for_element_not_visible( plural = "s" if timeout == 1: plural = "" + if ( + original_selector + and ":contains(" in original_selector + and "contains(." in selector + ): + selector = original_selector message = "Element {%s} was still visible after %s second%s!" % ( selector, timeout, From bc3ec123b96fc78210f45801a6f04139c1fffc71 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Mon, 18 Apr 2022 01:28:14 -0400 Subject: [PATCH 3/4] Update example tests --- examples/hack_the_planet.py | 7 ------- examples/offline_examples/test_demo_page.py | 6 +++++- examples/proxy_test.py | 4 ++-- examples/pure_python.py | 8 ++++++++ examples/test_iframes.py | 8 ++++++-- 5 files changed, 21 insertions(+), 12 deletions(-) create mode 100755 examples/pure_python.py diff --git a/examples/hack_the_planet.py b/examples/hack_the_planet.py index 6e5d56b34aa..cd0133c4047 100755 --- a/examples/hack_the_planet.py +++ b/examples/hack_the_planet.py @@ -1,16 +1,9 @@ """ Video Link: https://youtu.be/1s-Tj65AKZA """ -from seleniumbase import __version__ from seleniumbase import BaseCase class HackTests(BaseCase): def test_all_your_base_are_belong_to_us(self): - # First make sure that seleniumbase 1.65.0 or newer is installed - version = __version__.split(".") - if version[0] == "1" and int(version[1]) < 65: - raise Exception( - "This test requires minimum seleniumbase version: 1.65.0" - ) self.set_window_size(1220, 740) ayb = "ALL YOUR BASE" abtu = "ARE BELONG TO US" diff --git a/examples/offline_examples/test_demo_page.py b/examples/offline_examples/test_demo_page.py index fde4d7ba310..862410e1116 100755 --- a/examples/offline_examples/test_demo_page.py +++ b/examples/offline_examples/test_demo_page.py @@ -27,7 +27,11 @@ def test_demo_page(self): # Verify that a hover dropdown link changes page text self.assert_text("Automation Practice", "h3") - self.hover_and_click("#myDropdown", "#dropOption2") + try: + self.hover_and_click("#myDropdown", "#dropOption2", timeout=1) + except Exception: + # If someone moves the mouse while the test runs + self.js_click("#dropOption2") self.assert_text("Link Two Selected", "h3") # Verify that a button click changes text on the page diff --git a/examples/proxy_test.py b/examples/proxy_test.py index 9e16087523b..17f372ed92b 100755 --- a/examples/proxy_test.py +++ b/examples/proxy_test.py @@ -4,10 +4,10 @@ class ProxyTests(BaseCase): def test_proxy(self): self.open("https://ipinfo.io/") - ip_address = self.get_text("div.home-ip-details span.value")[1:-1] + ip_address = self.get_text('#ip-string span[class*="primary"] span') print("\n\nMy IP Address = %s\n" % ip_address) print("Displaying Host Info:") - text = self.get_text("div.home-ip-details").split("asn:")[0] + text = self.get_text("#widget-scrollable-container").split("asn:")[0] rows = text.split("\n") data = [] for row in rows: diff --git a/examples/pure_python.py b/examples/pure_python.py new file mode 100755 index 00000000000..857b5a2b5a7 --- /dev/null +++ b/examples/pure_python.py @@ -0,0 +1,8 @@ +"""Running tests with pure "python" instead of directly calling "pytest". +To run, use: "python pure_python.py". +Two examples: pytest.main() and subprocess.call().""" +import pytest +import subprocess + +pytest.main(["test_mfa_login.py", "--chrome", "-v"]) +subprocess.call(["pytest", "test_mfa_login.py", "--chrome", "-v"]) diff --git a/examples/test_iframes.py b/examples/test_iframes.py index 88249cfb29f..b8a94bd9b9c 100644 --- a/examples/test_iframes.py +++ b/examples/test_iframes.py @@ -8,7 +8,11 @@ def test_iframe_basics(self): self.assert_text("HTML Iframes", "h2") self.switch_to_frame('[title*="Iframe"]') # Enter iframe inside iframe self.assert_text("This page is displayed in an iframe", "h1") - self.switch_to_default_content() # Exit all iFrames + self.switch_to_parent_frame() # Exit only the inner iframe + self.assert_text("Use CSS width & height to specify", "p") + self.switch_to_frame('[title*="Iframe"]') # Enter iframe inside iframe + self.assert_text("seleniumbase.io/w3schools/iframes", "a") + self.switch_to_default_content() # Exit all iframes self.click("button#runbtn") self.switch_to_frame("iframeResult") # Go back inside 1st iframe self.highlight('iframe[title="Iframe Example"]') @@ -20,7 +24,7 @@ def test_set_content_to_frame(self): self.set_content_to_frame("iframe") self.assert_element_not_visible("iframe") self.highlight("body") - self.set_content_to_default(nested=False) + self.set_content_to_parent() self.highlight('iframe[title="Iframe Example"]') self.set_content_to_default() self.click("button#runbtn") From a6aab8c6617334fb0018b06ca6835e164b1a711e Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Mon, 18 Apr 2022 01:29:41 -0400 Subject: [PATCH 4/4] Version 2.4.34 --- seleniumbase/__version__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seleniumbase/__version__.py b/seleniumbase/__version__.py index 45b0e36f111..213886d8975 100755 --- a/seleniumbase/__version__.py +++ b/seleniumbase/__version__.py @@ -1,2 +1,2 @@ # seleniumbase package -__version__ = "2.4.33" +__version__ = "2.4.34"