0

I goggled this issue but could not find a better answer, so... posting it here.

I click on a button in the browser, which opens up a form/div (which is generated dynamically). The form/div element does not exist until I press button.

Now, I am trying to check whether form/div element is existing or not. I tried with the below code. But it works when an element exists and throws exception (first method - timeout and for second, driver gets stopped) when the element does not exists.

Method 1:

 ReadOnlyCollection<IWebElement> elements = Utility.Browser.FindElements(By.TagName("div")); // Utility.Browser is the browser instance.

 var expElement = from e in elements
                  where e.GetAttribute("id").Contains("element id")
                  select e;

  return expElement.Count() > 0;

and Method 2:

 string script = string.Format("return document.getElementById('{0}')", attValue);
 IJavaScriptExecutor js = (IJavaScriptExecutor)Utility.Browser; // Utility.Browser is the browser instance.
 var ele = js.ExecuteScript(script);

 return ele != null;

Any help would be highly appreciated.

Thanks.

3
  • Why don't you use a try catch block around the FindElements() part, if it throws an exception the element does not exits and you may return Commented Apr 8, 2015 at 2:57
  • Yes, I added those statements in try-catch block, but for method 1, the next FindElement() method also returns timeout exception (though the element exists). For method 2, since the driver gets stopped, cant move ahead. Commented Apr 8, 2015 at 3:15
  • May be you can write a method to CheckIfElementExists(), and call that method with everytime Commented Apr 8, 2015 at 3:25

4 Answers 4

2

Look into WebDriverWait. You can define a wait function that will wait a specific amount of time to satisfy a specific condition. You can essentially say "wait for ten seconds for the element to appear". I'm on my phone and the exact syntax may be incorrect but it would look something like the following.

pulic bool ElementExist(IWebDriver driver)
{
 var value = false;

 var objWait = new WebDriverWait(driver, Timespan.FromMilliseconds(10000));
 objWait.IgnoreExceptionTypes(typeof(WebDriverTimeoutException));
 value = objWait.Until(b=>b.FindElements(By.TagName("div")).Count > 0);

 return value;
}

You can specify which types of exceptions to ignore, such as ElementNotFound and StaleElement, and the function will continue to wait if those occur. You can also define a function and pass that as a parameter to the .Until function. My skills in lamda expressions and inline function definitions are lacking, otherwise I would give a better example but that is definitely the most customizable approach.

Sign up to request clarification or add additional context in comments.

1 Comment

+1, especially for highlighting IgnoreExceptionTypes - this allows for fine grained exclusions of known likely errors
2

similarly to the other two answers already here, I fashion my test using an extension method along the lines of:

public static bool ElementExists(this IWebDriver driver, By condition, TimeSpan? timeSpan)
{
    bool isElementPresent = false;

    if (timeSpan == null)
    {
        // default to 15 seconds if timespan parameter is not passed in
        timeSpan = TimeSpan.FromMilliseconds(15000);
    }

    var driverWait = new WebDriverWait(driver, (TimeSpan)timeSpan);
    driverWait.IgnoreExceptionTypes(typeof(WebDriverTimeoutException));
    isElementPresent = driverWait.Until(x => x.FindElements(condition).Any());

    return isElementPresent;
}

I then use this in code as such:

var isElementPresent = _driver.ElementExists(By.ClassName("register"), TimeSpan.FromSeconds(90.00));
if (isElementPresent)
{
    // do required processing...
}

Hope this helps

[edit] - you could of course refactor the extension method to return the required element, with a default of null if you wanted to do everything in a single action.

public static IWebElement FindElementAfterWait(this IWebDriver driver, By condition)
{
    bool isElementPresent = false;
    IWebElement singleElement = null;

    var driverWait = new WebDriverWait(driver, TimeSpan.FromSeconds(90));
    driverWait.IgnoreExceptionTypes(typeof(WebDriverTimeoutException));
    isElementPresent = driverWait.Until(x => x.FindElement(condition) != null);

    if (isElementPresent)
    {
        singleElement = driver.FindElement(condition);
    }

    return singleElement;
}

usage:

_driver.FindElementAfterWait(By.ClassName("register"));

also:

public static IWebElement FindElementAfterWait(this IWebDriver driver, Func<IWebDriver, IWebElement> condition)
{
    IWebElement singleElement = null;

    var driverWait = new WebDriverWait(driver, TimeSpan.FromSeconds(90));
    driverWait.IgnoreExceptionTypes(typeof(WebDriverTimeoutException));
    singleElement = driverWait.Until(condition);

    return singleElement;
}

usage:

_driver.FindElementAfterWait(ExpectedConditions.ElementIsVisible(By.Id("firstName")))

enjoy...

Comments

1

The following function helps me to test the existence of an element on a page in C# Selenium code:

public static bool IsElementPresent(this IWebDriver driver, By by) { return driver.FindElements(by).Count > 0; }

Please let me know if it helps you!

1 Comment

+1 this is exactly how i do it myself (i.e. using an extension method). I then use my version along the lines of: var isElementPresent = _driver.ElementExists(By.ClassName("register"), TimeSpan.FromSeconds(90.00));
0

Following method is the one that I always use, and trust me really does what it says. It will return true if the specified element is displayed else it will return false. You can use it like : IsElementDisplayedByXpathVariableWait("Xpath_Of_The_Element",5);

5 is the number of times it will check if the element is displayed with a pause of 1 sec after every check.

public static bool IsElementDisplayedByXpathVariableWait(string xpath, int iterations)
    {
bool returnVal = false;   
        int tracker = 0;
        while (tracker < iterations)
        {
            try
            {
                tracker++;
                IWebElement pageObject = _driver.FindElement(By.XPath(xpath));
                if (pageObject.Displayed)
                {
                    returnVal = true;
                    break;
                }
            }
            catch (Exception e)
            {                   
                Wait(1000);
                continue;
            }
        }           
        return returnVal;
}

4 Comments

IMHO, this stresses the event chain unneccesarily (having to try/catch errors inside the while loop). it feels a little fragile to me also. I'm certain that the WebDriverWait object encapsulates a more robust logic for dealing with the presence and absence within the DOM. That said, it's always good to see alternative approaches.
@jimtollan, I agree this is kind of fragile. But as far as my knowledge is concerned WebDriverWait doesn't have anything like that to check the visibility(Explicit waits do work). But won't do the task which @Sham is looking. He directly wants to check if an element is displayed. This can do the work. try{ IWebElement pageObject = _driver.FindElement(By.Id(id)); if (pageObject.Displayed) { // Do your task } } catch(){}
hi ram - there actually is a delegate that can be passed into the WebDriverWait along the lines of one of my examples below which does this quite nicely: _driver.FindElementAfterWait(ExpectedConditions.ElementIsVisible(By.Id("firstName"))). As i said, my comment wasn't a criticism per-se, purely an observation. Hopefully the knowledge of this delegate will help you with other parts of your own code :-)
@jimtollan, I never considered your comment as a criticism :-) I was glad that someone pointed out my mistake to help me out in improving my code. I will definitely go ahead and find out about your suggestion and try to implement the delegate which you suggested. Thank you :-) Will get back to you if I find some issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.