How to handle table data in Protractor

2019-01-24 17:40发布

问题:

In Protractor, how does one handle repeated content, from say a table? For example, given the following code, that kicks out a table with 3 columns: Index, Name and Delete-Button in each row:

<table  class="table table-striped">
<tr ng-repeat="row in rows | filter : search"  ng-class="{'muted':isTemp($index)}">
  <td>{{$index+1}}</td>
  <td>{{row}}</td>
  <td>
    <button class="btn btn-danger btn-mini" ng-click="deleteRow(row)" ng-hide="isTemp($index)"><i class="icon-trash icon-white"></i></button>
  </td>
</tr>
</table>

And in my test I need to click the delete button based on a given name. What's the best way to find this in Protractor?

I know I could grab the rows.colum({{row}}) text, get the index of that, and then click on the button[index], but I'm hoping for a more elegant solution.

For example, in Geb, you could pass a row locator to a module, that would then dice up each row with column indicators. And that solution has me eyeing Protractors map method...

回答1:

You can use map or filter. The api would look like this:

  var name = 'some name';

  // This is like element.all(by.css(''))
  return $$('.table.table-stripe tr').filter(function(row) {
    // Get the second column's text.
    return row.$$('td').get(2).getText().then(function(rowName) {
      // Filter rows matching the name you are looking for.
      return rowName === name;
    });
  }).then(function(rows) {
    // This is an array. Find the button in the row and click on it.
    rows[0].$('button').click();
  });

http://angular.github.io/protractor/#/api?view=ElementArrayFinder.prototype.filter



回答2:

Here is how I am doing something similar in my application using Protractor against a Kendo grid:

I have a page object that has the following functions:

// Query all table rows (tr) inside the kendo grid content container
this.getGrid = function () {

    return element.all(by.css('.k-grid-content tr'));
};


// Use the given rows element finder to query for the delete button within the context of the row
this.getDeleteButtonInRow = function (row) {

    return row.element(by.css(".btn.delete"));
};

Then I use these functions in my test like so:

// Verify that a delete button appears in every row of the grid
var grid = pageObj.getGrid();

grid.each(function (row) {

    var deleteButton = downloadsPage.getDeleteButtonInRow(row);

    expect(deleteButton.isDisplayed()).toBe(true);
});


回答3:

Here's my solution, based on @Andres solution, that I used in my page object:

    this.deleteFriend = function(nameString) {
        return this.rows.filter(function(row) {
            // find the row with the name we want...
            return row.$$('td').get(1).getText().then(function(name) {
                return name === nameString;
            });
        }).then(function(filteredRows) {
            filteredRows[0].$('i.icon-trash').click();
        });
    };


标签: protractor