简体   繁体   中英

How do I get rows from a list(table) in a protractor e2e test?

The list in question is a table generated by a reactive angular form which does not have a specific ID. Following code is used to generate the list in angular part:

<p-table id='paragraphList' *ngIf="paragraphsObs | async; else loading"
         [value]="paragraphsObs | async"
         selectionMode="single" (onRowSelect)="select($event)"
         scrollable="true">
  <ng-template pTemplate="header">
    <tr> ...header... </tr>
  </ng-template>
  <ng-template pTemplate="body" let-paragraph let-rowData>
    <tr [pSelectableRow]="rowData">
      <td width="15%">{{paragraph.cell1}}</td>
      <td width="10%">{{paragraph.cell2}}</td>
      <td width="31%">{{paragraph.cell3}}</td>
      <td width="11%">{{paragraph.cell4 | dateTransform: helperService.MM_DD_YYYY_HH_MM_A_Z_DATE_PATTERN}}
      </td>
      <td width="11%">{{paragraph.cell5}}</td>
      <td width="11%">{{paragraph.cell6 | dateTransform: helperService.MM_DD_YYYY_HH_MM_A_Z_DATE_PATTERN}}
      </td>
      <td width="11%">{{paragraph.cell7}}</td>
    </tr>
  </ng-template>
</p-table>

The corresponding table generated at the front-end has the following html source:

<p-table _ngcontent-c6="" id="paragraphList" scrollable="true" selectionmode="single" ng-reflect-selection-mode="single" ng-reflect-scrollable="true" class="ng-star-inserted" ng-reflect-value="[object Object],[object Object">
  <div class="ui-table ui-widget ui-table-hoverable-rows" ng-reflect-ng-class="[object Object]">
    <div class="ui-table-scrollable-wrapper ng-star-inserted">  
      <div class="ui-table-scrollable-view" ng-reflect-frozen="false">
        <div class="ui-table-scrollable-header ui-widget-header">...header...</div>
        <div class="ui-table-scrollable-body">
          <table class="ui-table-scrollable-body-table" ng-reflect-klass="ui-table-scrollable-body-table" ng-reflect-ng-class="[object Object]">               
            <tbody class="ui-table-tbody" ng-reflect-template="[object Object]">
              <tr _ngcontent-c6="" ng-reflect-data="[object Object]" class="ng-star-inserted">...</tr>
              <tr _ngcontent-c6="" ng-reflect-data="[object Object]" class="ng-star-inserted">...</tr>
               ...
            </tbody>
          </table>
          <div class="ui-table-virtual-scroller"></div>
        </div>
      </div>
    </div>
  </div>
</p-table>

I want to reach to those inner elements and get them as a list. I have tried using class names with element and all locators, to get the elements but to no avail. Then I tried using tag names to reach to those elements but that too doesn't seem to work.

This following small snippet returns 0 for the count of elements that I try to obtain from the list.

element(by.id('paragraphList')).element(by.css('.ui-table-scrollable-body-table'))
  .all(by.tagName('tr')).count().then(function (result) {
  console.log(result);
});

Any help would be appreciated. Thanks

Considering above is your full rendered HTML.. The code below will give an Array of arrays, where each array would be containing texts from all the cells of a row.

Explanation: The code has three functions, populateData() - is the driving function where we pass the resolved list of rows .

Then _populateRows() and _populateCells() run recursively to gather the text from the cells. This is also possible to do with a loop (as protractor queues the promises by itself) but I like keeping things clear on my end. _populateRows() recur on rows and _populateCells() recur on cells of each row. (more in comments)

Note This first thing which you should do before implementing this is: check the count() (or .length of resolvedRows ) of element.all(by.css('#paragraphList table tbody tr')) . As basically this was your original question I believe. Now If you have a count, then you can go with this solution or whatever suites your need.

let allRows = element.all(by.css(`#paragraphList table tbody tr`)); //will have all the rows.
allRows.then((rowsResolved) => {
    // now have all the rows
    PO.populateData(rowsResolved).then((allData) => {console.log(allData)})  // should be an Array od arrays, each array would be containing texts from all the cells. 
    // Considering you have a Page Object and added the functions below in the Page Object.
    // Page Object is nothing but another class where we keep our utility methods
})


//    driving function
populateData(rowsResolved) {
    let data = [];
    return this._populateRows(0, rowsResolved, data);
}

// calls itself recursively to loop over the rows
private _populateRows(index, rowsResolved, data) {
    if (index >= rowsResolved.length) {
        let defer = protractor.promise.defer();
        defer.fulfill(data);
        return defer.promise;   // so that it is chainable even if I don't have any rows
    }

    let cells = element.all(by.css(`#paragraphList table tbody tr:nth-child(${index + 1}) td`));
    cells.then((cellsResolved) => {
        let cellData = [];
        if (cellsResolved.length) {
            data.push(cellData);
        }
        this._populateCells(0, cellsResolved, cellData);
        return this._populateRows(index + 1, rowsResolved, data);
    })
}

// calls itself recursively to loop over all the cells ofeach row.
private _populateCells(index, cellsResolved, cellData) {
    if (index >= cellsResolved.length) {
        let defer = protractor.promise.defer();
        defer.fulfill(cellData);
        return defer.promise;  // so that it is chainable even if I don't have any cells(that would be an incorrect structure though, if a row exists then cells have to exist )
    }

    cellsResolved[index].getText().then((cellValue) => {
        cellData.push(cellValue)
    });
    return this._populateCells(index + 1, cellsResolved, cellData);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM