Protractor click element before its appears at the page

205 Views Asked by At

I've been through some problems with my waits in protractor. For example, I am navigating between my pages which has a loading, then I need to click a button. But, sometimes, the button appears before the loading disappear. So protractor click at this button, behind the loading, and the button has no action, because the loading was at the screen. So, How can I use the waits for this situation?

I've been trying:

EC.invisibilityOf(loading)
    .then(() => {
        EC.elementToBeClickable(button)
            .then(() => {
                browser.actions().mouseMove(button).click().perform();
            });
    });
});
3

There are 3 best solutions below

2
Axel Vincent On

Did you tried to make the browser sleep a little before the click ?

browser.sleep(2000);

0
Silvan Bregy On

You should create some helper methods for general waiting. Let's say you would have following function for waiting:

async waitForDisplayed(element: ElementFinder, timeout = 20000): Promise<boolean> {
  try {
     return await browser.wait(element.isDisplayed());
  } catch (error) {
    return false;
  }
}

When assuming you have the above function you are able to wait for elements to be displayed. In combination with a function which checks if the page is still loading this is very useful.

For creating a function which determines if the page is still loading, you will have to search for some element which is displayed when the page is loading or for an element which is displayed as one of the latest. In our test suite we are waiting until spinners are gone.

Example for waiting the page to be loaded:

async function waitForTestability(timeout = 20000): Promise<boolean> {
  let spinner = element(by.css('.spinner'));
  try {
    await browser.wait(async function () { return !await spinner.isDisplayed(); });
    return true;
  } catch (error) {
    return false;
  }
}

Then you can modify your waitForDisplayed() function with the waitForTestability() function so whenever you use waitForDisplayed(), it's first tested if the page is still loading:

async waitForDisplayed(element: ElementFinder, timeout = 20000): Promise<boolean> {
      try {
         await waitForTestability();
         await browser.wait(element.isDisplayed());
         return true
      } catch (error) {
        return false;
      }
    }

cheers!

0
BuruY On

Try waiting for the element with:

static forElementVisible(element) {
    return new Promise<any>(async (resolve) => {
        await browser.driver.wait(ExpectedConditions.visibilityOf(element), 10000,
            `Timed out waiting for element to become visible`).then(() => {
                resolve();
            });
    });
}