element not interactable exception in selenium web automation
Asked Answered
M

13

44

In the below code i cannot send password keys in the password field, i tried clicking the field, clearing the field and sending the keys. But now working in any of the method. But its working if i debug and test

  public class TestMail {
   protected static WebDriver driver;

   protected static String result;

   @BeforeClass

   public static void setup()  {
              System.setProperty("webdriver.gecko.driver","D:\\geckodriver.exe");

   driver = new FirefoxDriver();

   driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);

  }

   @Test

 void Testcase1() {

   driver.get("http://mail.google.com");

   WebElement loginfield = driver.findElement(By.name("Email"));
   if(loginfield.isDisplayed()){
       loginfield.sendKeys("[email protected]");
   }
   else{
  WebElement newloginfield = driver.findElemnt(By.cssSelector("#identifierId"));                                      
       newloginfield.sendKeys("[email protected]");
      // System.out.println("This is new login");
   }


    driver.findElement(By.name("signIn")).click();

  // driver.findElement(By.cssSelector(".RveJvd")).click();

   driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
 // WebElement pwd = driver.findElement(By.name("Passwd"));
  WebElement pwd = driver.findElement(By.cssSelector("#Passwd"));

  pwd.click();
  pwd.clear();
 // pwd.sendKeys("123");
 if(pwd.isEnabled()){
     pwd.sendKeys("123");
 }
 else{
     System.out.println("Not Enabled");
 }
Murry answered 19/7, 2017 at 7:32 Comment(0)
E
26

Try setting an implicit wait of maybe 10 seconds.

gmail.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

Or set an explicit wait. An explicit waits is code you define to wait for a certain condition to occur before proceeding further in the code. In your case, it is the visibility of the password input field. (Thanks to ainlolcat's comment)

WebDriver gmail= new ChromeDriver();
gmail.get("https://www.gmail.co.in"); 
gmail.findElement(By.id("Email")).sendKeys("abcd");
gmail.findElement(By.id("next")).click();
WebDriverWait wait = new WebDriverWait(gmail, 10);
WebElement element = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.id("Passwd")));
gmail.findElement(By.id("Passwd")).sendKeys("xyz");

Explanation: The reason selenium can't find the element is because the id of the password input field is initially Passwd-hidden. After you click on the "Next" button, Google first verifies the email address entered and then shows the password input field (by changing the id from Passwd-hidden to Passwd). So, when the password field is still hidden (i.e. Google is still verifying the email id), your webdriver starts searching for the password input field with id Passwd which is still hidden. And hence, an exception is thrown.

Emmy answered 19/7, 2017 at 8:23 Comment(0)
O
29

"element not interactable" error can mean two things :

a. Element has not properly rendered:

Solution for this is just to use implicit /explicit wait

  • Implicit wait :

    driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);

  • Explicit wait :

    WebDriverWait wait=new WebDriverWait(driver, 20); element1 = wait.until(ExpectedConditions.elementToBeClickable(By.className("fa-stack-1x")));

b. Element has rendered but it is not in the visible part of the screen:

Solution is just to scroll till the element. Based on the version of Selenium it can be handled in different ways but I will provide a solution that works in all versions :

    JavascriptExecutor executor = (JavascriptExecutor) driver;
    executor.executeScript("arguments[0].scrollIntoView(true);", element1);
  1. Suppose all this fails then another way is to again make use of Javascript executor as following :

    executor.executeScript("arguments[0].click();", element1);

  2. If you still can't click , then it could again mean two things :

1. Iframe

Check the DOM to see if the element you are inspecting lives in any frame. If that is true then you would need to switch to this frame before attempting any operation.

    driver.switchTo().frame("a077aa5e"); //switching the frame by ID
    System.out.println("********We are switching to the iframe*******");
    driver.findElement(By.xpath("html/body/a/img")).click();

2. New tab

If a new tab has opened up and the element exists on it then you again need to code something like below to switch to it before attempting operation.

String parent = driver.getWindowHandle();
driver.findElement(By.partialLinkText("Continue")).click();
Set<String> s = driver.getWindowHandles();
// Now iterate using Iterator
Iterator<String> I1 = s.iterator();
while (I1.hasNext()) {
String child_window = I1.next();
if (!parent.equals(child_window)) {
    driver.switchTo().window(child_window);
    element1.click() 
}
Overstuffed answered 11/5, 2021 at 1:47 Comment(0)
E
26

Try setting an implicit wait of maybe 10 seconds.

gmail.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

Or set an explicit wait. An explicit waits is code you define to wait for a certain condition to occur before proceeding further in the code. In your case, it is the visibility of the password input field. (Thanks to ainlolcat's comment)

WebDriver gmail= new ChromeDriver();
gmail.get("https://www.gmail.co.in"); 
gmail.findElement(By.id("Email")).sendKeys("abcd");
gmail.findElement(By.id("next")).click();
WebDriverWait wait = new WebDriverWait(gmail, 10);
WebElement element = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.id("Passwd")));
gmail.findElement(By.id("Passwd")).sendKeys("xyz");

Explanation: The reason selenium can't find the element is because the id of the password input field is initially Passwd-hidden. After you click on the "Next" button, Google first verifies the email address entered and then shows the password input field (by changing the id from Passwd-hidden to Passwd). So, when the password field is still hidden (i.e. Google is still verifying the email id), your webdriver starts searching for the password input field with id Passwd which is still hidden. And hence, an exception is thrown.

Emmy answered 19/7, 2017 at 8:23 Comment(0)
A
7

you may also try full xpath, I had a similar issue where I had to click on an element which has a property javascript onclick function. the full xpath method worked and no interactable exception was thrown.

Amp answered 21/5, 2020 at 20:26 Comment(1)
I had the same experience. Though it would be really nice to understand why..Crowning
S
5

Please try selecting the password field like this.

    WebDriverWait wait = new WebDriverWait(driver, 10);
    WebElement passwordElement = wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#Passwd")));
    passwordElement.click();
  passwordElement.clear();
     passwordElement.sendKeys("123");
Stockman answered 19/7, 2017 at 7:49 Comment(0)
R
3

In my case the element that generated the Exception was a button belonging to a form. I replaced

WebElement btnLogin = driver.findElement(By.cssSelector("button"));
btnLogin.click();

with

btnLogin.submit();

My environment was chromedriver windows 10

Resendez answered 6/9, 2020 at 20:8 Comment(0)
F
1

In my case, I'm using python-selenium. I have two instructions. The second instruction wasn't able to execute. I put a time.sleep(1) between two instructions and I'm done.

If you want you can change the sleep amount according to your need.

Feeney answered 10/4, 2022 at 18:58 Comment(0)
A
1

In my case, query wasn't specific enough. There were multiple elements on a page with the same attributes so the first element that was found wasn't the one I needed. As a result, the "element not interactable" error was correct since I was trying to click wrong element. I ended up finding ids for all the "identical" elements and grabbing the nth one instead of the first one. That would explain why some people say that using xpath worked for them.

Note: I'm using Clojure and Etaoin library that is a wrapper around Selenium so terminology might not match

See simplified examples below.

Buggy code that throws "element not interactable" error:

(let [submit-button-query {:tag :button :fn/has-class "submit-yes"}
      submit-button-element (query driver submit-button-query)] 
       (click-el driver submit-button-element))  

Working code:

(let [submit-button-query {:tag :button :fn/has-class "submit-yes"}   ;; query that I assumed was unique and matched the button I was interested in but, in fact, there were multiple elements with that class. I didnt realize it because I was using query fn that only returns the first match. Below Im using query-all fn to find all matches first
      all-submit-button-elements (query-all driver submit-button-query)
      pop-up-submit-button-element (last all-submit-button-elements)] ;; my case was simple and I could safely assume that the button I need is the last one from the list of matches 
   (click-el driver pop-up-submit-button-element))                    ;; successful click 
Arguseyed answered 5/7, 2023 at 18:32 Comment(2)
Add a code example, please.Cleora
@Cleora Just updated my answerArguseyed
T
0

I had the same problem and then figured out the cause. I was trying to type in a span tag instead of an input tag. My XPath was written with a span tag, which was a wrong thing to do. I reviewed the Html for the element and found the problem. All I then did was to find the input tag which happens to be a child element. You can only type in an input field if your XPath is created with an input tagname

Tracheostomy answered 22/7, 2019 at 11:39 Comment(0)
I
0

I'm going to hedge this answer with this: I know it's crap.. and there's got to be a better way. (See above answers) But I tried all the suggestions here and still got nill. Ended up chasing errors, ripping the code to bits. Then I tried this:

import keyboard    
keyboard.press_and_release('tab')
keyboard.press_and_release('tab')
keyboard.press_and_release('tab') #repeat as needed
keyboard.press_and_release('space') 

It's pretty insufferable and you've got to make sure that you don't lose focus otherwise you'll just be tabbing and spacing on the wrong thing.

My assumption on why the other methods didn't work for me is that I'm trying to click on something the developers didn't want a bot clicking on. So I'm not clicking on it!

Isometric answered 9/12, 2020 at 22:53 Comment(0)
E
0

I got this error because I was using a wrong CSS selector with the Selenium WebDriver Node.js function By.css().

You can check if your selector is correct by using it in the web console of your web browser (Ctrl+Shift+K shortcut), with the JavaScript function document.querySelectorAll().

Elinorelinore answered 31/12, 2020 at 19:13 Comment(0)
B
0

If it's working in the debug, then wait must be the proper solution.
I will suggest to use the explicit wait, as given below:

WebDriverWait wait = new WebDriverWait(new ChromeDriver(), 5);
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#Passwd")));
Biblical answered 1/1, 2021 at 11:49 Comment(0)
E
0

I came across this error too. I thought it might have been because the field was not visible. I tried the scroll solution above and although the field became visible in the controlled browser session I still got the exception. The solution I am committing looks similar to below. It looks like the event can bubble to the contained input field and the end result is the Selected property becomes true.

The field appears in my page something like this.

<label>
  <input name="generic" type="checkbox" ... >
<label>

The generic working code looks more or less like this:

var checkbox = driver.FindElement(By.Name("generic"), mustBeVisible: false);
checkbox.Selected.Should().BeFalse();
var label = checkbox.FindElement(By.XPath(".."));
label.Click();
checkbox.Selected.Should().BeTrue();

You'll need to translate this to your specific language. I'm using C# and FluentAssertions. This solution worked for me with Chrome 94 and Selenium 3.141.0.

Exorable answered 13/9, 2021 at 12:42 Comment(0)
T
0

I had to hover over the element first for the sub-elements to appear. I didn't take that into account at first.

    WebElement boardMenu = this.driver.findElement(By.linkText(boardTitle));
    Actions action = new Actions(this.driver);

    action.moveToElement(boardMenu).perform();

Another tip is to check that you are having one element of that DOM. Try using Ctrl+F when inspecting the web page and check your xpath there; it should return one element if you are going with the findElement method.

Tripod answered 27/9, 2022 at 19:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.