0

I'm getting an error when I try to switch_to_frame() or switch_to.frame() (btw, which of those is correct?) to an unfriendly iFrame. Should that be supported?

def click_all(driver):
    for img in imgs:
        img.click()
    iframes = driver.find_elements_by_tag_name('iframe')
    for ifr in iframes:
        try:
            driver.switch_to.frame(ifr)
        except:
            e = sys.exc_info()
            print "Error: %s" % str(e) # Gives a vague error: '(<class 'selenium.common.exceptions.WebDriverException'>, WebDriverException(), <traceback object at 0x1102a9680>)'
            return
        click_all(driver)

Thanks for any help!

The stack trace is:

Traceback (most recent call last):
File "/Users/merrigan/working/DockLion/qe-cordell/test/bases/util.py", 
line 45, in click_all
driver.switch_to_window(ifr)
File "/Library/Python/2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 657, in switch_to_window
self._switch_to.window(window_name)
File "/Library/Python/2.7/site-packages/selenium/webdriver/remote/switch_to.py", line 113, in window
self._driver.execute(Command.SWITCH_TO_WINDOW, data)
File "/Library/Python/2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 308, in execute
self.error_handler.check_response(response)
File "/Library/Python/2.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 194, in 
check_response
raise exception_class(message, screen, stacktrace)
WebDriverException: Message: unknown error: 'name' must be a string
(Session info: chrome=65.0.3325.181)
(Driver info: chromedriver=2.33.506106 
(8a06c39c4582fbfbab6966dbb1c38a9173bfb1a2),platform=Mac OS X 10.12.6 x86_64)

(Does this mean it only works if the iFrame has a name attribute?)

Chanda Korat
  • 2,453
  • 2
  • 19
  • 23
Seanonymous
  • 1,304
  • 10
  • 30
  • 1
    depending on which version of selenium you're running, `switch_to_frame` is deprecated. also, please provide the full stacktrace of the exception you are encountering. you'll get the output of it by either removing the `try/except` and letting the console print the exception, or using `traceback` and putting `print traceback.format_exc()` in your `except` block – crookedleaf Apr 03 '18 at 22:44
  • well, based on the stacktrace... it doesn't appear to be matching the code sample you provided. for example, the 4th line of the stacktrace is: `driver.switch_to_window(ifr)`. also, the very last line of your code seems to cause an infinite loop, but i'm guessing this is just a formatting error of your example. – crookedleaf Apr 03 '18 at 23:38

2 Answers2

1

Yes, you can pass a WebElement to the switch_to.frame function and it will work.

ex.

 driver.switch_to.frame(driver.find_element_by_id('id'))

The issue you are having above is caused by this line that is not present in your code above:

self._switch_to.window(window_name)

Which requires a window name or handle, thus causing your error in the Traceback provided.

If you are still having issues, please provide the relevant HTML, so we can help you switch to this frame.


switch_to_frame is now deprecated, please use switch_to for any switching functions.

The documentation on switching between windows and frames is HERE, which refers to switch_to_frame, but the description is still relevant for use purposes.


SIDENOTE

Please update your Chromedriver to at least 2.36 since you are running on Chrome build 65, which is not supported by your current version of Chromedriver 2.33: https://sites.google.com/a/chromium.org/chromedriver/downloads

By keeping these up to date, or on a recommended pair, you will run into less problems as described on the chromedriver download landing page.

PixelEinstein
  • 1,713
  • 1
  • 8
  • 17
  • as you can tell by his code sample, he is passing a `WebElement` to the `switch_to` function, so that's not the problem. the rest of your answer is about his code not matching the traceback, which has already been noted in a comment onto his post. this answer doesn't provide any answer at all and is more suited for a comment. – crookedleaf Apr 04 '18 at 00:53
  • 1
    He is directly asking if it should be supported, so I am indeed answering all of his questions stated. He asks in the bottom as well if it can only be switched by name. If you are unhappy with the answer. Please answer yourself. – PixelEinstein Apr 04 '18 at 01:16
  • you answered the question in his title "can i switch to an unfriendly iframe", in which case, the answer is yes. and a side question about which method is proper. but his question states he has tried both methods and is having an error while trying to do so, which is what he is here trying to get help with. the example you provided is what he is already saying he is trying to do. his traceback, however, shows his code that he is running is not the same he is providing, and that is the problem. so, as said, there isn't a way to provide an answer yet. – crookedleaf Apr 04 '18 at 17:59
  • Thanks, it turns out that updating the Chromedriver got rid of the error. And thanks for the recommendation to use traceback, @crookedleaf. The test framework was hiding stack traces from me, so this is very helpful. – Seanonymous Apr 04 '18 at 19:25
1

While working with frames you need to consider a couple of things as follows :

  • An webpage can have multiple frames.
  • All the frames may not have distinct id, name, class etc attributes.
  • Loading sequence of the frames can differ with respect to the WebElements with which you interact within the Top-Level Browsing Context
  • Some ifames can have the attribute style set to display: none;

Keeping in view the above mentioned usecases you have to figure out the intended <iframe> to which you want to switch. So instead of creating a list through :

iframes = driver.find_elements_by_tag_name('iframe')

Try to locate the exact frame where the intended WebElements are located with which you want to interact through either of the following methods :

driver.switch_to.frame("iframe_name") # By Frame Name
driver.switch_to.frame("iframe_id") # By Frame ID
driver.switch_to.frame(frame_index) # By Frame Index

You can find a detailed discussion in How can I select a html element no matter what frame it is in in selenium?

The API Docs clearly mentions switch_to_frame() method is Deprecated :

switch_to_frame(frame_reference)
Deprecated use driver.switch_to.frame

Use switch_to.frame() instead as follows :

driver.switch_to.frame(frame_reference)

Returns : SwitchTo an object containing all options to switch focus into

Note : For effective frame switching you need to induce WebDriverWait with expected_conditions clause as frame_to_be_available_and_switch_to_it(). You can find a detailed discussion under the subheading A Better Approach to Switch Frames

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352