how to ignore span with List<WebElement> - selenium

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);

Related

Roboframework Selenium - fidn web element and iterate in nested sub-elements

Hello I have this HTML structure:
<div class="1234" role="article">
<div class="A">
<h2 class="B">
<a class="C" href="https://www.test.it">
</a>
</h2>
</div>
<div class="X">
<span class="Y">"some text"
</span>
</div>
</div>
<div class="1234" role="article">
<div class="A">
<h2 class="B">
<a class="C" href="https://www.test2.it">
</a>
</h2>
</div>
<div class="X">
<span class="Y">"some text2"
</span>
</div>
</div>
My goal is to iterate in each Div with role=article, and gather corresponding href and text
(i.e. https://www.test.it - "some text" for the first one)
I've created a basic for loop:
${elements}= Get WebElements xpath://div[contains(#role, 'article')]
FOR ${element} IN #{elements}
Log To Console ${element.get_attribute('href')}
END
But i cannot figure it out how to get the sub elements that I need.
Any help is more than appreciated.
Many thanks
###Update
this works for the href, but I'm unable to get the span text
${elements}= Get WebElements xpath://div[contains(#role, 'article')]
FOR ${element} IN #{elements}
${sub1}= Set Variable ${element.find_element_by_xpath(".//h2//a[contains(#class, 'C')]")}
Log To Console ${sub1.get_attribute('href')}
END
To iterate in each DIV with role="article" and gather corresponding href and text you can use the following Locator Strategies:
href:
${elements}= Get WebElements xpath://div[contains(#role, 'article')]
FOR ${element} IN #{elements}
${sub1}= Set Variable ${element.find_element_by_xpath(".//h2/a[#class='C']")}
Log To Console ${sub1.get_attribute('href')}
END
text:
${elements}= Get WebElements xpath://div[contains(#role, 'article')]
FOR ${element} IN #{elements}
${sub1}= Set Variable ${element.find_element_by_xpath(".//div[#class='X']/span[#class='Y']")}
Log To Console ${sub1.get_attribute('innerHTML')}
END

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)

Not able to identify check box based on the name given beside it using xpath

I wanted to identify the CheckBox based on the name given to it by using the xpath, but was not able to reach till the text uniquely.
The html code is in below. How can I get the dynamic xpath for 'text1' or 'text2' mentioned in the html?
<html>
<body>
<div class="section-content">
<div>
<input class="cls" type="checkbox"/>
text1
</div>
</div>
<div class="section-content">
<div>
<input class="cls" type="checkbox"/>
text2
</div>
</div>
<div class="section-content">
<div>
<input class="cls" type="checkbox"/>
text3
</div>
</div>
<div class="section-content">
<div>
<input class="cls" type="checkbox"/>
text4
</div>
</div>
</body>
</html>
The below code worked for me
driver.findElement(By.xpath("//div[contains(.,'text4')]/input")).click();
To identify the node with text as text1 you can use the following line of code :
WebElement element_text1 = driver.findElement(By.xpath("//div[#class='section-content']/div[contains(normalize-space(), 'text1')]"));
To get identify the Check Box associated with the node with text as text1 you can use the following line of code :
driver.findElement(By.xpath("//div[#class='section-content']/div[contains(normalize-space(), 'text1')]/input"));
Try this:
WebElement body = dr.findElement(By.xpath("/html/body"));
List<WebElement> div = dr.findElements(By.className("section-content"));
for(int i=1;i<div.size();i++)
{
String checkBoxText = dr.findElement(By.xpath("/html/body/div["+i+"]/div")).getText();
if(checkBoxText.equals("text3"))
{
dr.findElement(By.xpath("/html/body/div["+i+"]/div/input")).click();
break;
}
}

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'"))