I can't get right elements - selenium-webdriver

I click the sort button, get all prices, and I need to ensure that elements were sorted correctly by prices. So I need to get price value="377", price value="1288", price value="1688" etc. but I can't get the right elements.
<div class="ssl-price-box">
<price value="377" units="/yr" class="lg-price ng-isolate-scope">
<span class="price">
<span class="currency-icon">$</span>
<span class="integer ng-binding">3.</span>
<span class="cent ng-binding">77</span>
<span class="units">/yr</span>
</span>
</price>
<!-- ngIf: product.prices.max.certIsPromo -->
</div>
<div class="ssl-content">
<div class="ssl-price-box">
<price value="1288" units="/yr" class="lg-price ng-isolate-scope">
<span class="price">
<span class="currency-icon">$</span>
<span class="integer ng-binding">12.</span>
<span class="cent ng-binding">88</span>
<span class="units">/yr</span>
</span>
</price>
i tried search be css, className, xpath, repearet, i thought if they are all the same repeater would work.
My code:
const allSSLList = $$('.ssl-price-box');
const newAllSSLList = allSSLList.sort((a, b)=>a-b));
expect(await allSSLList).toBe(massiveOfElements)
I need to get only prices, e.g. "3.77", "12.88", "16.88" etc. and then verify if they are ASC sorting but I got all prices, even old ones. I need to get only where
<span class="price">
<price value="377" units="/yr" class="lg-price ng-isolate-scope">
Expected [ '$3.77/YR', '$12.88/YR $26.99/YR', '$16.88/YR $31.99/YR', '$19.66/YR $35.88/YR', '$30.88/YR $44.99/YR', '$38.88/YR $95.99/YR', '$59.99/YR', '$68.88/YR $138.99/YR', '$70.88/YR $96.99/YR', '$78.19/YR', '$78.19/YR', '$134.99/YR', '$138.88/YR $215.89/YR' ] to be 'smth'.
Stack:

From the HTML provided, it looks like the CSS selector div.ssl-price-box > price will get you all the price elements you need. From there, you can use .getAttribute() to pull the value attribute from each element as "377", "1288", etc. Then you would want to convert those string values into numbers, copy that array, sort the second array, and then compare to the first list to verify that the two lists are sorted.

Related

Is there a way to generate new span elements for each value we iterate in *ngFor Angular 8?

I want to generate a span element for each saved tag from my collection tag's array.
I use firebase and get in *ngFor loop i get one big span element with all saved tags separated by comma, instead of getting a span for each tag. Is there any way that i can't prevent this from happening. Also i have created an interface for Saved.
Thanks in advance.
<div class="card">
<div class="card-body">
<h5 class="card-title text-center">{{saved?.title}}</h5>
<hr />
<div *ngFor="let tag of saved.tags">
<span class="badge badge-pill badge-primary">{{saved?.tags}}</span>
</div>
<hr /> View
</div>
</div>
//Saved interface in Saved.ts file
export interface Saved {
id: string;
title: string;
tags: string[];
}
Try having your code like this. This should make the span element repeat rather than the div and then make sure to reference the individual tag rather than the array inside.
If the tag has a name / title attribute swap {{ tag }} for {{ tag.title}}
looking at the interface its just {{ tag }}.
<div>
<span *ngFor="let tag of saved.tags" class="badge badge-pill badge-primary">
{{tag}}
</span>
</div>
Reference to Angular docs on using *ngFor to display data.
At the moment, you are referencing the array inside your *ngFor. So, as a result, you should see the whole list of n tags, for n times. If you switch from {{saved?.tags}} to {{tag}}. You will see one div per tag including one span and a single tag inside.
So for getting one span per tag, use it like the following:
<div class="card">
<div class="card-body">
<h5 class="card-title text-center">{{saved?.title}}</h5>
<hr />
<div>
<span class="badge badge-pill badge-primary" *ngFor="let tag of saved.tags">
{{tag}}
</span>
</div>
<hr />
View
</div>
</div>

I can't create filter to extract all elements that i need

I get prices, even that I don't need, how can I filter them?
<div class="ssl-price-box">
<price value="377" units="/yr" class="lg-price ng-isolate-scope"><span class="price"><span class="currency-icon">$</span><span class="integer ng-binding">3.</span><span class="cent ng-binding">77</span><span class="units">/yr</span></span></price>
<!-- ngIf: product.prices.max.certIsPromo -->
</div>
<price value="13888" units="/yr" class="lg-price ng-isolate-scope">
<span class="price">
<span class="currency-icon">$</span>
<span class="integer ng-binding">138.</span>
<span class="cent ng-binding">88</span>
<span class="units">/yr</span>
</span>
</price>
<price ng-if="product.prices.max.certIsPromo" value="21589" units="/yr" old-price="" class="base-price ng-scope ng-isolate-scope">
<span class="price old-price">
<span class="currency-icon">$</span>
<span class="integer ng-binding">215.</span>
<span class="cent ng-binding">89</span>
<span class="units">/yr</span>
<span class="line-through"></span>
</span>
</price>
I have no idea how to do it. I tried
const allSSLList = element.all(by.css('div.ssl-price-box')).all(by.className("span[class='price']"));
and this
const allSSLList = element.all(by.css('div.ssl-price-box > price'));
expect(await allSSLList)).toBe(newPrices)
I got all elements, but I don't need old price in tag class="price old-price" from second css, because I need compare Array with all new prices
Expected [ '377', '1288', '2699', '1688', '3199', '1966', '3588', '3088', '4499', '3888', '9599', '5999', '6888', '13899', '7088', '9699', '7819', '7819', '13499', '13888', '21589' ] to be 'newPrice'.
With the HTML provided, it looks like you can use the XPath
//div[#class='ssl-price-box']/price[not(#old-price)]
^ find a DIV that has the right class
^ find a child PRICE tag
^ that does not contain the attribute "old-price"
to only get the price that aren't old prices. From there, you can use .getAttribute() to pull the value attribute from each element as "377", "1288", etc.
allSSLList will return an array with all the prices, as you are getting inside the expectation. You need to specify which element from the array you want with a .get(index);
But please provide more info because from the html snipped it's not clear exactly what element do you need to retrieve

How to find element in selenium python using class in div with different selection

I have tried
driver.find_element_by_xpath( "//div[#class='pepDayScroller_dayNum']").click()
for below elements but it did not work. Please help.
Try to located second element with a number of 2
<div class="pepDayScroller_dayNum">1</div>
<div class="pepDayScroller_dayNum">2</div>
<div class="pepDayScroller_dayNum">3</div>
here is addition information
<div class="pepDayScroller_dayWrapper">
<a href="#" class="pepDayScroller_day pepDayScroller_day--selected" data-index="0">
<div class="accessibleText accessibleSelectedMark" aria-hidden="false">Selected</div>
<div class="pepDayScroller_dayNum">1</div>
<div class="pepDayScroller_startingFrom"><div
class="pepDayScroller_startingFromLabel">Prices vary by date.</div>
</div>
</a>
</div>
<div class="pepDayScroller_dayWrapper"><div class="accessibleText accessibleSelectedMark" aria-hidden="false">Selected</div><div class="pepDayScroller_dayNum">1</div><div class="pepDayScroller_startingFrom"><div class="pepDayScroller_startingFromLabel">Prices vary by date.</div></div></div>
once I am able to click on this button, it will scroll down and ask me to select either it is peak or value. codes are below
<a href="#" class="pepTieredCalendar_dateBox tappable pepTieredCalendar_dateBox--32 pepTieredCalendar_dateBox--value" tabindex="0" role="button" data-tier="value" data-date="2018-09-27" aria-label="2018-09-27, 87.30 USD">
<span class="pepTieredCalendar_dateBoxText">27</span>
</a>
how do I find these elements.thanks
The class which you're trying to refer matches many elements at once. You could try to find by matching text like:
driver.find_element_by_xpath("//*[contains(text(), '2')]")
or by matching all elements and selecting the one that you need:
all_elements = driver.find_elements_by_class_name("pepDayScroller_dayNum")
two_element = None
for el in all_elements:
if el.text == "2":
two_element = el
break
Let me know if that helps.

how to create greater than and less than filter in angularjs ng-repeat

I am trying to use range slider in angularjs to filter the grid. I want a greater than and less than filter in my ng-repeat. But I am not getting how to do this. I am using the following code for now. But this is not working for me. This code is not giving me desired output
Here is my html for grid
<div class="col-md-3 product-left-grid" ng-repeat="data in Products| filter:priceSlider.max |filter:priceSlider.min">
<div class="product-grid"></div>
<div class="product-grid-text">
<a href="javascript:void(0)">
<img alt="" src="{{data.Picture1}}">
</a>
<div class="products-grid-info">
<div class="price">
<a class="btn btn-sm btn-width btn-default btn-font-weight"
href="javascript:void(0)"
ng-click="viewDetails($index)">Quick View</a>
<a href="javascript:void(0)"
class="btn btn-sm btn-width btn-default btn-font-weight"
ng-click="addToCart (data.ProductID,data.Picture1,data.ProductName,data.UnitPrice,data.Discount,data.ShippingCharges,data.wieght)">Add to cart</a>
<div class="tovar_description clearfix">
<a class="tovar_title" href="#"><b>{{data.ProductName}} </b> | {{data.UnitPrice | currency:mycurrency}}</a>
</div>
</div>
<div class="clearfix"> </div>
</div>
</div>
</div>
this is my price range slider
<rzslider rz-slider-floor="priceSlider.floor"
rz-slider-ceil="priceSlider.ceil"
rz-slider-model="priceSlider.min"
rz-slider-high="priceSlider.max"
rz-slider-on-change="onSliderChange()"></rzslider>
Now I am using filter but I have doubt that I am going wrong somewhere. Please experts help to solve this problem. Price range filter I need like every eCommerce website have.
Thanks
You have to make a custom filter :
//create an angular filter named "price"
app.filter('price', function () {
//our function will need three arguments
return function(items, greaterThan, lowerThan) {
//then we filter the array with dedicated ES5 method
items = items.filter(function(item){
//if item price is included between the two boundaries we return true
return item.price > greaterThan && item.price < lowerThan;
});
//then we return the filtered items array
return items;
};
});
You can see how Array.filter() works here
Our function will need 3 arguments to work, the items list which is passed by default and the lower and higher boundaries that we will pass as arguments in our ng-repeat filter.
Then you can use the filter as follow :
<div ng-repeat="data in Products | price:priceSlider.min:priceSlider.max | orderBy:'price'">...</div>
As I said above, items array is passed by default, then, to specify other parameters you have to separate them with a colon : right after the filter name.
You can read about custom filters in the official documentation here.
Finally you can then specified as many other filters as you want by separating them with a pipe |.
In our example I'm ordering them by price after the array has been filtered.
Here is a working JSFiddle.

Count group elements using angular-filter

Is it possible using angular-filter "groupBy" (https://github.com/a8m/angular-filter#groupby) to count the elements in each group to use in a "badge" span (of course without using a a function doing the "manual count")
<div class="list-group" ng-repeat="(key, value) in directoryResult | groupBy: 'TableId'">
<a href="#" class="list-group-item active">
<span class="glyphicon glyphicon-transport"></span> {{convertTableid(key)}} <span class="badge">{{directoryResult.length}}</span>
</a>
<div class="list-group" ng-repeat="item in value">
<a href="#" class="list-group-item">
<span class="glyphicon glyphicon-transport"></span> {{item.Text}}
</a>
</div>
</div>
If you do something like:
ng-repeat="(key, value) in directoryResult | groupBy: 'TableId' as result"
then result will be the filtered variable. You can check the length of that for the number of groups.
Update:
Here is a plunker with a groupBy filter.
http://plnkr.co/edit/8jB4wSRtKfVmEsTGZtfV?p=preview
I took an existing filter I found (since angular doesn't have a built in one) and added a length property. The results show up properly.
Update 2:
Another plunker:
http://plnkr.co/edit/iwUkIMjvevja7KyfTrFC?p=preview
Since angular-filter doesn't provide a length property, you have to count it yourself with Object.keys
<div>Number of groups: {{numGroups(result) }} </div>
JS:
$scope.numGroups = function(input){
return Object.keys(input).length;
}
Update 3:
the result contains an object literal: each property is named "key" and its value is a subgroup of the list. So the running solution is:
<div>Number of groups: {{numGroups(result[key]) }} </div>
Update 4
Finally we may get rid completly of the numGroups function, using directly:
<div>Number of groups: {{result[key].length}} </div>
So your first idea was the good one, I had just to adapt it as my groupBy resturn an object literal containing all the goruped lists.

Resources