$browser.findelement in a loop

Hi,

I need to test the data from a grid of my application. I created a multidimensional array and initialized it with desired output. Now I want to run a loop based upon this array and want to verify the data of application’s grid in that loop. Here is the code:-

}).then(function(){
    var showdata=
        [
          ["Client 2","8 %"],
          ["Client 3","7 %"],
          ["Client 4","9 %"]
        ];
     var str;
     var r=showdata.length;
     var c=showdata[0].length;

     for(i=0;i<r;i++)
       {
         for(j=0;j<c;j++)
           {
             str="//*[@id='graph-popup-area']/div/div[1]/div/div[1]/table/tbody/tr["+(i+1)+"]/td["+(j+1)+"]";
          $browser.findElement($driver.By.xpath(str)).then(function(element){
             return element.getText().then(function(text){                
          assert.equal(showdata[i][j], text, 'Cell value is not correct');
          });
         });
          
    }
}
  1. I am getting an error “TypeError: Cannot read property ‘2’ of undefined” with above code.
  2. I found out that $browser.findElement function is getting executed after end of loop. Why this piece of code is getting executed after loop even it is under the scope of loop.

Thanks

Hi @hashrakhi

The $browser.findElement function returns a promise which then executes on its own. When coding with promises you will need to chain the promises together so they execute in the correct order. As you are missing the return on your $browser.findElement call you are skipping returning the promise to the current chain.

}).then(function(){
var showdata=
[
["Client 2","8 %"],
["Client 3","7 %"],
["Client 4","9 %"]
];
var str;
var r=showdata.length;
var c=showdata[0].length;

 for(i=0;i<r;i++)
   {
     for(j=0;j<c;j++)
       {
         str="//*[@id='graph-popup-area']/div/div[1]/div/div[1]/table/tbody/tr["+(i+1)+"]/td["+(j+1)+"]";
         return $browser.findElement($driver.By.xpath(str)).then(function(element){
           return element.getText().then(function(text){                
           assert.equal(showdata[i][j], text, 'Cell value is not correct');
        });
     });
      
}

As an alternative you may want to look at using $browser.findElements which can return an array of elements which you could then loop through.

Hi Stefan

Thanks for your reply !!!

I made the changes as per our suggestion but now it seems like that $brwoser.findElement is working for first time only in the loop. Now this code returning out from the loop during first execution itself. Here is the code which I am using:-

  }).then(function(){
     var val;
    var showdata=
        [
          ["","Buses Returns %"],
          ["Client 3","4 %"],
          ["Client 4","9 %"]
        ];
     var str;
     var r=showdata.length;
     var c=showdata[0].length;
     console.log(r+"-"+c);
     $browser.sleep(220);
     for(i=0;i<r;i++)
   {
     for(j=0;j<c;j++)
       {
         console.log("Hello"+i+"~"+j);
         str="//*[@id='graph-popup-area']/div/div[1]/div/div[1]/table/tbody/tr["+(i+1)+"]/td["+(j+1)+"]";
         return $browser.findElement($driver.By.xpath(str)).then(function(element){
           return element.getText().then(function(text){ 
             console.log(i+"-"+j);
           assert.equal(showdata[i][j], text, 'Cell value is not correct');
        });
     });
             
 }
 }

Result:-
3-2
Hello0~0
0-0

Thanks

Hi,

Extremely sorry. Not sure why the complete code was not copied here. I am copying the content again which is as per your suggestion. I can see, loop is getting executed only once and it is being terminated after first execution. I think, this is because of return statement.

}).then(function(){
var showdata=
[
["Client 2","8 %"],
["Client 3","7 %"],
["Client 4","9 %"]
];
var str;
var r=showdata.length;
var c=showdata[0].length;

 for(i=0;  i < r; i++)
   {
     for(j=0; j < c; j++)
       {
         str="//*[@id='graph-popup-area']/div/div[1]/div/div[1]/table/tbody/tr["+(i+1)+"]/td["+(j+1)+"]";
       
         return $browser.findElement($driver.By.xpath(str)).then(function(element){
           return element.getText().then(function(text){  
             console.log(i+"####"+j);
           assert.equal(showdata[i][j], text, 'Cell value is not correct');
           
        });
     });
      
}
}

Request you to help me on this.
Thanks.

1 Like

@hashrakhi - The issue you are running into here is that the findElement command initiates a promise and you can’t iterate through a loop starting promises like you are. You will need to re-write your function to work properly in an async environment like Synthetics.
As @stefan_garnham mentioned, you will likely be better served by using findElements to return an array of web elements and then iterate through that array comparing the values to your desired data values. This action will still require working with promises though so I would highly recommend you look at some different methods to iterate through an array while working with promises. Here is a quick example I put together that might help you get started Iterate through array of elements

1 Like