Skip to content

Optimize methods for switching into iframes #462

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions examples/test_double_click.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,18 @@

class MyTestClass(BaseCase):

def test_double_click(self):
def test_double_click_and_switch_to_frame(self):
self.open("https://www.w3schools.com/jsref"
"/tryit.asp?filename=tryjsref_ondblclick")
self.switch_to_frame("iframeResult")
self.ad_block()
self.switch_to_frame("#iframeResult")
self.double_click('[ondblclick="myFunction()"]')
self.assert_text("Hello World", "#demo")

def test_double_click_and_switch_to_frame_of_element(self):
self.open("https://www.w3schools.com/jsref"
"/tryit.asp?filename=tryjsref_ondblclick")
self.ad_block()
self.switch_to_frame_of_element('[ondblclick="myFunction()"]')
self.double_click('[ondblclick="myFunction()"]')
self.assert_text("Hello World", "#demo")
7 changes: 4 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ requests==2.22.0
selenium==3.141.0
pluggy>=0.13.1
attrs>=19.3.0
pytest>=4.6.8;python_version<"3"
pytest>=4.6.9;python_version<"3"
pytest>=5.3.2;python_version>="3"
pytest-cov>=2.8.1
pytest-forked>=1.1.3
Expand All @@ -29,7 +29,7 @@ beautifulsoup4==4.8.2
atomicwrites==1.3.0
portalocker==1.5.2
cryptography==2.8
asn1crypto==1.2.0
asn1crypto==1.3.0
pyopenssl==19.1.0
pygments==2.5.2
colorama==0.4.3
Expand All @@ -41,4 +41,5 @@ cffi>=1.13.2
tqdm>=4.41.1
flake8==3.7.9
certifi>=2019.11.28
pdfminer.six==20191110
pdfminer.six==20191110;python_version<"3.5"
pdfminer.six==20200104;python_version>="3.5"
31 changes: 25 additions & 6 deletions seleniumbase/fixtures/base_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -1061,7 +1061,7 @@ def is_element_in_an_iframe(self, selector, by=By.CSS_SELECTOR):
return False

def switch_to_frame_of_element(self, selector, by=By.CSS_SELECTOR):
""" Set driver control to the iframe of the element (assuming the
""" Set driver control to the iframe containing element (assuming the
element is in a single-nested iframe) and returns the iframe name.
If element is not in an iframe, returns None, and nothing happens.
May not work if multiple iframes are nested within each other. """
Expand All @@ -1076,13 +1076,26 @@ def switch_to_frame_of_element(self, selector, by=By.CSS_SELECTOR):
iframe_identifier = iframe['name']
elif iframe.has_attr('id') and len(iframe['id']) > 0:
iframe_identifier = iframe['id']
elif iframe.has_attr('class') and len(iframe['class']) > 0:
iframe_class = " ".join(iframe["class"])
iframe_identifier = '[class="%s"]' % iframe_class
else:
continue
self.switch_to_frame(iframe_identifier)
if self.is_element_present(selector, by=by):
return iframe_identifier
try:
self.switch_to_frame(iframe_identifier, timeout=1)
if self.is_element_present(selector, by=by):
return iframe_identifier
except Exception:
pass
self.switch_to_default_content()
return None
try:
self.switch_to_frame(selector, timeout=1)
return selector
except Exception:
if self.is_element_present(selector, by=by):
return ""
raise Exception("Could not switch to iframe containing "
"element {%s}!" % selector)

def hover_on_element(self, selector, by=By.CSS_SELECTOR):
selector, by = self.__recalculate_selector(selector, by)
Expand Down Expand Up @@ -1310,7 +1323,13 @@ def maximize_window(self):
self.__demo_mode_pause_if_active()

def switch_to_frame(self, frame, timeout=None):
""" Sets driver control to the specified browser frame. """
"""
Wait for an iframe to appear, and switch to it. This should be
usable as a drop-in replacement for driver.switch_to.frame().
@Params
frame - the frame element, name, id, index, or selector
timeout - the time to wait for the alert in seconds
"""
if not timeout:
timeout = settings.SMALL_TIMEOUT
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
Expand Down
20 changes: 17 additions & 3 deletions seleniumbase/fixtures/page_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from selenium.webdriver.remote.errorhandler import NoSuchWindowException
from seleniumbase.config import settings
from seleniumbase.core import log_helper
from seleniumbase.fixtures import page_utils


def is_element_present(driver, selector, by=By.CSS_SELECTOR):
Expand Down Expand Up @@ -604,11 +605,11 @@ def wait_for_and_switch_to_alert(driver, timeout=settings.LARGE_TIMEOUT):

def switch_to_frame(driver, frame, timeout=settings.SMALL_TIMEOUT):
"""
Wait for an iframe to appear, and switch to it. This should be usable
as a drop-in replacement for driver.switch_to.frame().
Wait for an iframe to appear, and switch to it. This should be
usable as a drop-in replacement for driver.switch_to.frame().
@Params
driver - the webdriver object (required)
frame - the frame element, name, or index
frame - the frame element, name, id, index, or selector
timeout - the time to wait for the alert in seconds
"""
start_ms = time.time() * 1000.0
Expand All @@ -618,6 +619,19 @@ def switch_to_frame(driver, frame, timeout=settings.SMALL_TIMEOUT):
driver.switch_to.frame(frame)
return True
except NoSuchFrameException:
if type(frame) is str:
by = None
if page_utils.is_xpath_selector(frame):
by = By.XPATH
else:
by = By.CSS_SELECTOR
if is_element_visible(driver, frame, by=by):
try:
element = driver.find_element(by=by, value=frame)
driver.switch_to.frame(element)
return True
except Exception:
pass
now_ms = time.time() * 1000.0
if now_ms >= stop_ms:
break
Expand Down
9 changes: 5 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@

setup(
name='seleniumbase',
version='1.34.11',
version='1.34.12',
description='Fast, Easy, and Reliable Browser Automation & Testing.',
long_description=long_description,
long_description_content_type='text/markdown',
Expand Down Expand Up @@ -95,7 +95,7 @@
'selenium==3.141.0',
'pluggy>=0.13.1',
'attrs>=19.3.0',
'pytest>=4.6.8;python_version<"3"', # For Python 2 compatibility
'pytest>=4.6.9;python_version<"3"', # For Python 2 compatibility
'pytest>=5.3.2;python_version>="3"',
'pytest-cov>=2.8.1',
'pytest-forked>=1.1.3',
Expand All @@ -112,7 +112,7 @@
'atomicwrites==1.3.0',
'portalocker==1.5.2',
'cryptography==2.8',
'asn1crypto==1.2.0',
'asn1crypto==1.3.0',
'pyopenssl==19.1.0',
'pygments>=2.5.2',
'colorama==0.4.3',
Expand All @@ -124,7 +124,8 @@
'tqdm>=4.41.1',
'flake8==3.7.9',
'certifi>=2019.11.28',
'pdfminer.six==20191110',
'pdfminer.six==20191110;python_version<"3.5"',
'pdfminer.six==20200104;python_version>="3.5"',
],
packages=[
'seleniumbase',
Expand Down