How can I wait for a condition?

2019-01-16 07:36发布

I'm new on protractor, and I'm trying to implement an e2e test. I don't know if this is the right way to do this, but... The page that I want to test is not a full angular page based, so... I'm having some trouble.

On my first spec I have:

describe('should open contact page', function() {
var ptor = protractor.getInstance();

beforeEach(function(){

   var Login = require('./util/Login');
   new Login(ptor);
});

I have created this Login class, but after login I want to open the contact page, but protractor immediately try to find element before the page is fully loaded.

I've tried to use:

browser.driver.wait(function() {

    expect(browser.findElement(by.xpath("//a[@href='#/contacts']")).isDisplayed());
    ptor.findElement(by.xpath("//a[@href='#/contacts']")).click();

});

But it doesn't work... it always try to find the element before the page loads. I tried this one too:

browser.driver.wait(function() {
    expect(ptor.isElementPresent(by.xpath("//a[@href='#/contacts']")));          
    ptor.findElement(by.xpath("//a[@href='#/contacts']")).click();
});

I'm able to do that using browser.sleep(); but I don't think that is a good option. Any idea? On my login class I have:

ptor.ignoreSynchronization = true;

How can I wait for this @href='#/contacts before protractor tries to click on it?

8条回答
走好不送
2楼-- · 2019-01-16 07:39

Thanks to answers above, this was my simplified and updated usage

function waitFor (selector) {
  return browser.wait(function () {
    return browser.isElementPresent(by.css(selector));
  }, 50000);
}
查看更多
劫难
3楼-- · 2019-01-16 07:45
browser.driver.wait(function() {
    return browser.driver.isElementPresent(by.xpath("//a[@href='#/contacts']"));
});

This works for me too (without the timeout param)..

for more information, see http://angular.github.io/protractor/#/api?view=webdriver.WebDriver.prototype.wait

查看更多
Emotional °昔
4楼-- · 2019-01-16 07:56

I finally find out...

   var waitLoading = by.css('#loading.loader-state-hidden');

   browser.wait(function() {
       return ptor.isElementPresent(waitLoading);
   }, 8000);

   expect(ptor.isElementPresent(waitLoading)).toBeTruthy();

   var openContact = by.xpath("//a[@href='#/contacts']");
   element(openContact).click();

With this protractor could wait for that element until it loading page disappears. Thanks for those who tried to help XD.

查看更多
ら.Afraid
5楼-- · 2019-01-16 07:56

Best way to use wait conditions in protractor that helps to show proper error message to particular element if test case failed

const EC = ExpectedConditions;
const ele = element(by.xpath(your xpath));

return browser.wait(EC.visibilityOf(ele),9000,'element not found').then(() => {
            ele.click();
         });
查看更多
Emotional °昔
6楼-- · 2019-01-16 07:58

I'm surprised that nobody has added this solution. Basically, if you are using modal dialogues you often get an element visible and available to click but not being clickable due to the modal dialogue being in front of it. This happens because protractor moves faster than angular and is ready to click the next element while angular is still closing the modal.

I suggest using

public async clickElementBug(elementLocator: Locator) {
const elem = await element(elementLocator);
await browser.wait(
  async function() {
    try {
      await elem.click();
      return true;
    } catch (error) {
      return false;
    }
  },
  this.TIMEOUT_MILLIS,
  'Clicking of element failed: ' + elem
);

}

查看更多
7楼-- · 2019-01-16 08:01

Protractor 1.7.0 has also introduced a new feature: Expected Conditions.

There are several predefined conditions to explicitly wait for. In case you want to wait for an element to become present:

var EC = protractor.ExpectedConditions;

var e = element(by.id('xyz'));
browser.wait(EC.presenceOf(e), 10000);

expect(e.isPresent()).toBeTruthy();

See also:

查看更多
登录 后发表回答