0

I am using Selenium with C# to test a Web App. We have an implementation that when a section of a page is loading, we add a class to the div of the section and once the section has been loaded, the div class is removed from the div. For example:

Before

<div class="tabs-container spinner">

After:

<div class="tabs-container">

I am trying to add a Wait until the spinner is removed from the div class. I tried using

wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.InvisibilityOfElementLocated(By.CssSelector("spinner")));

', however, this doesn't work.

Any idea how to handle this case?

KunduK
  • 32,888
  • 5
  • 17
  • 41

4 Answers4

1

Since you are using css selector.Try with .classname

wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.InvisibilityOfElementLocated(By.CssSelector(".spinner")));

Or You can check .spinner class is not present using ElementIsVisible

wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(By.CssSelector("div.tabs-container:not(.spinner)")));
KunduK
  • 32,888
  • 5
  • 17
  • 41
  • You're looking for an invisible .spinner instead of the particular element to not be .spinner. Do you see the difference? – pguardiario Jan 17 '20 at 10:04
  • @pguardiario : Updated the answer with `ElementIsVisible` with .spinner class not present.However 1st option should work as per OP looking after.Thanks. – KunduK Jan 17 '20 at 10:19
0

To wait for the removal of the loader you have to induce WebDriverWait for the InvisibilityOfElementLocated() and you can use either of the following Locator Strategies:

  • CssSelector:

    new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(SeleniumExtras.WaitHelpers.ExpectedConditions.InvisibilityOfElementLocated(By.CssSelector("div.tabs-container.spinner")));
    
  • XPath:

    new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(SeleniumExtras.WaitHelpers.ExpectedConditions.InvisibilityOfElementLocated(By.XPath("//div[@class='tabs-container spinner']")));
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
0

You can write a custom function to wait for change in class attribute like

public static Func<IWebDriver, string> waitForChangeInAttribute(By locator, string attribute, string notValue) {
    return (driver) => {
      try {
          var value = driver.FindElement(locator).GetAttribute(attribute);
          return value == notValue ? null : value;
      }
      catch (NoSuchElementException) {
          return null;
      }
      catch (StaleElementReferenceException) {
          return null;
      }
    };
}

And you use/call like

string valueBefore = driver.FindElement(By.xpath("//div[contains(@class, 'tabs-')]")).GetAttribute(attribute);

wait.Until(waitForChangeInAttribute(By.xpath("//div[contains(@class, 'tabs-')]"), "class", valueBefore));

Note: Please take care of single and double quote as I am typing from Mobile keypad

Muzzamil
  • 2,823
  • 2
  • 11
  • 23
0

You could create a quick hacky method with a while loop.

    ...
    CheckLoaded("div[class*='spinner']", 5);

    public void CheckLoaded(string css, int timeout)
    {
        timeout = timeout * 1000;
        int count=0;
        while(driver.FindElements(By.CssSelector(css) > 0 || count < timeout))
        {
             Thread.Sleep(1000);
        }
    }
marwaha.ks
  • 540
  • 1
  • 7
  • 19