How to wait for a page to load or element to be pr

2019-03-20 14:45发布

I am new to Protractor. I think I have this down when dealing with an Angular page, but can't figure it out for a non-Angular page. Any help would be appreciated.

describe('Search', function() {
   it('should click Search button and wait for results', function() {
      browser.driver.findElement(by.id('search')).click();
   });
});

4条回答
爷、活的狠高调
2楼-- · 2019-03-20 14:59

In protractor there are two types terms for on the page. isPresent ask if the element is exists on the page. isDisplayed asks if the element is visible. If you are waiting for a page to load you need to wait for isDisplayed, but that will error if it is not present, so wait for isPresent first. I use a function to wait for an element.

function waitForElement(el, waitTimeoutMilliseconds){
    return browser.wait(function() { return el.isPresent(); }, waitTimeoutMilliseconds)
        .then(function(){
           return browser.wait(function() { return el.isDisplayed(); }, waitTimeoutMilliseconds);
        });
}

Then just call that function in your test.

describe('Search', function() {
    it('should click Search button and wait for results', function() {
        var el = element(by.id('search'));
        waitForElement(el, 5000);
        el.click();
    });
});
查看更多
我想做一个坏孩纸
3楼-- · 2019-03-20 15:04

Testing non-angular pages with Protractor can be tricky regarding waiting for stuff.

I suggest you upgrade Protractor to latest (1.5.0 as of now), use a custom function waitReady() that browser.wait for elements ready and rewrite your test like below. Note you can put everything within 1 spec if you like so.

// TODO: use page objects
var searchBtnElm = $('#search'); // use element(by.id('search')) if you prefer

it('waits for the elements present and visible (non-angular)', function() {
    expect(searchBtnElm.waitReady()).toBeTruthy();
});

it('should click Search button', function() {
    searchBtnElm.click();
});

it('wait for more results', function() {
    // keep using waitReady() before interacting with the elements
    // and before performing expectations on them
});

More details of why waitReady here.

Note: remember to set ignore synchronization for testing a non-angular page:

    browser.ignoreSynchronization = true;

You can set it before browser.get the non-angular page.

I've suggested setting a high implicit wait in the past, e.g.

browser.manage().timeouts().implicitlyWait(5000);

That hack allows to you avoid waitReady and keep using the standard

expect(searchBtnElm.isPresent()).toBeTruthy();

But has an ugly disadvantage when testing for elements NOT present, i.e. when testing for absent or non visible elements in which case it will wait 5 seconds (5000ms) in vane, e.g. when doing

expect(someNonExistingElm.isPresent()).toBeFalsy();
查看更多
冷血范
4楼-- · 2019-03-20 15:15

Figured this out. I simply added the code below, after the click method:

describe('Search', function() {
   it('should click Search button and wait for results', function() {
        browser.driver.findElement(by.id('search')).click();
        dvr.wait(function() {
            return dvr.isElementPresent(by.xpath(
                '/html/body/div/div[4]/div/div[2]/div/div/div/span'));
        }, 20000);
    });
});
查看更多
仙女界的扛把子
5楼-- · 2019-03-20 15:23

Another Neat approach is to use "Expected Conditions" inside browser.wait - something like this:

var EC = protractor.ExpectedConditions;
var search = element(by.id('search'))
browser.wait(EC.visibilityOf(search), 2000).then(function(){
 search.click()
})

You can get more details here: https://angular.github.io/protractor/#/api?view=ExpectedConditions

查看更多
登录 后发表回答