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

2019-03-20 14:33发布

问题:

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();
   });
});

回答1:

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();


回答2:

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);
    });
});


回答3:

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



回答4:

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();
    });
});