1

Using Selenium (via Python), I am trying to locate the "Login" button of http://schwab.com. The button is an element of type BUTTON and id='loginSubmitButton'. I am using the following code:

from selenium import webdriver

driver = webdriver.Chrome()
driver.maximize_window()
driver.get("http://schwab.com")
driver.implicitly_wait(10)
driver.find_element_by_id("loginSubmitButton")
driver.close()

The browser correctly opens the page and the button is verifiably there (using Chrome dev tools), however Selenium fails to locate it.

I have tried many variations of this code, including using WebDriverWait, but nothing seems to work.

Suggestions are quite appreciated.

petar
  • 75
  • 5

3 Answers3

3

You are unable to click on that button because login form is under iFrame.

enter image description here

So first you need to switch into iframe, then only you'll be able to access those elements

username_frame = driver.find_element_by_id('LoginComponentForm')
driver.switch_to.frame(username_frame)
driver.find_element_by_id("loginSubmitButton").click()
NarendraR
  • 7,577
  • 10
  • 44
  • 82
2

As the the desired element is within an <iframe> so to invoke click() on the element 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 either of the following Locator Strategies:

    • Using CSS_SELECTOR:

      from selenium import webdriver
      from selenium.webdriver.support.ui import WebDriverWait
      from selenium.webdriver.support import expected_conditions as EC
      from selenium.webdriver.common.by import By
      
      driver = webdriver.Firefox(executable_path=r'C:\Utility\BrowserDrivers\geckodriver.exe')
      driver.get('https://www.schwab.com/')
      WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe#LoginComponentForm")))
      WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "span#LoginText"))).click()
      
    • Using XPATH:

      from selenium import webdriver
      from selenium.webdriver.support.ui import WebDriverWait
      from selenium.webdriver.support import expected_conditions as EC
      from selenium.webdriver.common.by import By
      
      driver = webdriver.Firefox(executable_path=r'C:\Utility\BrowserDrivers\geckodriver.exe')
      driver.get('https://www.schwab.com/')
      WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[@id='LoginComponentForm']")))
      WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//span[@id='LoginText']"))).click()
      

Reference

Here you can find a relevant discussion on Ways to deal with #document under iframe

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

Using find_element_by_xpath is more efficient than using find_element_by_id. You can try using this

Also the login form is displayed on the iframe. You need to switch to the iframe to click the button. and then switch back to the default to be able to click or do actions on other elements outside the frame.

For switching to iframe you can use the following code :

driver.switch_to.frame(iframe)

Then use your click button code here.

For switching back to default content, use this line :

driver.switch_to.default_content()

This should work.

Sridhar Murali
  • 320
  • 1
  • 2
  • 8
  • 1
    Can you elaborate why _find_element_by_xpath is more efficient than find_element_by_id_ ? – NarendraR Mar 02 '20 at 06:30
  • Finding elements using XPath is better for locating elements having complex selectors. Although I missed checking that there is an iframe over there. – Sridhar Murali Mar 02 '20 at 09:20
  • 1
    You still didn't explain how XPath is more efficient than ID. Frankly, if you read up on best practices including listening to the Selenium contributors they will tell you that XPath should be the last locator you should use, if at all. ID should be first, shortly after that CSS selector, and then dead last is XPath. – JeffC Mar 03 '20 at 05:25
  • @JeffC Your comment is misleading and at the same time counter reproductive in learning Selenium. Selenium contributors never suggested to avoid _XPath_ where as at times there are instances where only _xpath_ can be used. You need to read up the documentation carefully. – undetected Selenium Mar 03 '20 at 06:46
  • @DebanjanB My comment is not misleading nor counter productive... it's truth. If you think that Selenium contributors never suggested to avoid XPath then you've clearly never listened to any talks by Selenium contributors. They say it all the time at conferences like SeleniumConf and SauceCon. I know... I've been to the confs and heard their talks first hand. The videos are out on yt... go watch them. I've even linked them to you before so I know you've seen them. – JeffC Mar 03 '20 at 14:36
  • @DebanjanB You will notice that I listed XPath as an option, I just put it last because of the mountain of evidence (much of which comes from Selenium contributors) against using it which I've listed in answers and our past conversations. There are some things that can only be done using XPath but I use it sparingly... only when necessary. – JeffC Mar 03 '20 at 14:39
  • @JeffC It depends on the way a page is developed. I personally find Xpath more efficient than any other type. Using Xpath saves up time for a tester who is writing test cases for a very complex pages with too many nestings. What you said may be true according to the contributors. But for a continuously changing applications. I don't think using id is efficient at all. It is equally debatable on what is efficient. I personally found Xpath to be very efficient where I need not change my locators every now and then when the application changes. – Sridhar Murali Mar 04 '20 at 06:22
  • @SridharMurali There are very, very few things that an XPath can locate that a CSS selector cannot. If there is an element with an ID and you create an XPath that locates that element using the ID then you aren't being more efficient and the locator is slower than By Id. You'd have to give me specific examples of what you think is more efficient with XPath because pretty much all the evidence is against that belief. – JeffC Mar 04 '20 at 14:45