Select child of sibling element - selenium

I have the following HTML DOM. My goal is to get the "Error" text.
<div class = "row">
<div class ="col-sm-4">
<input id = "firstName" type = "text"> John
<div class = "mh-15">
<div class = "text-danger">Error</div>
</div>
</div>
</div>
As class = "text-danger" is repeated numerous times, my goal is to get to the "Error" text by starting from id = "firstName" and going down the way by using something like an xpath ancestor. How should i do that? Thanks!

Xpath :
//input[#id='firstName']/following-sibling::div[2]
Note that <div class = "mh-15"> should be sibling of input box.

ancestor is for selecting parent element, the class="text-danger" is after the element of id="firstName" you have to select it with following or following-sibling
//input[#id="firstName"]/following-sibling::div/div
# or
//input[#id="firstName"]/following::div/div

Related

how to ignore span with List<WebElement>

I am trying to extract Main Text1 and Main Text2 from below DOM structure.
<div class="origination">
<div class="origin">
<h3>
Main Text1
<span class="info">Test1</span>
</h3>
<div class="test">
</div>
</div>
<div class="origin">
<h3>
Main Text2
<span class="info">Test2</span>
</h3>
<div class="test">
</div>
</div>
</div>
I have used below xpath with text() to identify header without span
#FindBy(xpath = ".//*[#id='origination']/div[*]/h3/text()")
List<WebElement> content;
I am trying to print header element without span using below code
for (WebElement element: content){
System.out.println("Header" + element.getText());
}
But I am getting error:
org.openqa.selenium.NoSuchElementException: Timed out after 15 seconds. List elements not found
However, when I used the same XPath on the firepath elements get highlighted in the DOM structure but not on to the page.
Here is the answer.
spanText = element.findElement(By.xpath("//span[#class='info']")).getText()
element.getText().Replace(spanText, string.Empty);

How can I find the exact value using xpath in selenium webdriver for text that contains ?

I'm having an issue selecting the exact text 'Section' from the code using xpath.
** To be clear I require the exact text selection to be made from the innerText or innerHTML of the element if that is possible, not the id. **
I'm able to use the contains text function, but that results in other partial matches that contain 'Section' being returned/highlighted as well:
//div[#aria-hidden='false']//ul/li[contains(text(),'Section')]
I've tried using the following methods, but I don't know if I've got the syntax correct, as nothing is returned/highlighted:
//div[#aria-hidden='false']//ul/li[text()='Section')]
//div[#aria-hidden='false']//ul/li[.='Section']
//div[#aria-hidden='false']//ul/li[normalize-space(.)='Section']
This is what is shown when inspecting the Section node:
<li id="GOS--/40" class="nodecollapsed item parent-node xh-highlight" style="" xpath="1">
Section <span class="child-count"></span>
</li>
This is what is shown in the element properties:
id: "GOS--/40"
innerHTML: "↵ Section <span class="child-count"></span>↵ "
innerText: " Section "
Here is the xml which shows the other partial matches that are returned:
<div class="selection-list-dialog modal-dialog Dialog">
<div class="modal-content">
<div class="modal-header SectionHeader">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<span class="modal-title" data-lang="StandardItems">Standard Items</span>
</div>
<div class="modal-body selection-list-container" style="margin-top: 30px" id="base">
<div>
<span data-lang="SelectItemInstructions">Select the items you are interested in from the list.</span>
</div>
<br/>
<div class="pull-left selection-tree-container">
<h4 class="selection-list-title">
<span data-lang="Available">Available</span>
</h4>
<ul class="selection-list selection-tree-list">
<li id="CS--/14" class="nodecollapsed item parent-node">
Country Section <span class="child-count"></span>
</li>
<li id="Sec1--/23" class="nodecollapsed item parent-node">
Section 1 <span class="child-count"></span>
</li>
<li id="Sec2--/24" class="nodecollapsed item parent-node">
Section 2 <span class="child-count"></span>
</li>
<li id="GOS--/40" class="nodecollapsed item parent-node">
Section <span class="child-count"></span>
</li>
<li id="RS--/43" class="nodecollapsed item parent-node">
Regional Section <span class="child-count"></span>
</li>
This was a tough one. The problem is that you have a number of similar options all containing "Section" in some flavor and it's hard to distinguish them apart. What adds to this is that each one contains a non-breaking space which means that normalize-space() won't work (directly) either.
But... I found that the below XPath will work.
//li[normalize-space()='Section\u00a0']
normalize-space() removes whitespace (but not &nbsp) so you have to add it in there with \u00a0. I've tested this locally and it's working.
Try following xpath see if it helps.
//li[starts-with(#id,'GOS')][#class='nodecollapsed item parent-node xh-highlight']
OR
//li[#class='nodecollapsed item parent-node xh-highlight'][#xpath='1']
you can try the below XPath to find a section node
Try if it helps
//li[#id='GOS--/40'][contains(text(),'Section')]
Let me throw my hat into the ring....
//li[(normalize-space(text()) = 'Section')]
Here is the method that will fetch the text from the parent only. (exclude the text in the child(ren))
In Python:
def get_pure_element_text(element):
return driver.execute_script(
"""
var parent = arguments[0];
var child = parent.firstChild;
var textValue = "";
while(child) {
if (child.nodeType === Node.TEXT_NODE)
textValue += child.textContent;
child = child.nextSibling;
}
return textValue;""",
element).strip()
This method will iterate all the firstChild (direct children) and extract all text from all the text nodes.
In this context If you want to retrieve the text of li which have the id GOS--/40 then use the method as below.
element = driver.find_element_by_xpath("//li[#id='GOS--/40']")
print(get_pure_element_text(element))
Sharing this method, at least might help the others (if not the OP in this context).
C# implementation:(not tested)
string get_pure_text(IWebDriver driver, IWebElement element){
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
return (string)js.ExecuteScript(""""
var parent = arguments[0];
var child = parent.firstChild;
var textValue = "";
while(child) {
if (child.nodeType === Node.TEXT_NODE)
textValue += child.textContent;
child = child.nextSibling;
}
return textValue;""",
element");
Usage:
string output = get_pure_text(driver,element)

How can i click an image from the search results page

I am writing a test in Webdriver C# with Nunit. I have a search results page loaded with a list of products with images. I want to click the 1st image in the results.
I have tried using the Xpath (I used firepath to get this value)
[FindsBy(How = How.XPath, Using = "html/body/form/div[2]/div[4]/div/div[2]/p")]
private IWebElement ProductImage_xpath {get; set; }
When it runs it says:
Could not find element by XPath.
I would like to use CSS selector if possible as that is faster than finding by Xpath.
What syntax could I use to locate the image from the code snipped below?
Note: the hyperlinks are dynamic, I don't want to use the href.
public SearchResultsPage clickProduct_Image()
{
ProductImage_xpath.Click();
Console.Out.WriteLine("ProductImage = " + ProductImage_xpath.Text);
return new SearchResultsPage(Driver);
}
The Code snippet:
<div id="main" class="nav_redesign s-left-nav-rib-redesign" data-page-construction="aui" skeleton-key="results--searchTemplate listLayout so_gb_en --left-nav--shopping-engine">
<div id="topStatic">
<div id="top">
<div id="topAmabot"> </div>
<div id="searchTemplate" class="searchTemplate listLayout so_gb_en ">
<div id="topDynamicContent">
<div id="rightContainerATF">
<div id="rightResultsATF">
<div id="widthPreserver"></div>
<div id="centerPlus">
<div id="rhsAjax"></div>
<div id="resultsCol" class="">
<div id="centerMinus" class="">
<div id="atfResults" class="list results apsList">
<div id="result_0" class="fstRow prod celwidget" name="1780974728">
<div class="linePlaceholder"></div>
<div class="image imageContainer">
<a href="http://testerServer1co.uk/SpaceExplorer/dp/1780974728/ref=sr_1_1?ie=UTF8&qid=1409311161&sr=8-1&keywords=planets+1">
<div class="imageBox">
<img class="productImage cfMarker" alt="Product Details" src="http://ecx.images-test.com/images/I/51iYWWt1BqL._SL160_PIsitb-sticker-arrow-dp,TopRight,12,-18_SH30_OU02_AA160_.jpg" onload="viewCompleteImageLoaded(this, new Date().getTime(), 16, false);">
</div>
Xpath is very very bad choice to find element on the page =). As you said better use css selector. I don't know how your image presents on the page, but i'll write possible variants, choose the best one. So, using css selectors to find your image:
1. You can find any element using it's class
//will find "div class="image imageContainer""
driver.findElement(By.Css(".imageContainer"))
2. Combine searching by class and find first "a" child in that div
driver.findElement(By.css(".imageContainer > a"))
3.Find element using known attribute
driver.findElement(By.css("img[alt='Product Details']"))
4. Find element by ID
driver.findElement(By.Css("#atfResults"));
//or
driver.findElement(By.Id("atfResults"));
Well, it will be enough for you, i think. If you have any questions, you are welcome.

I am trying Selenium Webdriver to find input element by class name

How to find element input class="Test_type"? I successfully got by id=Test1 but failing to find element by input class="Test_type"
I have tried:
WebElement mainform = driver.findElement(By.className("mainform"));
List<WebElement> postadchildone2 = mainform.findElements(By.className("formrow"))
for(WebElement formrow: postadchildone2)
{
WebElement formfield = formrow.findElement(By.className("formfield"));
WebElement inputclass = formfield.findElement(By.className("Test_type"))
}
Also tried using CSS selector & XPath, however still it says didn't found, because of the same class name it is not finding input class.
Under for loop I tried doing
formrow.getText()
It displays all the text results but it is not taking class name? I am stuck please help
HTML:
<div class="mainform">
<div class="formrow">
<div class="formrow">
<div class="formrow">
<div class="formfield">
<div id="Test1" class="city_select">
<div class="blank1"/>
<div class="formrow " style="margin-left:10px;">
<div class="formrow">
<div class="formlabel">
<strong>You Are</strong>
</div>
<div class="formfield">
<label>
<input class="Test_type required" type="radio"/>
YouareTest
</label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
as you have the following piece of code:
<div class="formfield">
<label>
<input class="Test_type required" type="radio"/>
YouareTest
</label>
</div>
We need to outline input element somehow.
So I recommend to locate this element using CSS selector because it is the fastest way.
So 'input' tag has following class attribute= "Test_type required" , that means that to this element 2 CSS classes are applied:
Test_type
required
When locating with CSS selector element, an element B with class attribute y will be notated as B.y, an element with 2 class attributes y and z will be notated as B.y.z then.
So in terms of our task it will look like
input.Test_type.required
But also you can notice that you have another element - div with class attribute =formfield as parent element.
So to locate child element to parent with CSS in the structure like:
<parent class="zz">
<child 1>
<child2> abaracadabra</child>
</child 1>
</parent>
parent.zz child2 => in this way
So the second part of our selector be like :
div.formfield as it be parent selector in relation to input.
So solution combo =
WebElement inputt=driver.findElement(By.cssSelector('div.formfield input.Test_type.required'));
Please try this one, and tell whether it works for you or not.
Since you are trying to fetch with only partial class name, try using the below code
WebElement inputclass = formfield.findElement(By.CssSelector("Input[class*='Test_type'"))

Understanding WebElement.findElement() and XPATH

I want to use the WebElement.findElement() API to locate a node inside the parent node using XPATH //span[#class='child-class']. I thought this would return me the <div> that is inside the parent. However, it is returning me the first one it found in the entire DOM tree. Did I use the wrong XPATH?
I have also tried using .//span[#class='child-class'] as the XPATH, but that does return anything.
Thank you.
UPDATE:
given the HTML below, I want to define a locator for the child-title <span> and child-date <span> and locate them using WebElement.findElement() API regardless of the parent being "//a/li[1]" or "//a/li[2]"
<a>
<li> parent 1
<div>
<span class="child-title child-style">title 1</span>
<span class="child-date child-style"> date 1</span>
<span class="child-author">author 1</span>
</div>
</li>
</a>
<a>
<li> parent 2
<div>
<span class="child-title child-style">title 2</span>
<span class="child-date child-style"> date 2</span>
<span class="child-author">author 3</span>
</div>
</li>
</a>
<a>
<li> parent 3
<div>
<span class="child-title child-style">title 3</span>
<span class="child-date child-style"> date 3</span>
<span class="child-author">author 3</span>
</div>
</li>
</a>
I have a WebElement parent2 initialized and located using "//a/li[2]",
WebElement child = parent2.findElement(By.xpath("//span[#class='child-author']")); would give me "author 1"
WebElement child = parent2.findElement(By.xpath("span[#class='child-author']")); would give me NoSuchElementException
There are my 2 comments with your sample code
1 - With your posted HTML, the xpath //a/li[2] is not found (we only have 3 elements with //a/li[1])
2 - Assume that we do have right code, you need to understand the differences between single slash and double slash in Xpath
a/b (single slash): select element that has "tag b" and "stands right after" an element that has "a tag"
E.g.:
<a>
<b>
<d>
<c>
</c>
</d>
</b>
</a>
AND
a//b (double slash): select element that has "tag b" and is n-level-child an element that has "a tag"
E.g.:
<a>
<c>
<d>
<b>
</b>
</d>
</c>
</a>
So, with your code
<a>
<li> parent 1
<div>
<span class="child-title child-style">title 1</span>
<span class="child-date child-style"> date 1</span>
<span class="child-author">author 1</span>
</div>
</li>
</a>
If you want to get Date Info, you should use
WebElement parent = driver.findElement(By.xpath("//a/li"));
WebElement date = parent.findElement(By.xpath("div/span[contains(#class, 'child-date')]"));
WebElement date = parent.findElement(By.xpath("//span[contains(#class, 'child-date')]"));
The code
WebElement date = parent.findElement(By.xpath("span[contains(#class, 'child-date')]"));
Will bring out NoSuchElementException because there is no [span] tag right after [li] tag
Hope help
Try something like:
Use dot(.) before double slash(//)
It looks for child under the given parent element.
Completely new question ... completely new answer. :(
Try something like:
WebElement parent1 = driver.findElement(By.xpath("//a[1]/li")); // use a[2] for parent2
WebElement author = parent1.findElement(By.xpath("span[#class='child-author']"));
WebElement date = parent1.findElement(By.xpath("span[contains(#class, 'child-date')]"));
WebElement title = parent1.findElement(By.xpath("span[contains(#class, 'child-title')]"));
Try something like :
//a/li[contains(text(), 'parent 1')]/div
It requests for "the <div> inside a <li> whose text contains 'parent 1' and who is inside a <a>.
It might not work if you have more parents because it works with a contains() (this xpath would also select <li> parent 10 ... </li>). It would be better if "parent x" were an attribute of the <li> instead of its text.