2

So I have a Selenium test that waits for a button to load up before it interacts with it.

As seen in my code, I have implemented it so that the driver will wait 14 seconds (14 is just a random number), or it will move on if the element is located before 14 seconds.

However, even after I have waited for element to load, and I try to interact with it (using Click() method), I get this error showing that the element is not 'interactable'.

The funny thing is, this actually works some times- where the element is indeed interactable- but not other times.

public void TestChromeDriverMinimalWaitTime()
        {
            driver.Navigate().GoToUrl("http://www.google.com");
            //find search bar and enter text
            driver.FindElement(By.Name("q")).SendKeys("Selenium");
            //wait 14 seconds max..
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(14));
            //...unless button element is found
            IWebElement waitUntil = wait.Until(x => x.FindElement(By.Name("btnK")));
            //once found, click the button
            waitUntil.Click();
            //wait 4 secs till this test method ends
            Thread.Sleep(2000);
        }

This is the error that I get: Line 53 is the line that says: waitUntil.Click();

enter image description here

Revised working code based on @DebanjanB's answer:

public void TestChromeDriverMinimalWaitTime()
        {
            driver.Navigate().GoToUrl("http://www.google.com");
            //find search bar and enter text
            driver.FindElement(By.Name("q")).SendKeys("Selenium");
            //wait 14 seconds max..unless button element is found
            IWebElement element = new WebDriverWait(driver, TimeSpan.FromSeconds(14)).Until(ExpectedConditions.ElementToBeClickable(By.Name("btnK")));    
            //click enter
            element.SendKeys(Keys.Return);
            Thread.Sleep(2000);
        }

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
mts396
  • 818
  • 1
  • 11
  • 15

3 Answers3

1

With it working sometimes, it seems like a timing issue. Perhaps the element starts out disabled, and is enabled after some tiny delay, or an event. Try adding a delay just before .Click. You might also check the state of the button element to see if it is disabled.

Thoryn Hawley
  • 335
  • 1
  • 7
  • Thanks @Thoryn, I did think of that but I was wondering whether its good to add a lot of sleep delays within tests. Is this good practice or is it a necessary thing that we just have to do, to wait for elements to load? – mts396 Apr 16 '19 at 17:25
  • Checking state is usually better than a static delay. – Thoryn Hawley Apr 16 '19 at 17:26
1

From you code trials it seems you are trying to invoke click() on the button with text as Google Search on the Google Home Page.

Your approach inducing WebDriverWait was just perfecto. But if you analyze the HTML DOM you will find the locator strategy which you have adapted identifies multiple (two) elements within the DOM Tree. So the locator doesn't identifies the desired element uniquely. While execution the locator identifies the other element which is not visible. Hence you see the error as:

ElementNotVisibleException: element not interactable

Solution

The easiest approach here is, as the search box which you have identified as:

driver.FindElement(By.Name("q")).SendKeys("Selenium");

is within a form, once you send the search text you can use either of the following solutions:

  • Sending Keys.Return as follows:

    IWebElement element = new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.Name("q")));
    element.SendKeys("Selenium");
    element.SendKeys(Keys.Return);
    
  • Sending Keys.Enter as follows:

    IWebElement element = new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.Name("q")));
    element.SendKeys("Selenium");
    element.SendKeys(Keys.Enter);
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • Regarding your solution(s), the first line does not compile as the Click() method returns void, and it would not allow us to convert to IWebElement type – mts396 Apr 17 '19 at 10:11
  • That was my bad, corrected it. Let me know the status. – undetected Selenium Apr 17 '19 at 10:13
  • 1
    Thanks for that, works perfectly (no more funny business, at least for now!). I had actually tried to use the 'ExpectedConditions' method before, but it wasn't being found. I just then found that I had to add a Nuget package 'DotNetSeleniumExtras.WaitHelpers' for the method to work. – mts396 Apr 17 '19 at 10:29
  • Regarding your solution(s), so you're saying that my previous code was not uniquely identifying the specific element all the time? – mts396 Apr 17 '19 at 10:32
  • Can you undo the Nuget package change please, because it doesn't correspond to the original issue in my question. The Nuget package was only mentioned after you included the 'ExpectedConditions' in your answer. – mts396 Apr 17 '19 at 13:19
  • 1
    Thanks a lot for that- all sorted now – mts396 Apr 17 '19 at 13:53
0

You can try to check the visibility of an element in the page using the below code.

public void TestChromeDriverMinimalWaitTime()
        {
            driver.Navigate().GoToUrl("http://www.google.com");
            //find search bar and enter text
            driver.FindElement(By.Name("q")).SendKeys("Selenium");

            //...unless button element is found
           while(!IsElementVisible(driver.FindElement(By.Name("btnK"))){
                  Thread.Sleep(1000);
                  }
            //once found, click the button
            waitUntil.Click();
            //wait 4 secs till this test method ends
            Thread.Sleep(2000);
        }

public bool IsElementVisible(IWebElement element)
{
    return element.Displayed && element.Enabled;
}
Ankur Singh
  • 1,239
  • 1
  • 8
  • 18