Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wait for a page to load or element to be present when using Protractor for a non-Angular page

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();
   });
});
like image 268
gppanter Avatar asked Aug 11 '14 17:08

gppanter


People also ask

How do you wait for page to load in Protractor?

pageLoadTimeout() method in protractor waits for an page to load within given time limit when we use get() or navigate().to() method to load a webpage.

How does a Protractor handle non angular pages?

Protractor works well on non-AngularJS pages as well. The first step is to set browser. ignoreSynchronization = true; inside the beforeEach() block in the spec file, to signal Protractor not to wait for Angular components to load.

How do you handle a Protractor wait?

Instead use ExpectedConditions in order to with Protractor. This means, it will wait up to 3500 ms, until the element is rendered. If the element is rendered within 1000ms, it will skip the rest of 2500 waiting ms. Therefore, you saved 2500ms.

How do you stop a page from loading on a Protractor?

How do you stop Page Loading in Protractor when an element is loaded? By using Key. ESC to body element in Protractor.


3 Answers

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();
like image 105
Leo Gallucci Avatar answered Nov 14 '22 22:11

Leo Gallucci


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);
    });
});
like image 23
gppanter Avatar answered Nov 14 '22 21:11

gppanter


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

like image 33
Rajive Pai Avatar answered Nov 14 '22 20:11

Rajive Pai