Search code examples
pythonseleniumxpathcss-selectorswebdriverwait

Selenium can't find dynamially loaded input field element even after waiting for that specific element


I'm trying to access an input field of username (of login page) with Selenium. The page is JavaScript based. driver.get() wait by default to load the complete page. In my case, it is unable to load that. I can inspect the element on browser (firefox) and I get this.

<input type="text" autocomplete="username" name="username">

I tried to wait for that specific element with EC.presence_of_element_located.

Code trials:

driver = webdriver.Firefox()
driver.get(url) 
delay = 10 # seconds
try:
    myElem = WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.NAME, 'username')))
    print("Page is ready!")
except TimeoutException:
    print("Loading took too much time!")

print(driver.page_source)

I get Loading took too much time!. Even though the element is there as I can inspect it in the browser. I also tried EC.presence_of_element_located((By.TAG_NAME, 'input'))) but It also can't find the tag.

Update from the comments: url='https://drive.inditex.com/drfrcomr/login'


Solution

  • To interact a clickable element instead of presence_of_element_located() you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:

    • Using NAME:

      myElem = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, "username")))
      
    • Using CSS_SELECTOR:

      myElem = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[name='username']")))
      
    • Using XPATH:

      myElem = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@name='username']")))
      
    • 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
      

    However on accessing the website I find the username field implemented through Windows Authentication

    inditex


    Solution

    Incase of Basic Authentication you need to embed the username and password within the url as follows:

    driver.get("http://username:password@drive.inditex.com/drfrcomr/login")
    

    Update

    Additionally the username field is within nested #shadow-root (open)

    username To send a character sequence to the username field you have to use shadowRoot.querySelector() and you can use the following Locator Strategy:

    • Code Block:

      driver.get("http://username:password@drive.inditex.com/drfrcomr/login")
      time.sleep(10)
      item = driver.execute_script('''return document.querySelector('glyph-splash.hydrated').shadowRoot.querySelector('glyph-login-form.hydrated').shadowRoot.querySelector('input[name="username"]')''')
      item.send_keys("ShaidaMuhammad")