Skip to content

Commit af1ca96

Browse files
authored
Merge pull request #462 from seleniumbase/update-iframe-switching-methods
Optimize methods for switching into iframes
2 parents 969eea9 + e6e1cf8 commit af1ca96

File tree

5 files changed

+62
-18
lines changed

5 files changed

+62
-18
lines changed

examples/test_double_click.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,18 @@
33

44
class MyTestClass(BaseCase):
55

6-
def test_double_click(self):
6+
def test_double_click_and_switch_to_frame(self):
77
self.open("https://www.w3schools.com/jsref"
88
"/tryit.asp?filename=tryjsref_ondblclick")
9-
self.switch_to_frame("iframeResult")
9+
self.ad_block()
10+
self.switch_to_frame("#iframeResult")
11+
self.double_click('[ondblclick="myFunction()"]')
12+
self.assert_text("Hello World", "#demo")
13+
14+
def test_double_click_and_switch_to_frame_of_element(self):
15+
self.open("https://www.w3schools.com/jsref"
16+
"/tryit.asp?filename=tryjsref_ondblclick")
17+
self.ad_block()
18+
self.switch_to_frame_of_element('[ondblclick="myFunction()"]')
1019
self.double_click('[ondblclick="myFunction()"]')
1120
self.assert_text("Hello World", "#demo")

requirements.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ requests==2.22.0
1212
selenium==3.141.0
1313
pluggy>=0.13.1
1414
attrs>=19.3.0
15-
pytest>=4.6.8;python_version<"3"
15+
pytest>=4.6.9;python_version<"3"
1616
pytest>=5.3.2;python_version>="3"
1717
pytest-cov>=2.8.1
1818
pytest-forked>=1.1.3
@@ -29,7 +29,7 @@ beautifulsoup4==4.8.2
2929
atomicwrites==1.3.0
3030
portalocker==1.5.2
3131
cryptography==2.8
32-
asn1crypto==1.2.0
32+
asn1crypto==1.3.0
3333
pyopenssl==19.1.0
3434
pygments==2.5.2
3535
colorama==0.4.3
@@ -41,4 +41,5 @@ cffi>=1.13.2
4141
tqdm>=4.41.1
4242
flake8==3.7.9
4343
certifi>=2019.11.28
44-
pdfminer.six==20191110
44+
pdfminer.six==20191110;python_version<"3.5"
45+
pdfminer.six==20200104;python_version>="3.5"

seleniumbase/fixtures/base_case.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,7 @@ def is_element_in_an_iframe(self, selector, by=By.CSS_SELECTOR):
10611061
return False
10621062

10631063
def switch_to_frame_of_element(self, selector, by=By.CSS_SELECTOR):
1064-
""" Set driver control to the iframe of the element (assuming the
1064+
""" Set driver control to the iframe containing element (assuming the
10651065
element is in a single-nested iframe) and returns the iframe name.
10661066
If element is not in an iframe, returns None, and nothing happens.
10671067
May not work if multiple iframes are nested within each other. """
@@ -1076,13 +1076,26 @@ def switch_to_frame_of_element(self, selector, by=By.CSS_SELECTOR):
10761076
iframe_identifier = iframe['name']
10771077
elif iframe.has_attr('id') and len(iframe['id']) > 0:
10781078
iframe_identifier = iframe['id']
1079+
elif iframe.has_attr('class') and len(iframe['class']) > 0:
1080+
iframe_class = " ".join(iframe["class"])
1081+
iframe_identifier = '[class="%s"]' % iframe_class
10791082
else:
10801083
continue
1081-
self.switch_to_frame(iframe_identifier)
1082-
if self.is_element_present(selector, by=by):
1083-
return iframe_identifier
1084+
try:
1085+
self.switch_to_frame(iframe_identifier, timeout=1)
1086+
if self.is_element_present(selector, by=by):
1087+
return iframe_identifier
1088+
except Exception:
1089+
pass
10841090
self.switch_to_default_content()
1085-
return None
1091+
try:
1092+
self.switch_to_frame(selector, timeout=1)
1093+
return selector
1094+
except Exception:
1095+
if self.is_element_present(selector, by=by):
1096+
return ""
1097+
raise Exception("Could not switch to iframe containing "
1098+
"element {%s}!" % selector)
10861099

10871100
def hover_on_element(self, selector, by=By.CSS_SELECTOR):
10881101
selector, by = self.__recalculate_selector(selector, by)
@@ -1310,7 +1323,13 @@ def maximize_window(self):
13101323
self.__demo_mode_pause_if_active()
13111324

13121325
def switch_to_frame(self, frame, timeout=None):
1313-
""" Sets driver control to the specified browser frame. """
1326+
"""
1327+
Wait for an iframe to appear, and switch to it. This should be
1328+
usable as a drop-in replacement for driver.switch_to.frame().
1329+
@Params
1330+
frame - the frame element, name, id, index, or selector
1331+
timeout - the time to wait for the alert in seconds
1332+
"""
13141333
if not timeout:
13151334
timeout = settings.SMALL_TIMEOUT
13161335
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:

seleniumbase/fixtures/page_actions.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
from selenium.webdriver.remote.errorhandler import NoSuchWindowException
3434
from seleniumbase.config import settings
3535
from seleniumbase.core import log_helper
36+
from seleniumbase.fixtures import page_utils
3637

3738

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

605606
def switch_to_frame(driver, frame, timeout=settings.SMALL_TIMEOUT):
606607
"""
607-
Wait for an iframe to appear, and switch to it. This should be usable
608-
as a drop-in replacement for driver.switch_to.frame().
608+
Wait for an iframe to appear, and switch to it. This should be
609+
usable as a drop-in replacement for driver.switch_to.frame().
609610
@Params
610611
driver - the webdriver object (required)
611-
frame - the frame element, name, or index
612+
frame - the frame element, name, id, index, or selector
612613
timeout - the time to wait for the alert in seconds
613614
"""
614615
start_ms = time.time() * 1000.0
@@ -618,6 +619,19 @@ def switch_to_frame(driver, frame, timeout=settings.SMALL_TIMEOUT):
618619
driver.switch_to.frame(frame)
619620
return True
620621
except NoSuchFrameException:
622+
if type(frame) is str:
623+
by = None
624+
if page_utils.is_xpath_selector(frame):
625+
by = By.XPATH
626+
else:
627+
by = By.CSS_SELECTOR
628+
if is_element_visible(driver, frame, by=by):
629+
try:
630+
element = driver.find_element(by=by, value=frame)
631+
driver.switch_to.frame(element)
632+
return True
633+
except Exception:
634+
pass
621635
now_ms = time.time() * 1000.0
622636
if now_ms >= stop_ms:
623637
break

setup.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545

4646
setup(
4747
name='seleniumbase',
48-
version='1.34.11',
48+
version='1.34.12',
4949
description='Fast, Easy, and Reliable Browser Automation & Testing.',
5050
long_description=long_description,
5151
long_description_content_type='text/markdown',
@@ -95,7 +95,7 @@
9595
'selenium==3.141.0',
9696
'pluggy>=0.13.1',
9797
'attrs>=19.3.0',
98-
'pytest>=4.6.8;python_version<"3"', # For Python 2 compatibility
98+
'pytest>=4.6.9;python_version<"3"', # For Python 2 compatibility
9999
'pytest>=5.3.2;python_version>="3"',
100100
'pytest-cov>=2.8.1',
101101
'pytest-forked>=1.1.3',
@@ -112,7 +112,7 @@
112112
'atomicwrites==1.3.0',
113113
'portalocker==1.5.2',
114114
'cryptography==2.8',
115-
'asn1crypto==1.2.0',
115+
'asn1crypto==1.3.0',
116116
'pyopenssl==19.1.0',
117117
'pygments>=2.5.2',
118118
'colorama==0.4.3',
@@ -124,7 +124,8 @@
124124
'tqdm>=4.41.1',
125125
'flake8==3.7.9',
126126
'certifi>=2019.11.28',
127-
'pdfminer.six==20191110',
127+
'pdfminer.six==20191110;python_version<"3.5"',
128+
'pdfminer.six==20200104;python_version>="3.5"',
128129
],
129130
packages=[
130131
'seleniumbase',

0 commit comments

Comments
 (0)