Switch - pressing the button triggers the callback earlier than desired

I have a protractor test for a login page that sends credits and checks if the index page is loaded. I am passing a callback function to a click button then

, assuming that the callback will be called after the promise returned by the function click

is resolved.

var protractor = require('protractor')
describe('E2E: main page', function() {
  beforeEach(function() {
    browser.get('http://localhost:8001/login.html/');
  });
  it("login in the portal", function(){
    var d = protractor.promise.defer();
    element(by.model('loginParams.email')).sendKeys('saravana0209@r.com');
    element(by.model('loginParams.password')).sendKeys('password');
    element(by.name('normalLogin')).click().then(function(){
        //it crashes here before selecting the sub menu item
        element(by.xpath('//a[@title="subMenuItem"]')).click()
        console.log("sub-menu item has been chosen in the ribbon")
        setTimeout(function() { d.fulfill('ok')}, 50000)
    })
    expect(d).toBe('ok');
  })
});

      

But the callback is called when a page loads, and it resets the test as element title

, subMenuItem

is still not loaded. Mistake,

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'.

      

+3


source to share


2 answers


You can wait for the submenu to appear before clicking:

var EC = protractor.ExpectedConditions;

element(by.name('normalLogin')).click().then(function() {
    var subMenu = element(by.xpath('//a[@title="subMenuItem"]'));

    browser.wait(EC.visibilityOf(subMenu), 5000);
    subMenu.click();

    console.log("sub-menu item has been chosen in the ribbon");
    setTimeout(function() { d.fulfill('ok')}, 50000);
});

      


Since it looks like all problems come from manual angular bootstraping, you should usebrowser.driver.get()

:

If your page is doing manual loading, then the protractor will not be able to load your page using browser.get. Use the base webdriver instance browser.driver.get instead. This means Protractor doesn't know when your page is fully loaded and you may need to add a wait statement to make sure your tests avoid race conditions.



Which could lead to something like:

element(by.name('normalLogin')).click(); 
browser.sleep(3000); 
browser.driver.get("index.html");

      

Log in, let it log in by running a delay (sleep bad, yeah) and manually get the index page after.


You can also work with disabled sync between protractor and angular by setting browser.ignoreSynchronization = true;

, but this has many drawbacks - you will have to reuse Explicit Expectations ( browser.wait()

). You can try to play around with this flag and temporarily set it to true

before loading the page and return to false

after.

+6


source


Have you tried this ?:

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

      

The protractor runs asynchronously, so



var venueLink = by.xpath('//a[@title="Venues"]')

      

will be executed when

browser.wait(function() {
      return browser.driver.isElementPresent(by.xpath('//a[@title="Venues"]'))
    })

      

+1


source







All Articles