protractor: Protractor does not wait for app load after button click

I have an angular application that has a login page, login.html and index page, index.html. I use requireJs to reduce page load time and angularjs in both the pages are manually bootstrapped as,

angular.bootstrap(document, ['loginApp'])  //for login.html
angular.bootstrap(document, ['mainApp'])   //for index.html

Now, i enter the credentials, press submit in login.html page and on success, index.html gets loaded with a delay. Now, i used login button click promise as,

  element(by.name('normalLogin')).click().then(
    function(){
      element(by.xpath('//a[@title="Venues"]')).click()  //this crashes because there is no element with matching xpath
   })

Then i tried,

    element(by.name('normalLogin')).click()
    browser.wait(function() {
      return browser.driver.isElementPresent(by.xpath('//a[@title="Venues"]'))
    })
    var venueLink = by.xpath('//a[@title="Venues"]')
    browser.driver.isElementPresent(venueLink).then(function(){
        console.log("tenant login process successful")
        element(venueLink).click()
    })

This also throws the exception,

Error: Failed: invalid selector: Unable to locate an element with the xpath expression //a[@title="Venues"] because of the following error:
TypeError: Failed to execute 'createNSResolver' on 'Document': parameter 1 is not of type 'Node'.

Protractor is not waiting for the complete page load after login button click causing this issue. How can i instruct protractor to wait until a new angular app gets bootstrapped/loaded completely?

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 24 (8 by maintainers)

Most upvoted comments

Temporary fix to your problem is that put “browser.sleep(5000)” after log-in button click instruction. Browser will sleep for 5 seconds mean time index.html page will be loading completely.

Hope this will help you to fix.

Just a route change is causing issues for me too, when the new route is slow to load/render. I checked by adding some logging (visible through console plugin) to the app main module .run functions, that it’s really really just a route change, the app isn’t created from scratch in a full page reload.

After changing route, first few expectations/actions that find an element fail, with the element not being there, or having a wrong, uninitialized value. I take screenshots for failed specs, sometimes it even shows a not-fully rendered page, e.g. one that has blank space where interpolated Angular variables are supposed to appear! So it definitely has started running stuff without waiting for angular to settle, if it gets as far as taking the screenshot with the page still loading/rendering.

A short-ish browser.sleep works around the issue, as for others. The required time is proportionate to the amount of time it takes to load and render the new route, in this case 500-100ms.

My route is loaded with ui-router $state.go, from a simple synchronous ng-click handler. No setTimeout, event handlers without $scope.$apply, non-$http requests etc usual culprits going on anywhere in this app. Angular sync always on here (browser.ignoreSynchronization = false).

Using protractor 2.5.1 with chromedriver banging Chrome 47, on Windows 10. Node 0.12.6.

@juliemr I’m seeing similar behaviour intermittently with 2.4.0. Can you clarify if it is expected to have to explicitly wait after a command has triggered a view change, before carrying on with commands to elements on the new page.

For example:

// we start on the 'landing' page
it('should go to the dashboard', function () {
    var goToLoginButton = element(by.linkText('LOGIN'));
    goToLoginButton.click();  // triggers a route change

    // should I wait here?
    // until an element from the login page is available?
    // or does element() or sendKeys() wait internally?

    var username = element(by.model('vm.username'));
    var password = element(by.model('vm.password'));
    var loginButton = element(by.buttonText('LOG IN'));

    username.sendKeys('someusername');
    password.sendKeys('somepassword');
    loginButton.click();

    expect(browser.getCurrentUrl()).toContain('#/dashboard');
});

Thanks.

@jskrepnek It is indeed expected to have to wait if a command other than get or refresh causes a page reload. Currently, there is no way for Protractor to know if a click event would cause a page reload, so it’s unable to do the same waiting that occurs with protractor.get.

This is clearly causing confusion, so we should find some good place in the docs to mention it. Does anyone from this thread have suggestions on where in our docs they would look for help with this issue?

if it’s an actual <a> tag, i’ve opted to manually get the href attribute from the element, then just call browser.get(), since browser.get() seems to resolve at the correct time, but .click() resolves too early

linkElement.getAttribute('href')
      .then(function(linkUrl){
        browser.get(linkUrl);
      });

I hate using .then() when protractor is supposed to chain up all the commands properly but eh, it’s a workaround for click() resolving too early

I am also very interested in a response to this. We are waiting after every click even when it is just a route change. It would be nice to get rid of those waits.

I’m seeing similar behavior in my tests. It’s completely maddening because it will sometimes work. I’m testing a non-angular app, so it might be worse for me. browser.waits don’t always wait. It seems to occur more often when using sendKeys. I’m also seeing the next test fail before the previous test’s expect finish. Are expects blocking?

The ONLY thing that seems to work is a strategically placed browser.sleep (say for a few hundred ms). This seems to block just enough to right the flow.

It’s very hard to debug, and to say what’s happening with any certainty, because of the inconsistent behavior.