3

Yesterday I struggled with waiting for a loading indicator to be removed. Added this question and answer here because we spend a lot of time on it and Google didn't help much. Hopefully this will help others in the future. Still if you have a different or better solution to this problem please post your answer.

Situation:

We have a dropdown build with Semantic-UI. When we open the dropdown the dropdown starts loading the data. In the test we need to wait until the dropdown is fully loaded which takes random between 500-2000ms. Then we can process the test to select or retrieve the needed items.

Relevant version from package.json:

"semantic-ui": "^2.2.9",
"semantic-ui-react": "^0.66.0"
"jest": "^19.0.2",
"selenium-webdriver": "^3.3.0",
"chromedriver": "^2.29.0",

Problem:

Normally I would use the until.elementIsNotVisible(element) function to wait for the loading element to be not visible, but Semantic-UI does not remove the element it changes it to a 'V' dropdown-arrow icon by removing the loading class from the element. Thus the element stays visible it is just changed. Also I do not want to add a sleep for 3000ms.

To complicate it even more the loading image is added as content to a ::After CSS part, which cannot be used in CSS or Xpath locators. You cannot check for elements based on it attributes this way.

The best way is to wait for loading class to be removed from the parent div and not check the image.

Question:

How do I detect class changes on elements with plain selenium-webdriver in JavaScript?

1

I have created my own isNotPresent wait-until method which uses a locator so you can check if an element with a certain class is not present anymore. This loops over the locator either until the timeout is reached or no elements with that locator are present.

import webdriver from 'selenium-webdriver';   

export default class Element {
  static defaultTimeOut() { return 30000; }

  // other helper methods ...

  static async isNotPresent(driver, locator) {
    await driver.wait(() => {
      return driver.findElements(locator).then((elements) => {
        if (elements.length <= 0) {
          return true;
        }
        return false;
      });
    }, Element.defaultTimeOut(), 'The element was still present when it should have disappeared.');
  }
}

Example implementation code parts to showcase usage:

import Element from '../Util/WaitForElements';

async waitUntilFiltersLoaded() {
  await Element.isNotPresent(this.driver, By.css('.filterPanel .loading'));
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.