5

I have the following code for selecting an option from given list and it usually works, but sometimes it fails with NoSuchElement exception on the second if. I was under the impression that if it does not find the element it just goes back to through the loop again. I believe the explanation is pretty simple... Could anyone enlighten me?

    public static void selectFromList(String vList, String vText, IWebDriver driver)
    {
        for (int sec = 0; ; sec++)
        {
            System.Threading.Thread.Sleep(2500);
            if (sec >= 10) Debug.Fail("timeout : " + vList);
            if (driver.FindElement(By.Id(ConfigurationManager.AppSettings[vList])).Displayed) break;
        }
        new SelectElement(driver.FindElement(By.Id(ConfigurationManager.AppSettings[vList]))).SelectByText(vText);
    }
tom
  • 1,223
  • 6
  • 16
  • 26
  • 1
    driver.FindElement will not wait for an element to appear, if it isn't there when the web driver scrapes the page, it will throw an exception, which you are not catching. Jason's answer below will do what you require. – Arran Jun 05 '12 at 21:15
  • FindElement does in fact wait based on the implicit wait time defined on the IWebDriver instance. Check out this [C# solution](http://brantleytec.blogspot.com/2013/08/webdriver-iwebelementexists.html) on how to check if an element exists. – Brantley Blanchard Aug 06 '13 at 17:26

3 Answers3

6

Instead of having to try catch every instance, why not create a helper/extension method to take care of that for you. Here it returns the element or returns null if it doesn't exist. Then you can simply use another extension method for .exists().

IWebElement element = driver.FindElmentSafe(By.Id("the id"));

    /// <summary>
    /// Same as FindElement only returns null when not found instead of an exception.
    /// </summary>
    /// <param name="driver">current browser instance</param>
    /// <param name="by">The search string for finding element</param>
    /// <returns>Returns element or null if not found</returns>
    public static IWebElement FindElementSafe(this IWebDriver driver, By by)
    {
        try
        {
            return driver.FindElement(by);
        }
        catch (NoSuchElementException)
        {
            return null;
        }
    }

bool exists = element.Exists();

    /// <summary>
    /// Requires finding element by FindElementSafe(By).
    /// Returns T/F depending on if element is defined or null.
    /// </summary>
    /// <param name="element">Current element</param>
    /// <returns>Returns T/F depending on if element is defined or null.</returns>
    public static bool Exists(this IWebElement element)
    {
        if (element == null)
        { return false; }
        return true;
    }
Brantley Blanchard
  • 1,208
  • 3
  • 14
  • 23
2

You could try one of the answers from this SO question:

public static IWebElement FindElement(this IWebDriver driver, String vList, String vText, int timeoutInSeconds)
{

    By selector = By.Id(ConfigurationManager.AppSettings[vList])
    if (timeoutInSeconds > 0)
    {
        var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
        return wait.Until(drv => drv.FindElement(selector));
    }
    return driver.FindElement(selector);
}
Community
  • 1
  • 1
Jason Kulatunga
  • 5,814
  • 1
  • 26
  • 50
  • Thanks Jason. Unfortunately I get an error - the name "by" does not exist in the current context – tom Jun 06 '12 at 09:15
  • 1
    I see you have already accepted your answer for this question, but I have edited his answer to fix that error. – Arran Jun 06 '12 at 13:14
  • I added try/catch and it solved my problem, but I will try this solution given the time as it looks neat(er). Thanks for the fix. – tom Jun 11 '12 at 12:45
1

well, I am Java guy, so I will not provide you the code, but rather the algorithm:

  • Yours code (I think) should check, if the element is displayed and if not, wait extra 2,5 secs
  • The reason it fails is, that sometimes it takes more than first 2,5 secs to display the element. In that case, check for if the element is displayed will throw exception

So, basically you should do some exception handling in the for loop and catch this exception and do nothing. In Java its done by try and catch block. But because I dont know C# you will have to find out how its done in this language

Pavel Janicek
  • 14,128
  • 14
  • 53
  • 77