Asked  6 Months ago    Answers:  5   Viewed   25 times

So, I was absolutely baffled as to how to do this in Selenium, and couldn't find the answer anywhere, so I'm sharing my experience.

I was trying to select an iframe and having no luck (or not repeatably anyway). The HTML is:

<iframe id="upload_file_frame" width="100%" height="465px" frameborder="0" framemargin="0" name="upload_file_frame" src="/blah/import/">
<html>
    <body>
        <div class="import_devices">
            <div class="import_type">
                <a class="secondary_button" href="/blah/blah/?source=blah">
                    <div class="import_choice_image">
                        <img alt="blah" src="/public/images/blah/import/blah.png">
                    </div>
                    <div class="import_choice_text">Blah Blah</div>
                </a>
            </div>
        </div>
    </body>
</html>

The Python code (using the selenium library) was trying to find this iframe using this:

    @timed(650)
def test_pedometer(self):
    sel = self.selenium
    ...
    time.sleep(10)
    for i in range(5):
        try:
            if sel.select_frame("css=#upload_file_frame"): break
        except: pass
        time.sleep(10)
    else: self.fail("Cannot find upload_file_frame, the iframe for the device upload image buttons")

Repeated fails with every combination of Selenium commands I could find.

The occasional success would not be reproducible, so perhaps it was some sort of race condition or something? Never did find the right way to get it in selenium proper.

 Answers

12

What finally worked for me was:

        sel.run_script("$('#upload_file_frame').contents().find('img[alt="Humana"]').click();")

Basically, don't use selenium to find the link in the iframe and click on it; use jQuery. Selenium has the capability to run an arbitrary piece of javascript apparently (this is python-selenium, I am guessing the original selenium command is runScript or something), and once I can use jQuery I can do something like this: Selecting a form which is in an iframe using jQuery

Tuesday, June 1, 2021
 
Wookai
answered 6 Months ago
93

The element looks like:

<input class="js-username-field email-input js-initial-focus" type="text" name="session[username_or_email]" autocomplete="on" value="" placeholder="Phone, email or username">

So you could do something like:

email = bot.find_element_by_xpath('//input[@name="session[username_or_email]"]') 
Tuesday, July 27, 2021
 
Lloydworth
answered 4 Months ago
47

As the desired element is within an <iframe> so you have to:

  • Induce WebDriverWait for the desired frame to be available and switch to it.

  • Induce WebDriverWait for the desired element to be clickable.

  • You can use the following xpath based Locator Strategy:

  • Using CSS_SELECTOR:

    # Select the item on main DOM that will udpate the iframe contents
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#sm20"))).click()
    # Don't sleep, but only WedDriverWait...
    WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[value='ifrInterior']")))
    # Select the element inside the iframe and click
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[name='gestionesPropias_Equipo']"))).click()
    
  • Using XPATH:

    # Select the item on main DOM that will udpate the iframe contents
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//*[@id='sm20']"))).click()
    # Don't sleep, but only WedDriverWait...
    WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[@value='ifrInterior']")))
    # Select the element inside the iframe and click
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@name='gestionesPropias_Equipo']"))).click()
    
  • Note : You have to add the following imports :

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    

Reference

You can find a couple of relevant discussions in:

  • Ways to deal with #document under iframe
  • Switch to an iframe through Selenium and python

tl; dr

“NoSuchWindowException: no such window: window was already closed” while switching tabs using Selenium and WebDriver through Python3

Saturday, July 31, 2021
 
Sendy
answered 4 Months ago
55

To make the username field to be visible, you need to move cursor to the login link:

....

driver.get('http://www.etoro.com/au')
action = webdriver.ActionChains(driver)
action.move_to_element(driver.find_element_by_xpath(
    './/a[@class="top-link"]/span[text()="Login"]'
))
action.perform()
# TODO Need to wait until the `inputUsername` field is visible
elem = driver.find_element_by_class_name('inputUsername')
...
Tuesday, August 31, 2021
 
LunaLoveDove
answered 3 Months ago
72

You can't do this with a CSS selector. :eq() is from jQuery and not part of any standard.

td:nth-child(4) span:nth-child(2) means something entirely different, and will only work in very specific situations, such as when there is exactly one table row with four td elements all of which contain at least two span children:

<body>
  ...
  <table>
    <!-- The first, or only, row in the entire document
         with this many cells containing this many spans -->
    <tr>
      <td>
        <span></span>
        <span></span>
      <td>
        <span></span>
        <span></span>
      <td>
        <span></span>
        <span></span>
      <td>
        <span></span>
        <span></span>
  </table>
  ...
</body>

It won't match the element you're looking for in this example, because each tr has only two td children, so td:nth-child(4) will never match:

<body>
  ...
  <table>
    <tr>
      <td>
        <span></span>
        <span></span>
      <td>
        <span></span>
        <span></span>
    <tr>
      <td>
        <span></span>
        <span></span>
      <td>
        <span></span>
        <span></span> <!-- (//td/span[2])[4] -->
  </table>
  ...
</body>

If you know td:nth-child(4) span:nth-child(2) is guaranteed to work in your situation though, feel free to use it.

Wednesday, November 10, 2021
 
EnTee
answered 3 Weeks ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share