How to get values of same class/properties in Selenium C#? - c#

I am currently automating tests to compare expected and actual endorsements on a summary page.
How can I read all endorsements values on the page shown on the summary page.These can change, meaning there can be 2-5 depending on different input. I have tried Xpath and CSS selector but have had no luck. Here are the elements properties for two endorsements the rest of the endorsements will have same properties (elements wise) just different values.
I want to be able to get all the endorsements listed on the page so I can input to my excel sheet for comparison against expected endorsement.
ENDORSEMENT 1:
<div class="guidance smaller ng-scope" ng-repeat="end in
prop.Endorsements">
<a ng-href="#c03770af-3724-4c3a-a240-e341c0d2c3ef" ng-bind-
html="end.Name" class="ng-binding" href="#c03770af-3724-4c3a-
a240-e341c0d2c3ef">Restricted Theft</a>
</div>
<a ng-href="#c03770af-3724-4c3a-a240-e341c0d2c3ef" ng-bind-
html="end.Name" class="ng-binding" href="#c03770af-3724-4c3a-a240-
e341c0d2c3ef">Restricted Theft</a>
ENDORSEMENT 2:
<div class="guidance smaller ng-scope" ng-repeat="end in
prop.Endorsements">
<a ng-href="#93ff9067-f64c-4879-933d-8b0a1d077e74" ng-bind-
html="end.Name" class="ng-binding" href="#93ff9067-f64c-4879-933d-
8b0a1d077e74">Malicious Damage Exclusion</a>
</div>
<a ng-href="#93ff9067-f64c-4879-933d-8b0a1d077e74" ng-bind-
html="end.Name" class="ng-binding" href="#93ff9067-f64c-4879-933d-
8b0a1d077e74">Malicious Damage Exclusion</a>

You need a XPath expression to catch all the a elements at once and store them in a list.
When there are no other anchor tags then the Endorsements:
IList<IWebElement> listOfEndorsements= Driver.FindElements(By.XPath("//a"));
When there are other kind of anchor tags you can try:
IList<IWebElement> listOfEndorsements= Driver.FindElements(By.XPath("//div[contains(#ng-repeat,'prop.Endorsements')]/a"));
Then you can use a ForEach loop to extract from the list of IWebElements the information you need.Like:
foreach (var endorsement in listOfEndorsements)
{
var text = endorsement.Text;
}

Related

How to get xpath of different html values with the same properties

I'm working on Selenium and trying to get the values inside tags. The site that I'm working on is https://www.qnbfinansbank.enpara.com/doviz-kur-bilgileri/doviz-altin-kurlari.aspx. But the properties of the objects are the same. Therefore, the xpath scripts are the same. The values that I'm trying to get are like 5,615505 TL, 4,827450 TL, 187,389825 TL from
<div class="dlCont">
<span>5,615505 TL </span>
</div>
<div class="dlCont">
<span>4,827450 TL </span>
</div>
<div class="dlCont">
<span>187,389825 TL </span>
</div>
and so on. Is there any way to get the xpath of these values?
You can store all the values in a List. Then one by one you can retrieve it.
Something like :
IList<IWebElement> allValues= driver.FindElements(By.CssSelector("div.dlCont span"));
foreach (IWebElement values in allValues)
{
Console.WriteLine(values.Text);
}
Hope this will help.
You can use like this,
//span[contains(text(),'5,615505 TL')]
You can manually write the xpath for the below DOM Structure
<div class="dlCont">
<span>5,615505 TL </span>
</div>
Manually written xpath for above DOM structure is "//div[#class='dlCont']/span".
if the page is having many elements with same DOM struture then written Xpath will match with all the nodes.
There are 8 nodes are matched with XPATH="//div[#class='dlCont']/span" in the below URL https://www.qnbfinansbank.enpara.com/doviz-kur-bilgileri/doviz-altin-kurlari.aspx
if you want to fetch particular webelements then you need to specify the index value as "(//div[#class='dlCont']/span)[2]".
you need to add open bracket in the starting of the manually written xpath and close bracket in the ending of the Xpath.after that you need to mention the index value
1.//div[#class='dlCont']/span
2.(//div[#class='dlCont']/span
3.(//div[#class='dlCont']/span)
4.(//div[#class='dlCont']/span)[1]
Hope it will be helpful

How to sendkeys to a <p> tag through C# and Selenium

i want to sendkeys "description" within a textarea. I have tried all the possible ways but does not work.
HTML of the element :
<div class="ta-scroll-window ng-scope ta-text ta-editor form-control" ng-hide="showHtml">
<div class="popover fade bottom" style="max-width: none; width: 305px;">
<div class="arrow"></div>
<div class="popover-content"></div>
</div>
<div class="ta-resizer-handle-overlay">
<div class="ta-resizer-handle-background"></div>
<div class="ta-resizer-handle-corner ta-resizer-handle-corner-tl"></div>
<div class="ta-resizer-handle-corner ta-resizer-handle-corner-tr"></div>
<div class="ta-resizer-handle-corner ta-resizer-handle-corner-bl"></div>
<div class="ta-resizer-handle-corner ta-resizer-handle-corner-br"></div>
<div class="ta-resizer-handle-info"></div>
</div>
<div id="taTextElement737852736512107" contenteditable="true" ta-bind="ta-bind" ng-model="html" ta-keep-styles="true" class="ng-pristine ng-valid ta-bind ng-empty ng-touched" an-form-object-name="Açıklama" name="Açıklama">
<p>
<br>
</p>
</div>
</div>
Code trial :
Dim action2 = New Actions(driver)
Dim cekbul2 = driver.FindElement(By.XPath("//*#id=""taHtmlElement737852736512107""]"))
cekbul2.SendKeys("Açıklama")
Console.Write("textarea send description")
or
Dim cekbul2 = driver.FindElement(By.XPath("//textarea[#class='ng-pristine ng-untouched ng-valid ng-scope ta-bind ta-html ta-editor form-control ng-empty ng-hide' and #id='taHtmlElement737852736512107']"))
The error is :
"no such element: Unable to locate element does not work" give error
Your html does not have a text area input field inside it.
When you use an xPath that says
'//textarea' this means that you are looking for an element that has tags of <textarea> </textarea>
It looks like your html is actually div's that are styled up to look like text areas.
That is why your second attempt will never work - because you are looking for a textarea where none exists.
Typically, in the situation where a div is styled up to work like a text area or textbox, you will find that the div has a backing input behind it.
These must be located between the
<form> and </form> tags in the html - otherwise the server would never be able to receive the data. (Html 5 provides new ways of working with this - but that is another story)
Can you examine your full html, and see if you can find the actual text area objects or the input type objects that end up containing the text content.
Type some dummy text, and use an html inspector tool within chrome or firefox to look for your dummy text.
If however, the post is completed by javascript - you may find that the javascript does not use inputs or text areas for containing the text and instead posts it external to any form elements. This is common with richtext emulators such as forum post pages.
If that is the case- you may need to experiment and find the appropriate html element that you need to send keys to in order for the content to work.
Also - could you try
Dim cekbul2 = driver.FindElement(By.XPath("//div[#id='taHtmlElement737852736512107']"))
I couldnt help but notice it had an xPath syntax error - you had no starting [ square bracket ] - also, in programming it is sometimes considered lazy a bad practice to wildcard / work with dynamics. I recommend always using the tag type for your xpaths, as opposed to '//*'
Worse case scenario, I would say that you could probably get around this by using Javascript execution. Eg: Directly setting the text, instead of 'sending the key strokes'.
However, this does not emulate human behavior - but it may be a necessary evil depending on your situation.
To send text to the <p> tag you have to use the ExecuteScript() method from IJavaScriptExecutor Interface and you can use the following code block :
((IJavaScriptExecutor)driver).ExecuteScript("document.getElementsByTagName("p")[0].innerHTML="Hasan Sarıkaya";");
I want to highlight some points here
Most probably your locator which you are using is not correct.
There are three way which I know to enter text using selenium
1)Use driver.findElement(yourLoator).sendKeys("Stringvalue");
2)You can use action class to send keys
3)You can use javascript executor to change innerHtml code
Personally ill not prefer the third solution, because we are testers I believe changing dom attribute is a good practice
Hope this will give you some help. please Let me know in case any query.

Find node from known starting point in totally dynamic webpage using c# and XPath?

I am trying to write automated smoketest for an internal website. The problem is the website is almost primarily dynamically generated. So any kind of unique identifier like ID is a combination of known string prefix and ends with a radomized number.
I also can NOT depend on the order, so using things like div[2] or span[25] will not be reliable, UNLESS there is some way to grab the count of the span/div/input based on where I am currently located in the DOM by the KNOWN TEXT VALUE.
For example I can find the known text value. If I can somehow programatically determine that the span for this known text value is 55 , and I know that it is nested 2 deep from the other element I am looking for, then I could do something like "//span[55 - 2]/input".
The best I can do is navigate the DOM to some KNOWN text value, and work up OR down from there.
Given that, in the example below, how would I navigate to the INPUT element, when starting from the KNOWN TEXT VALUE???
<span id="RandomlyGenerated35673">
<span id="RandomlyGeneratedNum58532">
<span id="RandomlyGenerated78539">
<span/>
<span/>
<span id="RandomlyGenerated78539">KNOWN TEXT VALUE</span>
</span>
</span>
<input class="GENERIC-NON-UNIQUE" type="button" value="GENERIC-NON-UNIQUE"/>
</span>
You can use the following axis:
//span[. = 'KNOWN TEXT VALUE']/following::input[#type = 'button']

Client side alphabetic multi-column (lists) sorting and filtering

I have an index of "services" which is quite large, and I am trying to make it user friendly.
The current display is four columns (four unordered lists, at the moment) that displays alphabetically top to bottom, then left to right like so:
Ab Be Co En
Ac Ce De Fa
Af Ci Ef Gu
These lists are built in the C# code behind, then the BulletedList controls are attached to the containing Panel control on page load.
The number of items has become large enough that we want to make use of filtering giving a list across the top for # A B C D... etc, and when you click on it, it will filter the results. We want to accomplish this using JavaScript, and avoiding post backs.
My initial thought was to have JavaScript (jQuery) simply .show() and .hide() the ones necessary, but with the current unordered list arrangement, I am struggling with how to accomplish this and maintain the alphabetic layout.
For example, using the four unordered lists example above, filtering for A would result in just this:
Ab
Ac
Af
instead of spanning across the columns.
Taking the thought further, I considered using a single unordered list and having list items float left to easily span across the screen and then down -- but the issue I run into that is sorting alphabetically down first and then across, because it sorts across first and then down.
Additionally, using the float left method causes any link that spans two lines to cause an extra line break for all links across the row, resulting in odd gaps.
I realize this is fairly long winded and specific question, but any assistance on how to accomplish this with code, html/css formatting, or suggestions for a better way of doing this is much appreciated! Thanks for taking the time to read the question.
It sounds like you might want to use one of the jquery portfolio plugins.
Here's one example: http://webdesigntunes.com/coding/jquery-filterable-portfolio/
You create some html tagged with classes matching what you want to sort on
<nav class="primary clearfix">
<ul>
<li>All</li>
<li>Web Design</li>
<li>Ilustration</li>
<li>Logo</li>
<li>Video</li>
<li>Print Design</li>
</ul>
</nav>
<section class="main">
<div class="portfolio">
<article class="entry video">
<a data-rel="prettyPhoto" href="http://vimeo.com/34266952">
<img src="images/portfolio/work1.jpg" alt="">
<span class="video-hover"></span>
</a>
</article>
<article class="entry web">
<a data-rel="prettyPhoto" href="images/portfolio/work2.jpg">
<img src="images/portfolio/work2.jpg" alt="">
<span class="magnifier"></span>
</a>
</article>
</section>
Apply some .css ect.
Then use isotope for sorting
var $container = $('.portfolio');
$container.isotope({
filter: '*',
animationOptions: {
duration: 750,
easing: 'linear',
queue: false,
}
});
$('nav.primary ul a').click(function(){
var selector = $(this).attr('data-filter');
$container.isotope({
filter: selector,
animationOptions: {
duration: 750,
easing: 'linear',
queue: false,
}
});
return false;
});
var $optionSets = $('nav.primary ul'),
$optionLinks = $optionSets.find('a');
$optionLinks.click(function(){
var $this = $(this);
// don't proceed if already selected
if ( $this.hasClass('selected') ) {
return false;
}
var $optionSet = $this.parents('nav.primary ul');
$optionSet.find('.selected').removeClass('selected');
$this.addClass('selected');
});
CHeck out the demo and see if that's what you're needing: http://webdesigntunes.com/tutorial/filterable/
http://isotope.metafizzy.co/

Write query to parse HTML DOCUMENT with HtmlAgilityPack

I want to get the A href of that element in span class="floatClear" whose rating is minimum in
span class="star-img stars_4"
How can I use HtmlAgilityPack to achieve this behaviour I have give the html source of my file
<div class="businessresult"> //will repeat
<div class="rightcol">
<div class="rating">
<span class="star-img stars_4">
<img height="325" width="84" src="http://media1.px" alt="4.0 star rating" **title**="4.0 star rating">
</span>
</div>
</div>
<span class="floatClear">
<a class="ybtn btn-y-s" href="/writeareview/biz/KaBw8UEm8u6war_loc%NY">
</span>
</div>
The query I have written
var lowestreview =
from main in htmlDoc.DocumentNode.SelectNodes("//div[#class='rightcol']")
from rating in htmlDoc.DocumentNode.SelectNodes("//div[#class='rating']")
from ratingspan in htmlDoc.DocumentNode.SelectNodes("//span[#class='star-img stars_4']")
from floatClear in htmlDoc.DocumentNode.SelectNodes("//span[#class='floatClear']")
select new { Rate = ratingspan.InnerText, AHref = floatClear.InnerHtml };
But I do not know how to apply condition here at last line of LINQ query!
Don't select "rating" from the entire htmlDoc, select it from the previously found "main".
I guess you need something like:
var lowestreview =
from main in htmlDoc.DocumentNode.SelectNodes("//div[#class='rightcol']")
from rating in main.SelectNodes("//div[#class='rating']")
from ratingspan in rating.SelectNodes("//span[#class='star-img stars_4']")
from floatClear in ratingspan.SelectNodes("//span[#class='floatClear']")
select new { Rate = ratingspan.InnerText, AHref = floatClear.InnerHtml };
I hope it will not crash if some of those divs ans spans are not present: a previous version of the HtmlAgilityPack returned null instead of an empty list when the SelectNodes didn't find anything.
EDIT
You probably also need to change the "xpath query" for the inner selects: change the "//" into ".//" (extra . at the beginning) to signal that you really want a subnode. If the AgilityPack works the same as regular XML-XPath (I'm not 100% sure) then a "//" at the beginning will search from the root of the document, even if you specify it from a subnode. A ".//" will always search from the node you are searching from.
A main.SelectNodes("//div[#class='rating']") will (probably) also find <div class="rating">s outside the <div class="rightcol"> you found in the previous line.
A main.SelectNodes(".//div[#class='rating']") should fix that.

Categories

Resources