Halina
Halina

Reputation: 265

Protractor break while of for loop

I need help with loop beaking.

For my check I did the simple test:

while(i < 10) {
    element(by.xpath("//a[contains(@id, 'ma-apply')]")).isPresent().then(function(result) {
        if(!result) {
            helper.one_page_ahead();
        } else {
            console.log('there is on the page');
            break;
        }
    });
    i++;
};

This code leads to the error.

I tried to follow advice via StackOverflow and changed break to return. But this leads to full loop execution (up to 10).

Here is the output:

[14:17:46] I/launcher - Running 1 instances of WebDriver Started user skills: AJAX there is on the page there is on the page there is on the page there is on the page there is on the page there is on the page there is on the page there is on the page .

1 spec, 0 failures Finished in 37.93 seconds

I tried the same with for loop like

for(i = 0; i < 10; i++) {
    //code
    break;
}

Would be glad to find the answer.

Upvotes: 4

Views: 6011

Answers (4)

rakesh adupa
rakesh adupa

Reputation: 11

i = 10; is not effecting, Still loop iterating

Upvotes: -1

Martin Blaustein
Martin Blaustein

Reputation: 1163

If you want to avoid recursion you could modify the index variable inside the returned promised

while(i < 10) {
element(by.xpath("//a[contains(@id, 'ma-apply')]")).isPresent().then(function(result) {
    if(!result) {
        helper.one_page_ahead();
    } else {
        console.log('there is on the page');
        i = 10;
    }
});
i++;

};

And I would add a browser.sleep(x) in between each repetion to avoid the code to be run before the result from the promise is evaluated.

Upvotes: -1

craig
craig

Reputation: 5016

This is some commentary about why the while statement does not work: When you call isPresent you are returned a webdriver.promise.Promise<boolean>. Since you are in the webdriver control flow, you'll need to throw an error,

      browser.get('http://angularjs.org');
      var i = 0;
      var running = true;
      while(i < 3 && running) {
        console.log('while: ' + running + ' ' + i);
        element(by.model('username')).isPresent().then((result) => {
          console.log('element: ' + running + ' ' + i);

          if (result) {
            // huzzah we found it, so lets break the element after the first test
            browser.get('https://docs.angularjs.org/tutorial');
          } else {
            running = false;
            throw new Error('no username')
          }

        }).catch((err) => {
          console.log(err);
        });
        i++;
      }

This basically prints out:

[19:07:18] I/hosted - Using the selenium server at http://localhost:4444/wd/hub
[19:07:18] I/launcher - Running 1 instances of WebDriver
Started
while: true 0
while: true 1
while: true 2
element: true 3
[Error: no username]
element: false 3
[Error: no username]
element: false 3
[Error: no username]

So basically your while loop queues up items in the control flow to execute. These then will get executed asynchronously in order.

I like the suggestion by Sudharsan Selvaraj to do this recursively.

Upvotes: 2

Sudharsan Selvaraj
Sudharsan Selvaraj

Reputation: 4832

You need to implement a recursive method to achieve what you want, try the below piece of code,

function runTillElementFound(totalCount,currentCount){
  var self = this;
  var _element = element(by.xpath("//a[contains(@id, 'ma-apply')]"));
  if(currentCount < totalCount){
     return _element.isPresent().then(function(isElementPresent){
        if(isElementPresent){
           return;
         }else{
           helper.one_page_ahead();
           self.runTillElementFound(totalCount,currentCount++);
         }
      })
  }else{
     return false; //if element not present after Max count reached.
   }
}

this.runTillElementFound(10,0); //this will execute the method untill the required element found on the page.

Upvotes: 1

Related Questions