8

I am writing a test where I want to verify that an element is NOT present on a page (displayed or otherwise). I've read in various articles (like this one) how to do the element detection with a list that's empty or not. That works just fine for the opposite test that verifies the elements ARE present. However, when the element is not present, I am consistently getting a WebDriverException timeout after 60 secs of spinning: See screenshot here

The element detection function is as such:

public bool isButtonPresent(string buttonType)
    {
        switch (buttonType)
        {
            case "Button 1":
                return !(Driver.FindElements(By.Id("Button 1 ID Here")).Count == 0);
            case "Button 2":
                return !(Driver.FindElements(By.Id("Button 2 ID Here")).Count == 0);
            case "Button 3":
                return !(Driver.FindElements(By.Id("Button 3 ID Here")).Count == 0);
        }
        return false;
    }

Thank you for your time!

Community
  • 1
  • 1
Elininja
  • 185
  • 1
  • 2
  • 4
  • By the way, I'm running Selenium 2.53.1 – Elininja Oct 25 '16 at 16:49
  • 5
    It seems that the implicit wait is activated. Turn it off before calling `FindElements`: `driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromMilliseconds(0));` – Florent B. Oct 25 '16 at 17:07
  • 1
    That worked like a charm Florent, thank you! If you could put this solution in an answer I'd be happy to mark it. Also, if you have a more detailed explanation of why this works, that'd be great to include for me and other future viewers. – Elininja Oct 25 '16 at 18:33
  • I think some code is breaking the functionality. I had a similar problem here http://stackoverflow.com/questions/31437515/selenium-stops-to-work-after-call-findelements – Striter Alfa Oct 25 '16 at 20:35

5 Answers5

7

Here are the options:
Option 1:

// Specify the amount of time the driver should wait when searching for an element if it is not immediately present. Specify this time to 0 to move ahead if element is not found.
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(0));  
// InvisibilityOfElementLocated will check that an element is either invisible or not present on the DOM.
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(byLocator));  

With this approach, if your next action is to click on any element, sometimes you will get an error (org.openqa.selenium.WebDriverException: Element is not clickable at point (411, 675)) with Chrome browser. it works fine with Firefox.

Option 2:

// Set the implicit timeout to 0 as we did in option 1
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(0));  
WebDriverWait wait = new WebDriverWait(Driver.Browser, new TimeSpan(0, 0, 15));
try
{
   wait.Until(FindElement(By));
}
catch(WebDriverException ex) // Catch the WebDriverException here
{
   return;
}  

Here we are making implicit wait to 0 and finding element. if element is is not present it will try for next 15 seconds (you can change this number by your convenience). if there is time out, complete the function.

Option 3:

Sudeepthi has already suggested it.

Drivers._driverInstance.FindElement(by).Displayed;
CSharp
  • 1,573
  • 2
  • 14
  • 25
3

Will something like this work?

public static bool IsElementPresent(By by)
{
    try
    {
       bool b = Drivers._driverInstance.FindElement(by).Displayed;
       return b;
    }
    catch
    {
       return false;
    }
}
Sudeepthi
  • 494
  • 4
  • 20
  • Thanks Sudeepthi, that's passing my test now. :) The problem is, this means that the WebDriver is spinning for a minute for each button before the exception is caught. So, the test takes 4 minutes when the positive case only takes ~40 seconds. I'm still looking for a way to make the more efficient approach work. – Elininja Oct 25 '16 at 16:47
2

Forget the ExpectedConditions and the WebDriverWait -- both don't work really well.

  1. If you have a ImplicitWait, the WebDriverWait is completely ignored. So you can not set the default timeout over ImplicitWait to 10 seconds and then create a WebDriverWait instance with 1 second only to check, if a element is present
  2. WebDriverWait ignores the IgnoreExceptionTypes = WebDriverTimeoutException, so you need allways a try catch

With the following approach you have a simple and comfortable solution that works with a minimum of code:

using System.Linq;

#Decrease the timeout to 1 second
   Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(1);

#FindElements get an array and Linq take the first or null
   var result = Driver.FindElements(By.TagName("h7")).FirstOrDefault();

#Increase the timeout to 10 second
   Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);

The result will be the desired IWebElement or Null

Unfortunately the getter to get the current value from ImplicitWait is not implemented since 2016. So you can only reset the value to a fixed value and not dynamically read it before.

Andreas Karz
  • 390
  • 3
  • 6
  • I am no longer at the job that I asked this question for so the best I can do is an upvote for the helpful info. Thanks Andreas! – Elininja Nov 13 '18 at 14:01
0

another solution would be use an explicit wait. In Java (pseudo-code; you'd have to translate) something like this would work:

wait.until(ExpectedConditions.not(ExpectedConditions.invisibilityOfElementLocated(by)), 10, 1000)

that will wait until the element appears on the page, polling every second for ten seconds.

ddavison
  • 28,221
  • 15
  • 85
  • 110
0

In javascript, it's :

driver.manage().timeouts().implicitlyWait(10);
Sacha Durand
  • 473
  • 1
  • 5
  • 11
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). – Emmanuel Ponnudurai Sep 04 '21 at 04:22