Daniel
Daniel

Reputation: 5381

cant enter credentials using selenium

Im trying to log into a website using selenium by doing:

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("https://www.eco-visio.net/v5/")
username = driver.find_element_by_id("login-username")
username.send_keys("midregcog.admin")

but im getting the following error

ElementNotInteractableException           Traceback (most recent call last)
<ipython-input-9-975030640535> in <module>()
      8 driver.get("https://www.eco-visio.net/v5/")
      9 username = driver.find_element_by_id("login-username")
---> 10 username.send_keys("midregcog.admin")
     11 

C:\Anaconda2\lib\site-packages\selenium\webdriver\remote\webelement.pyc in send_keys(self, *value)
    477         self._execute(Command.SEND_KEYS_TO_ELEMENT,
    478                       {'text': "".join(keys_to_typing(value)),
--> 479                        'value': keys_to_typing(value)})
    480 
    481     # RenderedWebElement Items

C:\Anaconda2\lib\site-packages\selenium\webdriver\remote\webelement.pyc in _execute(self, command, params)
    631             params = {}
    632         params['id'] = self._id
--> 633         return self._parent.execute(command, params)
    634 
    635     def find_element(self, by=By.ID, value=None):

C:\Anaconda2\lib\site-packages\selenium\webdriver\remote\webdriver.pyc in execute(self, driver_command, params)
    319         response = self.command_executor.execute(driver_command, params)
    320         if response:
--> 321             self.error_handler.check_response(response)
    322             response['value'] = self._unwrap_value(
    323                 response.get('value', None))

C:\Anaconda2\lib\site-packages\selenium\webdriver\remote\errorhandler.pyc in check_response(self, response)
    240                 alert_text = value['alert'].get('text')
    241             raise exception_class(message, screen, stacktrace, alert_text)
--> 242         raise exception_class(message, screen, stacktrace)
    243 
    244     def _value_or_default(self, obj, key, default):

ElementNotInteractableException: Message: element not interactable
  (Session info: chrome=74.0.3729.131)
  (Driver info: chromedriver=74.0.3729.6 (255758eccf3d244491b8a1317aa76e1ce10d57e9-refs/branch-heads/3729@{#29}),platform=Windows NT 10.0.17134 x86_64)

Here is the id tag of the website im trying to get. enter image description here

Upvotes: 2

Views: 650

Answers (2)

Reedinationer
Reedinationer

Reputation: 5774

As explained here, you need to artificially click the element with javascript since it is being made by javascript itself (selenium cannot "see" the element). Another example of a similar situation is my answer on this question. Adjusting your code like this works (I implemented waits too, but that probably isn't necessary):

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

driver = webdriver.Chrome()
driver.get("https://www.eco-visio.net/v5/")
username_element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//form/div/input[@id='login-username']")))# driver.find_element_by_id("login-username")

driver.execute_script("arguments[0].click();", username_element)
time.sleep(1) # give the click a moment to register
action = action_chains.ActionChains(driver)
action.send_keys("midregcog.admin")
action.perform()

This works to fill in the field on my machine! Hope this helps.

update

@MarcelWilson points out that you just need to wait for the page to load (not entirely sure why since it is , and with a couple tests I'm not sure why it doesn't work with just an explicit wait. Apparently the first answer was overly complicated and you can accomplish the desired effect with:

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

driver = webdriver.Chrome()
driver.get("https://www.eco-visio.net/v5/")
username_element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//form/div/input[@id='login-username']")))# driver.find_element_by_id("login-username")
time.sleep(2) # give a longer wait than the explicit wait in the previous line
username_element.click()
username_element.send_keys("username")
password_element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//form/div/input[@id='login-password'][@type='password']")))# driver.find_element_by_id("login-username")
password_element.click()
password_element.send_keys("password")

I think this may be because in the javascript that generates the page (and I'm no javascript expert) there are lines such as if: loaded() which leads me to believe that the explicit WebDriverWait is getting the element, but the javascript is still in the process of loading it in. So the WebDriverWait makes sure the element exists, and the time.sleep(2) makes sure it is also loaded before trying to interact with it, at which point it looks like you can interact with it as a normal page without problems. I even got to learn some new stuff for this post XD!

Upvotes: 2

Marcel Wilson
Marcel Wilson

Reputation: 4572

The problem is selenium is trying to interact with the element before it's finished loading in the DOM. One way around this is to use the WebDriverWait in conjunction with the expected_conditions module to "look" for the elements and then interacting with them.

Try something like this.

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

driver = webdriver.Chrome()
driver.get("https://www.eco-visio.net/v5/")
wait = WebDriverWait(driver, 10)
ec = EC.visibility_of_element_located((By.ID, "login-username"))
try:
    username = wait.until(ec, f"Could not find {ec.locator}")
    username.send_keys("midregcog.admin")
except Exception as exc:
    raise
finally:
    driver.quit()

Upvotes: 1

Related Questions