Bernard Polman
Bernard Polman

Reputation: 855

Selenium - Wait time for checking that element doesn't exist is too long

I have a an explicit wait time set for webdriver:

WebDriverWait wait = new WebDriverWait(_driver, new TimeSpan(0, 0, 8));

And I have a situation where a loader element is blocking a button so I wait for the loader element to disappear:

wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.InvisibilityOfElementLocated(By.XPath(".//*[contains(@class, 'block-ui-wrapper')]")));
btnMenuAdministration.Click();

The problem is that loader element is only present for 1 or 2 seconds and the test still waits full 8 seconds before clicking the button. I tried using 'ElementToBeClickable' but I get an exception that button is not clickable.

Any suggestions?

Upvotes: 1

Views: 934

Answers (1)

Asyranok
Asyranok

Reputation: 985

        public static void WaitUntil(this IWebDriver driver, Func<bool> Condition, float timeout = 10f)
    {

        float timer = timeout;
        while (!Condition.Invoke() && timer > 0f) {

            System.Threading.Thread.Sleep(500);
            timer -= 0.5f;

        }
        System.Threading.Thread.Sleep(500);

    }

driver.WaitUntil(() => driver.FindElements(By.XPath(".//*[contains(@class, 'block-ui-wrapper')]").Length == 0);

I have a class of extensions where I do a bunch of custom Selenium operations. I find that the implicit waiting causes me more trouble than it is worth. And I find explicit selenium waiting can get a bit verbose, and it isn't everything I want in my framework, so I've made a good number of extensions. Here is one of them. Note, I use the FindElements for the example above because I do not want an exception thrown if nothing is found. This should work for you.

Note: You will need to put this in a static class to be functional. Be careful when extending existing classes like this in logic, as it can confuse others when they are trying to determine where the methods are defined.

Here is my full extensions file, via a Github gist. I wrap almost all Selenium functions. I do a good bit of Javascript because JQuery is 100% reliable in finding elements, whereas Selenium's find function has some trouble inside things like IFrames. Additionally, JQuery has an extremely robust, and super-readable way of querying elements in the DOM using any number of locators, whether they be ID, Class, text contains, pseudo selectors etc; all in the same query string! (Lack of pseudo selector support in Selenium css selector can be a limitation) That is why I use it. It is much more readable than xpath, easier to write, and 100% reliable when written correctly. If you do not have JQuery on the tested pages, you can simply inject JQuery's script every time a new page is loaded.

So what I do is I use JQuery to find and generate an explicit XPath to the exact element I want on a page, and then I pass the exact XPath to Selenium's "Find" logic. When you hold Selenium's hand, there are no problems finding elements.

https://gist.github.com/tsibiski/04410e9646ee9ced9f3794266d6c5a82

Upvotes: 1

Related Questions