How to check the state of element in selenium webdriver - selenium-webdriver

Trying the below code to get the total number of number elements in the different pages. The while condition is getting true and the loop gets executed, but after reaching the last page, the condition is not getting false.
I'm iterating the loop by clicking on "next" button till it is enabled and have to stop the loop execution when this condition becomes false.
Please advice and help me out here. Have tried isEnabled(), isDisplayed as well.
Last Page HTML mark-up
<ul class="pagination-list">
<li class="disabled">
<a>
<span class="icon-next"></span>
</a>
</li>
</ul>
Selenium-
while(driver.findElement(By.xpath("//li[not(contains(#class, 'disabled'))]/a/span[(contains(#class, 'icon-next'))]"))!= null)
{
((JavascriptExecutor)driver).executeScript("window.scrollTo(0, document.body.scrollHeight)");
driver.findElement(By.className("icon-next")).click();
ActiveEnrollUserCounts = driver.findElements(By.xpath("//*[#id='usersList']/tbody/tr"));
uTotal = uTotal + ActiveEnrollUserCounts.size();
}
System.out.println("Active Enrolled Users Count: " +uTotal);

Related

Cannot read property 'includes' of undefined when trying to aply a filter based on a user's input

Im trying to aplly tis simple filter ased on a query of a list that with each input the list will narrow the possibilities
HTML:
<mat-form-field>
<mat-label>Search for users</mat-label>
<input #query type="text" matInput placeholder="search" (keyup)="filter(query.value)">
</mat-form-field>
<div *ngIf="filteredUsers">
And the function:
filter(query){
this.filteredUsers= query?
this.users.filter(user=>user.username.includes(query)):
this.users;
}
<ul *ngFor="let u of filteredUsers">
<li>
{{u.username}}
</li>
</ul>
</div>
The error I get as I input a character id that filter is undefined, but since both arrays fileterdUsers and Users are populated, I can't understand why this error is beig thrown...Any ideas?
EDIT: the ngOninit:
ngOnInit(): void {
this.dataService.getUsers()
.pipe(first())
.subscribe(users=>{
this.filteredUsers=this.users=users;
console.log(users, this.filteredUsers) -> i get the data
})
}
Edit 2 :
EDIT
filter(query){
console.log(this.users)
this.filteredUsers= query?
this.users.filter(user=>user.username.includes(query)):
this.users;
console.log(this.users)
}
Like this I don't see any logs...
EDIT 3: snapshot
Ok, maybe I have an idea of whats going on. The first elements of my ngFor are empty as you can see in the picture. Is this the reason for Angular's complaint? (your last fix didn't solve the issue as well)
If console.log doesnt log your array, it means its empty at the time filter(query) is being called. And I just noticed the way you are assigning the array isnt really what you want since arrays work by reference.
ngOnInit(): void {
this.dataService.getUsers()
.pipe(first())
.subscribe(users=>{
this.filteredUsers=users;
this.users=users; //just to be sure
console.log(users, this.filteredUsers) -> i get the data
})
}
filter returns an array so I guess you want to assign that to the filteredUser. I removed the code that made no sense.
filter(query){
console.log(this.users)
this.filteredUsers = query ? this.users.filter(user=> user.username && user.username.includes(query)): this.users
console.log(this.filteredUsers)
}
Whith the help and envolvment of #ukn I found the solution: the first elements of the array - seen on pic - , in this case users, were empty, so the solution was deleting those elements. The filter function is now working properly, giving me the names as I input a single char. The list gets updated trying to match the chars I input.

Selenium can't find elements until I inspect the page

I have quite a weird problem.
There's a website that has the following two buttons (I can see them when I inspect the page):
button 1
<ul class=" _3dEhb">
<li class = " LH76I">
<a class="-na14 _81NM2" href="/preview/">
<span class="g47FY 10XF41"</span>" preview"
<li class = " LH76I">
<a class="-na14 _81NM2" href="/launch/">
<span class="g47FY 10XF41"</span>" launch"
I'm using the python selenium code
buttons = driver.find_element_by_class_name('LH76I')
if I run it without inspecting the webpage, this code gives me an empty list.
However, if I debug and I inspect the webpage, the same code gives me 2 items in the list.
What am I doing wrong?
Thanks
You should use driver.find_elements_by_class_name instead because you are trying to get a list of elements with same identifier. Try the following code:
buttons = driver.find_elements_by_class_name('LH76I')
Then, if you want to click or something, you would do:
buttons[0].click()
EDIT - You can try the way the list items are generally extracted:
main_list = driver.find_element_by_class_name('_3dEhb') //gets the main ul element
List<WebElement> list_items = main_list.findElements(By.tagName("li"));
for x in range(0, len(list_items)):
{
// whatever you want to do with the item
}

dir-pagination-controls only showing first 10 items. Angularjs

<tr dir-paginate="plan in access |itemsPerPage: 10" total-items="planCount" current-page="current">
<td>{{plan._id}}</td>
<td>{{plan.name}}</td>
<td>{{plan.email}}</td>
<td>{{plan.contactNumber}}</td>
<td>{{plan.accessToken}}</td>
<td>{{plan.downloadSpeed | toMBPS}}</td>
<td>{{plan.uploadSpeed | toMBPS}}</td>
<td>{{plan.issueTime}}</td>
and this is the directive
<div class="text-center">
<dir-pagination-controls auto-hide="false" on-page-change="pageChanged(newPageNumber)"></dir-pagination-controls>
</div>
and this is the angular code
$scope.planCount = 0;
$scope.current = 1;
$scope.pageChanged = function(value) {
console.log("Going to page" + value);
}
The data is coming from the server, but that is working fine. I have logged the data, and I am receiving the complete data. Also, it is the registering the changed page number correctly.
Still, it only shows the first ten items, doesn't matter on what page number I am.
Note: Don't mind the incomplete html. That is the only relevant part to my situation. I can't post the whole code.
Also, I am using this in a different page, but it's working fine in it.
<tr dir-paginate="plan in access |itemsPerPage: 10" total-items="planCount" current-page="current">
From above line remove total-items="planCount". It'll work here too.

Strange bug with ng-repeat and filter

I'm using NodeJS, ANgularJS, and MongoDB with mongoose
Here is my model :
var PostSchema = new mongoose.Schema({
nomReseau : String,
corps : String,
etat : String,
section : String
});
I got a function that change the attribute etat:
$scope.passer = function(index){
var post = $scope.posts[index];
post.etat = "enCours";
Posts.update({id: post._id}, post);
$scope.editing[index] = false;
}
I'm using a ng-repeat for show object in my database :
<ul>
<li ng-repeat="post in posts ">
<p>
<a ng-show="!editing[$index]" href="#/{{post._id}}">{{post.corps}}</a>
</p>
<button ng-show="!editing[$index]" ng-click="passer($index)">Passer</button>
</li>
</ul>
I can see all post in my database and when I click on the button this works perfectly the attribute etat change and all is fine.
But when I add a filter in the ng-repeat like this :
<li ng-repeat="post in posts | filter:{ etat:'aTraiter'} ">
The filter works great I have all post with the attribute etat:'aTraiter'
But if I click on my previous button and change the attribute etat nothing change and I try with other functions they all work wihout the filter but when I put it nothing work.
The problem is that $index will change if less data is shown (because you're filtering). you could use directly post variable
ng-click="passer(post)"
and your function should be something like
$scope.passer = function(post){
post.etat = "enCours";
Posts.update({id: post._id}, post);
var index = $scope.posts.findIndex(function(p) { /* comparison to get original index */ }); /* keep in mind findIndex is not supported on IE, you might want to use filter or for loop instead) */
$scope.editing[index] = false;
}
you could handle editing in the post variable directly. So in your passer function you can do this
post.editing = false;
and in your view
ng-show="!post.editing"
this way you won't use $index and you will prevent all issues with being updated by filters
There are bugs in AngularJS v1.4 where in certain situations the ng-repeat breaks. I upgraded to v1.6 and it went away.
Do you have any controllers/services that access $scope.editing? If so, you might be setting the $scope.editing[$index] equal a previous state where it wasn't equal to false. You may also want to consider that you are assuming $scope.editing[$index] is going to be a boolean. if it has any other type such as string or number then it will evaluate to true.
Otherwise none of your results have the attribute etat equal to 'aTraiter' so they aren't showing. Have you verified that any of them actually do have etat equal to 'aTraiter'. You might be changing that value somewhere else. Possibly from the Passer function

AngularJS: Add element depending on timestamp

I am creating a simple list of messages similar to "Whatsapp". I want to include small blurb saying today, yesterday etc.
JSON format:
{
"id":"2",
"chat_id":"2",
"msg":"sample message 1",
"timestamp":1404803173
}
HTML:
<ul>
<li class="time"><span>Today/Yesterday/2DaysAgo</span></li>
<li ng-repeat="result in results">{{result.msg}}<small>{{result.timestamp*1000 | date:'medium'}}</small></li>
</ul>
I want to show the first <li> (class="time") only once for the day (not for all message). Is there any better way I can do this?
Do you have a server side? If yes, the best way to do this would be to:
Show the "time" li upon first load every new day.
set a flag on the server side to "true" once the li is loaded
Set the flag to false at 0000 hrs every night (or at first load every morning).
Check upon every load if the flag was set to true that day already.
Not sure if this can be done purely from client side. One way thats worth a show would be to set the flag in LocalStorage once every day (append the date maybe? ) and check this flag upon each load..
IMHO the best approach would be to sort messages by time then to split them by day and as output repeat days and messages in days, with other approaches it can be really overcomplicated and not worth the time
Considering that this JSON is coming from a Service and it is an array:
var json=[
{
"id":"1",
"chat_id":"2",
"msg":"sample message 1",
"timestamp":1404803173
},
{
"id":"2",
"chat_id":"2",
"msg":"sample message 2",
"timestamp":1404803174
},
...]
then you could create a new object on your controller looping through the items from your JSON and adding a unique key value for all the days, so you can filter it e.g.: the dates without "/"
$scope.json = Service.json;
$scope.dates = [];
$scope.messages = [];
for(i=0; i<$scope.json.length; i++){
var d = new Date($scope.json[i].timestamp*1000);
var index = String(d.getDate()) + String((d.getMonth()+1)) + String(d.getFullYear());
var obj = {id: index, data: $scope.json[i]};
$scope.messages.push(obj);
if($scope.dates.indexOf(index) == -1) $scope.dates.push(index);
}
Then, on your view:
<ul ng-repeat="date in dates">
<li class="time"><span>{{date | someFilterToGetDayFromDate}}</span></li>
<li ng-repeat="message in messages | filter:{'id': date}:true">{{message.msg}}<small>{{message.timestamp*1000 | date:'medium'}}</small></li>
</ul>
I didn't test the code, but hopefully you will get the idea of what to do here.
If it is not clear, let me know and I will try to explain further.

Resources