Skip to content

Commit 140d64a

Browse files
committed
Optimize methods for switching into iframes
1 parent 969eea9 commit 140d64a

File tree

2 files changed

+42
-9
lines changed

2 files changed

+42
-9
lines changed

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

0 commit comments

Comments
 (0)