Iterate through a HTML table to get Cells using a

2019-09-02 18:56发布

问题:

I am writing e2e test using typescript in a protractor-cucumber framework. For my test, I want to compare a HTML table in the UI with the cucumber data table. initially, all I am doing is trying to get each cell text.But I am facing issues iterating through the table. Here is my code, I am new to typescript and javascript and I have mixed up all the syntax. Please excuse if the code doesn't look good. Any pointers are appreciated.

getCellText() {
    console.log('I am here');
    //'brickletrows' is my page object equivalent of 'tbody tr'       
    this.brickletrows.array.forEach(element => {
      let cells = element.$$('td');
      console.log(cells.getText);
    });
  }

I get the error: TypeError: Cannot read property 'forEach' of undefined for the above one

 async getCelltexts() {
//this.Bricklet_table_columns is my page object the equivalent of 'tbody tr td'
let someArray = [this.Bricklet_table_columns];
for (let cell of someArray) {
  {
    await console.log(cell.getText());
  }
}

} a bunch of gibberish code gets printed out for this one on console. My ultimate goal would be to put the cells in a 2D array so that I can use the chai library to assert the cucumber table with the 2D array that i form here. Could someone please point me in the right direction.

I am not able to post the DOM here as it is a sensitive info. But the table is very similar to any HTML table with table id, tbody, th, tr, td tags

回答1:

So, the below code partly works- in the sense it is able to iterate through the table but when I try to compare with the datatable- it fails and that is because the order of elements pushed to the 2D array is random. I think the .each() function is working asynchronously- would you have an idea as to how I can correct this?

 getCellValues(): Promise<string[][]> {
            return new Promise<string[][]>(function (resolve, reject) {
              let allValues = [];               
              // take all 'tr' child elements and iterate them using 'each()'                
              Brick_table_rows1.each(function(el){
                  //console.log("el text " + el.toString());
                // create sub arr for filling one row in   
                let subArr = [];   

                // take a row and process each element
                el.all(by.css('td')).each(function(subEl){
                    //console.log("subEl text: " + subEl.toString()); 
                  // get text of one row element
                  subEl.getText().then(function(text)  {

                    // at the point we receive the text add it to sub array.
                    subArr.push(text);   
                    console.log("subarr text: " + subArr.toString());                  
                  });
                }).then(function () {                 
                  allValues.push(subArr);                
                  console.log("arr text: " + allValues.toString()); 
                });
              }).then(function() {                               
                resolve(allValues);

              });
            });
        }    


回答2:

For beeing able to store elements in correct order we can rely on indexes. ElementArrayFinder.each() provides as second argument an index in it's callback. Since you want to compare whole tables, it would be enough to compare row by row and there's no need to have all values as single values. The new function would look a bit nicer as follows:

async getCellValues(): Promise<string[]> {
    return new Promise<string[]>(async function (resolve, reject) {
      let table = element(by.css('#myTableID'));
      let rows = table.all(by.css('tr'));
      let rowCount = await rows.count();
      let rowValues = new Array(rowCount);
      rows.each(async (row, index) => {
        let text = await row.getText();
        rowValues[index] = text.trim();
      }).then(function() { 
        resolve(rowValues);
      });
   });
}