Cypress - Choosing an option within a dropdown menu - html

Trying to use the bn.com to run a simple test to search for a book and sort by Lowest Price first. The HTML of that dropdown section after searching the bookstore for "left hand of darkness" is as follows:
<div class="sort-by">
<select name="sorter" id="sortProducts1" class="hidden selectBox" title="Sort by:" data-selectbox="" style="display: none;">
<option value="/s/left+hand+of+darkness" selected="selected">Top Matches</option>
<option value="/s/left+hand+of+darkness?Ns=P_Sales_Rank%7C0">Best Sellers</option>
<option value="/s/left+hand+of+darkness?Ns=P_Publication_Date%7C1">Newest to Oldest</option>
<option value="/s/left+hand+of+darkness?Ns=P_Publication_Date%7C0">Oldest to Newest</option>
<option value="/s/left+hand+of+darkness?Ns=P_Sale_Price%7C0">Price - Low to High</option>
<option value="/s/left+hand+of+darkness?Ns=P_Sale_Price%7C1">Price - High to Low</option>
<option value="/s/left+hand+of+darkness?Ns=P_Display_Name%7C0">Title - A to Z</option>
<option value="/s/left+hand+of+darkness?Ns=P_Display_Name%7C1">Title - Z to A</option>
</select>
<div class="selectBox-container">
<a class="selectBox hidden selectBox-dropdown selectBox--filled" title="Sort by:" tabindex="0" style="display: inline-block;" aria-labelledby="sortProducts1-button-label" id="sortProducts1-replacement" aria-expanded="false" aria-owns="selectBox-2">
<span class="selectBox-title">Sort by:</span>
<span class="selectBox-label" id="sortProducts1-button-label">Top Matches</span>
<span class="selectBox-arrow"></span>
</a>
<ul class="selectBox-dropdown-menu selectBox-options hidden-selectBox-dropdown-menu" style="display: none;" id="selectBox-2" role="listbox">
<li id="sortProducts1-option-0" role="option">
<a rel="/s/left+hand+of+darkness">Top Matches</a>
</li>
<li id="sortProducts1-option-1" role="option">
<a rel="/s/left+hand+of+darkness?Ns=P_Sales_Rank%7C0">Best Sellers</a>
</li>
<li id="sortProducts1-option-2" role="option">
<a rel="/s/left+hand+of+darkness?Ns=P_Publication_Date%7C1">Newest to Oldest</a>
</li>
<li id="sortProducts1-option-3" role="option">
<a rel="/s/left+hand+of+darkness?Ns=P_Publication_Date%7C0">Oldest to Newest</a>
</li>
<li id="sortProducts1-option-4" role="option">
<a rel="/s/left+hand+of+darkness?Ns=P_Sale_Price%7C0">Price - Low to High</a>
</li>
<li id="sortProducts1-option-5" role="option">
<a rel="/s/left+hand+of+darkness?Ns=P_Sale_Price%7C1">Price - High to Low</a>
</li>
<li id="sortProducts1-option-6" role="option">
<a rel="/s/left+hand+of+darkness?Ns=P_Display_Name%7C0">Title - A to Z</a>
</li>
<li id="sortProducts1-option-7" role="option">
<a rel="/s/left+hand+of+darkness?Ns=P_Display_Name%7C1">Title - Z to A</a>
</li></ul></div>
</div>
I can't seem to get the option in the dropdown selected.
My most recent attempt looks like this:
describe('Visits book store and finds cheapest book', () => {
it('Visits book store and finds cheapest book', () => {
cy.visit('https://www.barnesandnoble.com/');
cy.get(`[id="searchBarBN"]`).type('Left Hand of Darkness');
cy.get('.icon-search-2').click();
cy.get(`[id="sortProducts1-replacement"]`).find(`[id="sortProducts1-option-4"]`)
.click({ force: true });
There are no failures, but the sort option nevertheless remains unselected since the DOM does not have the book results sorted by price ascending.
Looking for some help in making sure I'm correctly selecting the dropdown choice that's needed.

You most likely need to wait for the results to be returned after the click (cy.get('.icon-search-2').click()) before trying to select any elements or make assertions. Cypress is trying to select elements that have not been rendered.
This can be done using cy.wait against the route for the results.
There are several examples in the Cypress Real World App, a payment application to demonstrate real-world usage of Cypress testing methods, patterns, and workflows of waiting on network requests that demonstrate this concept.

Related

How to force the first option in SORT BY to show the selected mark?

<a class="mobileSortBy-toggle_new"
data-collapsible="mobileSortBy-panel-{{type}}"
data-collapsible-disabled-breakpoint="medium"
data-collapsible-disabled-state="closed"
data-group-collapsible="main">{{lang 'common.sorter.sort_by'}}</a>
<div class="mobileSortBy-panel" id="mobileSortBy-panel-{{type}}" data-mobile-sort-by>
<h4 class="mobile-panel-heading"><span class="mobile-panel-heading-ellipse">{{lang 'common.sorter.sort_by'}}</span></h4>
<a class="mobile-panel-close" href="#" data-collapsible="mobileSortBy-panel-{{type}}" data-group-collapsible="main"><svg><use xlink:href="#icon-close" aria-hidden="true"></use></svg></a>
<div class="mobileSortBy-panel-body" data-lock-body-scroll>
<ul class="navList navList--mobileSelectList">
<li class="navList-item">{{lang 'common.sorter.relevance'}}</li>
<li class="navList-item">{{lang 'common.sorter.newest'}}</li>
<li class="navList-item">{{lang 'common.sorter.price_asc'}}</li>
<li class="navList-item">{{lang 'common.sorter.price_desc'}}</li>
</ul>
</div>
</div>
SORT BY code for the mobile version. When the user is selecting an option, the code shows the "is-active" in the class, and that places a V mark next to it.
The problem is with the first option. It ignores the If statement and doesn't show the mark.
What can be done to fix it?

Implementing Custom dropdown in Angular 2/4

I have been working on a custom dropdown functionality with a horizontal divider seperating two sets of values and have general select dropdown functionalities like using up and down arrow to navigate through the values, as well as go to specific values on press of a alphabet.
Code:
<div class="btn-group d-flex dropdown" dropdown>
<div class="floatLabelContainer w-100">
<button id="button-basic" dropdownToggle type="button" float-label [addLabel]="false" [hasFloat]="true" class="mb-2" aria-controls="dropdown-basic">
{{selectedCountry}}
<span class="caret" id="country-caret"></span>
</button>
<label for="button-basic" class="label-class" id="label-class">Country</label>
</div>
<ul id="dropdown-basic" slimScroll width="100%" height="250px" size="3px" alwaysVisible="true" wheelStep="20" *dropdownMenu
class="dropdown-menu d-block" role="menu" aria-labelledby="button-basic">
<li role="menuitem">
<a class="dropdown-item" tabindex="0" (click)="selectedCountry = country.name" *ngFor="let country of restOfCountries | orderBy : 'name'">{{country.name}}</a>
</li>
<li class="divider dropdown-divider"></li>
<li role="menuitem">
<a class="dropdown-item" tabindex="0" (click)="selectedCountry = country.name" *ngFor="let country of asianCountries | orderBy : 'name'">{{country.name}}</a>
</li>
</ul>
</div>
I have been able to achieve the divider part with the above code,
but is there away to implement arrows and alphabet press functionality also.
I would prefer to have angular specific implementation or a plugin, rather than js or jQuery
There is the possibility of evaluating keydown and keyup events:
https://alligator.io/angular/binding-keyup-keydown-events/
According to this you should be able to achieve this functionality by implementing click listeners such as:
<div class="btn-group d-flex dropdown"
(keydown.arrowup)="select(items[i-1])"
(keydown.arrowdown)="select(items[i+1])"
dropdown>
EDIT: so I tried this and turns out this does not work on any item on default. It works on inputs, how the example shows but I could not get i ti to work on a list by now.

iMacros - TAG specific element with XPATH

and thank you in advance for taking a minute of your valuable time to solve this puzzle and educate me on the topic.
(please forgive my terminology)
I am using the following code in iMacros for Firefox to select an element on the site, which works fine, as long as the element exists and is in the same order.
TAG XPATH=".//*[#id='contacts']/ul/li[1]/div/ul/li[1]" EXTRACT=TXT
Which in this case would result in "New York, NY"
From:
<div id="contacts" class="article expanding_group">
<div class="article-header">
<!-- Public Company = Block. Public Name/Title = Restricted. -->
<ul class="list">
<li class="list_item">
<div class="list_item_content contact-detail">
<div class="edit expanded">
<ul>
<li class="name"> New York, NY </li>
<li class=" ellipsis">
http://www.a24films.com
</li>
<li class="info ">
+1 646 568 6015
<span class="attributes">phone</span>
</li>
<li class="info ellipsis">
info#a24films.com
</li>
<li class="address ">601 West 26th Street</li>
<li class="address ">Suite 1740</li>
<li class="address "> New York, NY 10001 </li>
<li class="address ">USA</li>
<li class="address ">
</ul>
</div>
However, if the field is missing, it will skip to the next field which will, in essence, result in data being inserted into the incorrect row.
E.g. if I am expecting columns "name, phone, address", and it is missing phone, it will result in "name, address, blank".
I can see it I want only when list item 1's class="name", so my question is: is there a way to specify that I want the list item number 1 that contains "name" in class?
I have tried a variation of strings to no avail, but I woulf imaging something like this is possible:
TAG XPATH=".//*[#id='contacts']/ul/li[1]/div/ul/li[1]/name" EXTRACT=TXT
Thank you for your time,
Reinaldo
You can try the following code:
TAG XPATH=".//*[#id='contacts']/ul/li[1]/div/ul/li[#class='name'][1]" EXTRACT=TXT
Try this Xpath:
.//*[#id='contacts']//li[#class='name'][1]
I don't think #Shugar's code will work.

Creating a collapsible tree view with Angular 2

I am tring to develop my own collapsible tree view as a way to learn Angular 2. I have it partly working. Right now I am stuck on how to apply the hidden property to on the specific <li> item that has been clicked on. Here is what I have so far.
This is the html that displays the items to go in the list.
<div>
<ol>
<li *ngFor="let item of videoList">
<div>
<a *ngIf="item.nodes && item.nodes.length > 0" (click)="toggle()">{{item.title}}</a>
<a *ngIf="item.nodes <= 0">{{item.title}}</a>
</div>
<ol [hidden]="!collapsed">
<li *ngFor="let subItem of item.nodes">
<a *ngIf="subItem.nodes && subItem.nodes.length > 0" (click)="toggle()">{{subItem.title}}</a>
<a *ngIf="subItem.nodes <= 0">{{subItem.title}}</a>
<ol [hidden]="!collapsed">
<li *ngFor="let video of subItem.nodes">
<a *ngIf="video.nodes && video.nodes.length > 0">{{video.title}}</a>
<a *ngIf="video.nodes <= 0">{{video.title}}</a>
</li>
</ol>
</li>
</ol>
</li>
</ol>
</div>
and here is the typescript in the component that collapses or expands the list.
collapased = false;
toggle() {
this.collapsed = !this.collapsed;
}
currently the code collapses and expands the top level elements together and the second level elements together. I need to make each item in the list independent of the other ones. I also prefer to stay away form using CSS to achieve this.
If you add a new property in your front-end model, assuming you are using a front-end model, then you can toggle the items one at a time:
export class Item {
constructor (
public nodes: Node[],
public hidden: boolean) {}
}
<div>
<ol>
<li *ngFor="let item of videoList">
<div>
<a *ngIf="item.nodes && item.nodes.length > 0" (click)="item.hidden = !item.hidden">{{item.title}}</a>
<a *ngIf="item.nodes <= 0">{{item.title}}</a>
</div>
<ol [hidden]="!item.hidden">
…
If you're not using a model like that, then the only other thing I can think of is creating a unique id tag for each by using whatever unique id comes with your data:
<a id="{{node.id}}"> </a>
Then you can hide and show based on the id property of those elements. I'm out of ideas, but I'm sure someone else will help!
I have a list of JavaScript objects "hard coded for them moment" each object has properties id: 1, title: something, collapsed: true, and nodes: [] I added the collapsed property to each node and did the following in my html.
<div>
<ol>
<li *ngFor="let item of videoList">
<div (click)="item.collapsed = !item.collapsed">
<a *ngIf="item.nodes && item.nodes.length > 0">{{item.title}}</a>
<a *ngIf="item.nodes <= 0">{{item.title}}</a>
</div>
<ol >
<li *ngFor="let subItem of item.nodes" [hidden]="item.collapsed">
<div (click)="subItem.collapsed=!subItem.collapsed">
<a *ngIf="subItem.nodes && subItem.nodes.length > 0">{{subItem.title}}</a>
<a *ngIf="subItem.nodes <= 0">{{subItem.title}}</a>
</div>
<ol>
<li *ngFor="let video of subItem.nodes" [hidden]="subItem.collapsed">
<div>
<a *ngIf="video.nodes && video.nodes.length > 0">{{video.title}}</a>
<a *ngIf="video.nodes <= 0">{{video.title}}</a>
</div>
</li>
</ol>
</li>
</ol>
</li>
</ol>
</div>
basically what is happening is I am changing the collapsed property of the selected node.

How to find Xpath for read the list of elements use list<Webelement>

webdriver finding xpath its too dificult for me. i used fire path most of fire path given xpath not working and its too lengthy. some one give me idea about xpath will work all conditions and i know relative xpath
some times this posibilities also not working like {//ul[#class='review-nav']}. some one help me for find xpath that xpath will work all conditions
<ul class="review-nav">
<li id="pend" class="pend tabclass">
<a onclick="OnTabSelect(1,'pend',0)" href="#">Pending (197)</a>
<span class="glyphicon glyphicon-filter filterclass" style="color:#185daa;top:4px;display:none"/>
</li>
<li id="flag" class="flag tabclass active">
<a onclick="OnTabSelect(4,'flag',1)" href="#">Flagged (96)</a>
<span class="glyphicon glyphicon-filter filterclass" style="color:#185daa;top:4px;display:none"/>
</li>
<li id="esca" class="esca tabclass">
<a onclick="OnTabSelect(5,'esca',2)" href="#">Escalated (88)</a>
<span class="glyphicon glyphicon-filter filterclass" style="color:#185daa;top:4px;display:none"/>
</li>
<li id="closed" class="closed tabclass">
<a onclick="OnTabSelect(3,'closed',3)" href="#">Closed (99)</a>
<span class="glyphicon glyphicon-filter filterclass" style="color:#185daa;top:4px;display:none"/>
</li>
<li id="all" class="all tabclass">
<a onclick="OnTabSelect(0,'all',3)" href="#">All (1,355)</a>
<span class="glyphicon glyphicon-filter filterclass" style="color:#185daa;top:4px;display:none"/>
</li>
</ul>
I try this Xpath to read above list its not working
xpath = //ul[#class='review-nav']
Sorry for that, I am little bit not clear for what you need xpath..
If you are trying to get all link ('a') to collect into List
//ul[#class='review-nav']/li/a
If you are trying to get all 'span' element to collect into List
//ul[#class='review-nav']/li/span
If you want to get specific element in specific li, you can try with id of 'li', for example if you like to find xpath of 'a' in first li
//li[#id='pend']/a
Thank You
Try with CSS:
.tabclass
You should get the 'li' elements with this.