1

The following snippet works. If I change the order of the 2 explicit waits it also works. But if I comment out either of the explicit waits, it won't work. But it doesn't fail either; webdriver thinks send_keys() happened but it actually didn't.
Adding time.sleep() also makes it work but that is to be avoided.
The failures are intermittent.
The duration of wait times are definitely long enough.

driver.implicitly_wait(20)
driver.get("https://thirdpartywebsite.com")
WebDriverWait(driver,10).until(cond.visibility_of_element_located((By.ID, "username")))
WebDriverWait(driver,10).until(cond.element_to_be_clickable((By.ID, "username")))
driver.find_element(By.ID, "username").send_keys(username)

So given the above, what actually does clickable and visible mean in the context of send_keys()?
How could it be possible that send_keys() does not throw, but text does not appear?
What would be the proper way to do this with 1 line instead of 2?
Note that the element with ID "username" is a <input>

PizzaBeer
  • 183
  • 14

2 Answers2

0

Clickable checks for visible and not disabled (as in an INPUT button). In your case, it would depend on whether the INPUT that you are sending keys to is ever potentially disabled. If it's never disabled, both will act the same. You might as well just use clickable because it's basically the same thing with an extra check you may or may not ever need.

The docs
EC.element_to_be_clickable
EC.visibility_of_element_located

JeffC
  • 22,180
  • 5
  • 32
  • 55
0

send_keys()

send_keys(*value) simulates typing a value into the element where the value can be a string for typing, or setting form fields. For setting file inputs, this could be a local file path as well. send_keys() works flawless when the element is interactable. However there are three distinct states of a WebElement which can be matched to three distinct expected_conditions.

  • If your usecase is to validate the presence of any element you need to induce WebDriverWait setting the expected_conditions as presence_of_element_located() which is the expectation for checking that an element is present on the DOM of a page. This does not necessarily mean that the element is visible. In these cases your effective line of code will be:

    element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "username")))
    
  • If your usecase is to validate an element attribute, you need to induce WebDriverWait setting the expected_conditions as visibility_of_element_located() which is an expectation for checking that an element is present on the DOM of a page and visible. Visibility here implies that the element is not only displayed but also has a height and width that is greater than 0. In these cases your effective line of code will be:

    element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "username")))
    
  • If your usecase is to interact with any element you need to induce WebDriverWait setting the expected_conditions as element_to_be_clickable() which is an expectation for for checking an element is visible and enabled such that you can click it. In these cases your effective line of code will be:

    element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, "username")))
    

This usecase

In this usecase, as you intend to invoke send_keys() you need to induce WebDriverWait only for the element_to_be_clickable(). So optimizing your entire code block you can use the following single line of code:

driver.get("https://thirdpartywebsite.com")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, "username"))).send_keys(username)

Note: You have to remove the implicitly_wait()

PS: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example setting an implicit wait of 10 seconds and an explicit wait of 15 seconds, could cause a timeout to occur after 20 seconds.

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