Protractor can't find value from a table - angularjs

I have a table that displays search results, and it goes something like this:
<table>
<tbody _ngcontent-c4="">
<tr _ngcontent-c4="">
<td _ngcontent-c4="" class="owner">company name</td>
<td _ngcontent-c4="" class="name"> other name/a></td>
<td _ngcontent-c4="" class="status">kasutusel</td>
<td _ngcontent-c4="" class="approval-status">kooskõlastamata</td>
<td _ngcontent-c4="" class="topics">value</td>
<td _ngcontent-c4="" class="last-modified text-nowrap">value</td>
</tr>
<tr _ngcontent-c4="">
<td _ngcontent-c4="" class="owner">value</td>
<td _ngcontent-c4="" class="name"></td>
<td _ngcontent-c4="" class="name"></td>
<td _ngcontent-c4="" class="status">kasutusel</td>
<td _ngcontent-c4="" class="approval-status">some value/td>
<td _ngcontent-c4="" class="topics">some value</td>
<td _ngcontent-c4="" class="last-modified text-nowrap">table value</td>
</tr>
</tbody>
</table>
And I can't get protractor to find the first element, like "owner", my code is:
var rows = tabledata.all(by.tagName("tr"));
var cells = rows.all(by.className("owner"));
await expect(cells.get(0).getText()).to.eventually.equal("company name");
I've get: Trying to access element at index: 0, but there are only 0 elements that match locator By(css selector, .owner)
The testcase is like this: 1. go to mainpage, 2. search by string, 3. go to results page and verify the results from the table. I have a feeling it doesn't get any elements from that redirected page, although I've tried browser sleep and wait for angular. When I run the test though, it does go to the redirected page, displays the table, and then ends.

You can directly find out all .owner td as below showing:
var owners = tabledata.all(by.css('tr > td.owner'));
expect(owners.get(0).getText()).to.eventually.equal("company name");

Related

ng-click in ng-repeat with url redirect

I am trying to redirect the page using ng-click which is avail in ng-repeat.
ng-repeat code:
<tr ng-repeat="students in studlist" ng-click="gotoProfile(1)">
<td width="12%" class="student-list-pic-column"><img src="<?=base_url()."data/student-img/{{ students.photo }}";?>"></td>
<td width="50%" class="custom-table-border-body text-left">{{ students.studname }}</td>
<td width="38%">{{ students.bid }}</td>
</tr>
<tr ng-show="!studlist.length">
<td colspan="3" class="custom-table-border-body text-center">
Search student name ...
</td>
</tr>
Here in ng-click="gotoProfile(1)" instead of that 1 I need {{students.id}} but unable to get
Controller function:
$scope.gotoProfile = function (sid) {
console.log($scope.purl);
var rurl = $scope.purl+sid;
$location.url(rurl);
};
When I run this I am getting url
http://localhost/product/tcm_dev/utility/dashboard#/http://localhost/product/tcm_dev/utility/student/profile/1
like this.
Please help.
Thank You
Prashant
use <tr ng-repeat="students in studlist" ng-click="gotoProfile(student.id)"> to send student.id
and how about use $window.location.href=(rurl); instead of $location.url(rurl);
if you want to open a new page, use $window.location.href=(rurl,'_blank');

Xpath axis not working as expected

Given this snippet:
<tr class="ng-scope" ng-repeat="config in list.elements">
<td class="ng-binding">6grxe</td>
<td class="ng-binding">ComplexTest</td>
<td class="ng-binding">2016-11-25 10:35:03</td>
</tr>
<tr class="ng-scope" ng-repeat="config in list.elements">
<td class="ng-binding">l7yc</td>
<td class="ng-binding">SimpleTest</td>
<td class="ng-binding">2016-11-25 10:35:15</td><!--how to locate this ?-->
</tr>
I tried to locate the marked element on firefox console using xpath like this:
$x("//following-sibling::td[text()='SimpleTest']")
However, the returned element is
<td class="ng-binding">SimpleTest</td>
Whats wrong with my xpath?
I think you want the path //td[. = 'SimpleTest']/following-sibling::td[1] to select the td element immediately following the td with contents SimpleTest.
You XPath expands to
/descendant-or-self::node()/following-sibling::td[text()='SimpleTest']
Basically you are creating the set of all td elements in the document which contain the text SimpleTest in a complicated way.

angular smart-table plugin/directive wont work

I am trying to use smart-tables, Select row plugin, I have added 'smart-table' to my application, like so var myApp = angular.module('myApp', ['ui.bootstrap','smart-table']);
I have also changed the first line of the directive (since it didn't work to just copy-paste it), I changed this:
ng.module('smart-table').directive('stSelectRow', ['stConfig', function (stConfig)
To this: myApp.directive('stSelectRow', ['stConfig', function (stConfig) {
In my html I have this
<table st-table="displayedCollection" st-safe-src="safeCollection" class="table">
<thead>
<tr>
<th>Title</th>
<th>FieldOne</th>
<th>FieldTwo</th>
<th>FieldThree</th>
</tr>
</thead>
<tbody>
<tr st-select-row="row" st-select-mode="multiple" ng-repeat="row in displayedCollection">
<td> {{row.Title}} </td>
<td> {{row.FieldOne}} </td>
<td> {{row.FieldTwo}} </td>
<td> {{row.FieldThree}} </td>
</tr>
</tbody>
If I remove the st-select-row="row" st-select-mode="multiple" the table works, but obviously not the row selection
I am guessing I'm missing some dependency or something, I have only added smart-table.min.js to my application, but I think that should be enough, the directive (select row plugin) is added inside my app.js file. What could it be?
It is because the documentation on the site isn't exactly clear. But it does say
...and the class attribute st-selected is set on the tr element.
You have to define the CSS for st-selected for it to "work":
.st-selected{
background: #216eff !important;
color: white !important;
}

Angularjs - add additional row inside a tr ng-repeat

Ng-repeat is present on a table row
My query is how can we achieve the following:
<tr ng-repeat="x in y">
Looping here....
</tr>
Now as data object is looping on a <tr>. I have a scenario where I have to display data of 1 row in two <tr>.
Eg.
Table
Data1 data1.2 data1.3 data1.4
Data2 data2.2
Data2b data2.3 data2.4
Data3 data3.2 data3.3 data3.4
Data4 data4.2 data4.3
I.e. display data of 1 row in two
Can't use ng-repeat-end
1) You can combine ng-if with ng-repeat and 2) ng-repeat supports multi-element with ng-repeat-start and ng-repeat-end:
<tr ng-repeat-start="item in [1, 2, 3, 4, 5, 6]">
<td>{{item}}</td><td>something else</td>
</tr>
<tr ng-if="item % 2 === 0" ng-repeat-end>
<td colspan="2">-even</td>
</tr>
Demo
I modified the solution New Dev provided for my purposes & thought I'd share since it really saved me.
I needed a solution to repeat my table header row after every nth row as an alternative to a "frozen/fixed upon scrolling" header row, which just isn't feasible for my use case.
In this example, I'm showing the header row after every 25 rows, but not if it's going to be the last row in the table: (($index+1) != itemCollection.length).
<table class="table table-bordered">
<thead>
<tr>
<th>Column Header 1 - Value</th>
<th>Column Header 2 - Index</th>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="item in itemCollection">
<td>{{item}}</td>
<td>{{$index}}</td>
</tr>
<tr ng-repeat-end="" ng-if="(($index+1) % 25 === 0) && ($index+1) != itemCollection.length">
<th>Column Header 1 - Value</th>
<th>Column Header 2 - Index</th>
</tr>
</tbody>
</table>
Check out the modified demo. For simplicity's sake, I used an inline collection, so the "not if it's going to be the last row in the table" logic isn't included (as you'll see with the unneeded column header at the very bottom), but you get the picture.
You need to repeat tbody instead of tr.
<tbody ng-repeat="x in y" >
<tr>
<td>{{X. row data}}</td>
<td>{{X. row data 2}}</td>
</tr>
<tr>
<td colspan="2">
{{X. secondRowData}}
</td>
</tr>
</tbody>
<tr ng-repeat-start=x in y>
<td>selectbox here
<tr\>
<tr ng-repeat-end ng-if=somecondition>
<td>label data <\td>
<\tr>
So now we have already used ng-repeat-end. Inside ng-repeat-end i have to display 2 rows for a single iteration.
<tr><td indexis1>selectbox<\td><\tr>
<tr><td indexis2>label primary<\td><\tr>
<tr><td indexis2>label secondary<\td><\tr>
This is a rough code snippet and there are numerous td already present in code.

ng-init miscalculates aliased index after array.splice

I have encountered a strange behavior related to ng-init, any help would be appreciated.
I have a model object which has a flats property that is an array of flat objects. Each flat object has rooms property which is an array of room objects.
I'm trying to display flat and rooms as follows;
<table ng-repeat="flat in model.flats" ng-init="flatIndex = $index">
<thead>
<tr>
<td>{{flatIndex+1}}. {{flat.name}}</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="room in flat.rooms" ng-init="roomIndex = $index">
<td>{{roomIndex+1}}. {{room.name}}</td>
</tr>
</tbody>
</table>
If i delete a flat or room by using array.splice flatIndex and roomIndex variables doesn't seem to update properly even though $index and ui updates properly.
You can see the problem here in action.
Try to delete 1st, 2nd or 3rd flat or room object by clicking the delete link. Deleting last object from the array doesn't really expose the problem.
Any workarounds would also be appreciated.
This is a known behavior when you use ng-init, the scope property values set by ng-init are not watched and they don't update when you remove items from array to reflect the refreshed index position. So don't use ng-init, instead just use $index (deleteFlat($index)) and flat object reference (to get hold of rooms deleteRoom(flat,$index)).
<table ng-repeat="flat in model.flats track by flat.id">
<thead>
<tr>
<td colspan="2">{{$index+1}}. {{flat.name}}</td>
<td>DELETE FLAT</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="room in flat.rooms track by room.id">
<td> </td>
<td>{{$index+1}}. {{room.name}}</td>
<td>DELETE ROOM</td>
</tr>
</tbody>
</table>
and
$scope.deleteFlat = function(flatIndex){
$scope.model.flats.splice(flatIndex,1);
};
$scope.deleteRoom = function(flat,roomIndex){
flat.rooms.splice(roomIndex,1);
};
Plnkr
Or better off use the ids itself, deleteFlat(flat.id) and deleteRoom(room.id, flat).
<table ng-repeat="flat in model.flats track by flat.id">
<thead>
<tr>
<td colspan="2">{{$index + 1}}. {{flat.name}}</td>
<td>DELETE FLAT</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="room in flat.rooms track by room.id">
<td> </td>
<td>{{$index+1}}. {{room.name}}</td>
<td>DELETE ROOM</td>
</tr>
</tbody>
</table>
and
$scope.deleteFlat = function(flatId){
$scope.model.flats.splice(_getItemIndex(flatId, $scope.model.flats), 1);
};
$scope.deleteRoom = function(roomId, flat){
flat.rooms.splice(_getItemIndex(roomId, flat.rooms), 1);
};
function _getItemIndex(imtId, itms){
var id ;
itms.some(function(itm, idx){
return (itm.id === imtId) && (id = idx)
});
return id;
}
Plnkr2

Resources