I am using Selenium and Java to write a test, when I use the code below:
List<WebElement> elements = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy
(By.xpath("//div[.//span[text()='Map']]//*")));
for (WebElement e : elements) {
System.out.println("=>" + e.getTagName() + "<=");
}
it shows all the web elements in that <div> tag.
Result:
=>span<=
=>div<=
=>div<=
=>path<=
=>path<=
=>span<=
As you see, some of the elements tag-name is path but when I use the code below it says that I could not find the element.
List<WebElement> elements = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy
(By.xpath("//div[.//span[text()='Map']]//path")));
It not easy to find the real issue with out knowing your HTML structure.
While I think there is a issue in your xpath
Try below xpath
//div//span[text()='Map']//path
Hope it will help you :)
By.xpath("//div[.//span[text()='Map']]//* will return all the decedents of span[text()='Map'] in the html hierarchy.
For example, this html structure will produce the same results you have
<div>
<span>Map</span>
<div></div>
<div>
<path></path>
<path></path>
</div>
<span></span>
</div>
As you can see, <path> is not <span> direct child, so By.xpath("//div[.//span[text()='Map']]//path is not a valid xpath.
The issue was related to some web elements that Selenium cannot navigate, the web element that I was trying to catch was inside a svg web element which is not detectable by Selenium have a look here this is exactly what was happening to me.
Related
I cannot find any regular expression to make it work.
What I need to archive
In a herarchy, I would like to get all the children (including several levels) that contains some specific classes.
For example: I would like the WebElements with classes "black" or "white"
<div class="initial-div">
<div class="red">
<div class="white">Hello</div>
</div>
<div class="black">Goodbye</div>
</div>
It should be able to find both the "Hello" and "Goodbye" divs, as they are both children.
My approach
I am trying to do it using Selenium and searching by the xPath. My expression looks like:
List<WebElement> nodes = initialNode.findElements(By.xpath("//*[#class='black' or #class='white']"));
But I am getting all the time "Invalid Expression exceptions" or no results.
Could someone give me a hand with this?
Thank you in advance!
SOLVED!
It was more complicated that I though, but I finally make it. I share with you, in case that someone is searching for this at any time:
List<WebElement> nodes = initialNode.findElements(By.xpath("*//descendant::div[contains(#class, 'black') or contains(#class, 'white)]"));
List<WebElement> nodes = initialNode.findElements(By.xpath("*//descendant::div[contains(#class, 'black') or contains(#class, 'white)]"));
If the element has two xpath, then you can write two xpaths like below:
xpath1 | xpath2
Eg:
//div[#class="black"] | //div[#class=“white"]
It will choose any one xpath
Here is what I'm trying to do:
I have some links on a webpage with this pattern:
/html/body/div[4]/div/div/section/div[2]/div[3]/div/div1/div1/div/div[2]/a
/html/body/div[4]/div/div/section/div[2]/div[3]/div/div1/div[2]/div/div[2]/a
/html/body/div[4]/div/div/section/div[2]/div[3]/div/div1/div[3]/div/div[2]/a
/html/body/div[4]/div/div/section/div[2]/div[3]/div/div1/div[4]/div/div[2]/a
However, I also have other links within the same web page that have a similar path but not exactly following the same pattern:
/html/body/div[4]/div/div/section/div[2]/div[3]/div/div[3]/div/div1/div1/div/div[2]/a
How can I get just the links which follow the first pattern displayed and ignore the other ones?
Ps: I'm using Selenium Webdriver and Java and this is the update question with the html for the links
<div class="col-sm-6 half-tile">
<div class="outside-caro">
<div class="grey-overlay">
<div class="inside-caro" style="background-image:url(' https://resources/images/metabolism.jpg'")>
</div>
</div>
<div class="tile-content">
<h4 class="module title-long-card">Healthy Weight Loss</h4>
<p class="module line-clamp">This online eLearning programme is designed to help you make smart decisions when it comes to dieting and to be aware of the pitfalls.</p>
<a class="more-button" href="/application/res-courses/overview?id=23">Learn More<i style="font-size: 10px;padding-left: 5px; "class="fa fa-chevron-right" aria-hidden="true"></i></a>
</div>
</div>
</div>
Thanks very much.
I'm not quite following what you're really hoping for from your description, but I can make some guesses.
The quick answer is, just always give the full path.
But there are ways to make things a little easier to code. There are a couple ways you can create a pointer on the page and to only look for things beyond that point. The most straightforward is using simple string concatenation:
String pointer = "/html/body/div[4]/div/div/section/div[2]/div[3]/div/div[1]";
WebElement tag1 = driver.findElement(By.xpath(pointer + "/div[1]/div/div[2]/a"));
WebElement tag2 = driver.findElement(By.xpath(pointer + "/div[2]/div/div[2]/a"));
The other is to declare that pointer as a WebElement, and then use it as a base for all future findElements:
WebElement pointer = driver.findElement(By.xpath("/html/body/div[4]/div/div/section/div[2]/div[3]/div/div[1]"));
WebElement tag1 = pointer.findElement(By.xpath("./div[1]/div/div[2]/a"));
WebElement tag2 = pointer.findElement(By.xpath("./div[2]/div/div[2]/a"));
Note the dot at the beginning of the xpath to say "Use this node as your starting point".
Now, what I think you're really trying to accomplish to to make a list of all the anchors, not just pick them one by one. As in "get all the link that match one pattern but not a different but similar pattern". For that, you could just do a variation of either of the two above methods. For instance:
WebElement pointer = driver.findElement(By.xpath("/html/body/div[4]/div/div/section/div[2]/div[3]/div/div[1]"));
List<WebElement> tags = pointer.findElement(By.xpath("./div/div/div[2]/a"));
This will pull in all the links that match the pattern into a List. There are a couple things to take note:
The first element is just div, not div[1] and div[2]. since that seems to be the only thing changing in the pattern.
Most likely, the language you will use to script this is 0-indexed. So div[1] is tags.get(0).
I have a solution to problem and i hope it will help you.
You just have to identify a single parent for all 4 links that you mentioned above. And i feel you can use this locator as parent node /html/body/div[4]/div/div/section/div[2]/div[3]/div/div[1]/div[1].
Please find my code..
System.setProperty("webdriver.chrome.driver","Drivers/chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("http://www.abodeqa.com/2015/08/26/finding-child-elements-in-webdriver-using-findelements/");
Thread.sleep(3000);
WebElement parent = driver.findElement(By.xpath("//section[#class='secondary clearfix']"));
List<WebElement>childernNodes = parent.findElements(By.xpath("./aside//a"));
System.out.println("Total: "+childernNodes.size());
for(WebElement value: childernNodes){
System.out.println(value.getAttribute("href"));
}
WebElement pointer = driver.findElement(By.xpath("/html/body/div[4]/div/div/section/div[2]/div[3]/div/div[1]"));
// Generic path to simulate the change in the xpath for the elements of the following pattern:
// WebElement tag1 = pointer.findElement(By.xpath("./div[1]/div/div[2]/a"));
// WebElement tag2 = pointer.findElement(By.xpath("./div[2]/div/div[2]/a"));
List<WebElement> linksList = pointer.findElements(By.xpath("./div/div/div[2]/a"));
for (WebElement link : linksList) {
System.out.println(link.getAttribute("href"));
}
I am having a problem in clicking the link text given inside a span tag.
html code :
<div id="menu" style="width: 1752px;">
<div class="dd_menu" dd_event_id="dd_event_2">
<a class="dd_menu_menu_entry dd_menu_entry_clickable" href="javascript:void(0);" style="left: 3px; width: 111px;" dd_menu_id="0">
<a class="dd_menu_entry dd_menu_entry_clickable" href="javascript:void(0);" style="left: 114px; width: 131px;" dd_menu_id="1">
<span class="text" style="background-color: rgba(0, 0, 0, 0);">FirstMenu</span>
I need to click on the text 'FirstMenu' .
I have used the xpath : .//*[#id='menu']/div/a[2]/span
It does not seem to work. How do I fix it?
If your requirement is to "click on the link FirstMenu", then you should use that as the locator. No need to mess around with XPath.
driver.findElement(By.partialLinkText("FirstMenu")).click();
The .partialLinkText() locator strategy should account for any extra whitespace padding due to the extra span element.
Your xPath returns span element so you're clicking that span. To make your xpath return a link ament your query to the following:
//*[#id='menu']/div/a[span]
This query returns a "link" that has span element as a child.
Try to use below xpath :-
//span[contains(.,'FirstMenu')]
If it doesn't work then there may be any frame present. You need to switch it on first.
Please let me know if there is more element with name FirstMenu on DOM
Hope it will help you :)
The problem got solved by using the same xpath i specified above with the usual syntax driver.findElement(By.xpath("//*[#id='menu']/div/a[2]/span")).click(); after i gave the order by which testcases have to be executed and using #Test(priority=something) and giving some implicit waits.
Thank you all for the suggestions.
regards,
roma
It is not good to use xpath. If the html of the page is changed your code would stop working. Try with css selector.
This is is simple code and you can modify it for you case:
var collection = driver.getelementsBy(By.cssSelector('div#menu div'))
It should return you collection with elements
And after that you can iterate through collection and find the element you want to click.
Hope the answer helps you.
I am having a weird requirement. I am having a div class named "expandThisSection". And I have
<div id="requiredAccessoriesContentPlaceHolder" class="expandThisSection">No required accessories are available for this product.</div>
<div id="requiredAccessoriesContentPlaceHolderMeasurement" class="expandThisSection"> </div>
<div id="optionalAccessoriesContentPlaceHolder" class="expandThisSection">No optional accessories are available for this product.</div>
<div id="optionalAccessoriesContentPlaceHolderMeasurement" class="expandThisSection"> </div>
<div class="expandThisSection">
<div style="width:95%">mytext</div>
<ul class="movePos">…</ul>
<div><b>test</b></div>
<div><b>abc</b> Get this text</div>
<div id="vendLogo">…</div>
</div>
<div class="expandThisSection">
<table>...</table>
</div>
I want the content of the div that has style of 95% width.That is value I want is "mytext". But I am not able to find out xpath for the same.
Also I want xpath for finding the div content just above div with id="vendLogo". That is I want "Get this text".
NOTE: ITS ASSURED THAT THIS Bold tag WILL CONTAIN "abc"
How to do it? I am using selenium with Java
Got the first one. Not able to get second one.
Code:
List<WebElement> currentSkuDescription = driver.findElements(By.xpath("//div[#class='expandThisSection']/div"));
for(WebElement currentItem: currentSkuDescription) {
WebElement descriptionBlock = currentItem.findElement(By.xpath("//div[contains(#style, 'width:95%')]"));
description= descriptionBlock.getText();
}
Try dropping the #class='expandThisSection' because the div you want does not have that class attribute (it's parent does). Also, an exact match may be possible.
By.xpath("//div[#style='width:95%']
By.xpath("//div[contains(#style, 'width:95%')]
Either of those should work. If you want to make sure you are grabbing the right one, relative to the parent, use XPath axes...
//div[contains(#class, 'expandThisSection')]/child::div[contains(#style, 'width:95%')]
If you to search for the div by a specific text (in this case 'mytext') this you can use this xpath:
"//div[text()[contains(.,'mytext')]]/ancestor::div[#class='expandThisSection']"
Or if you want by the styling, the you can use this xpath:
"//div[#style='width:95%']/ancestor::div[#class='expandThisSection']"
Note that the second xpath will only work where the inline styling is done on the tag.
For the second query, try this xpath:
"//div[#id='vendLogo']/preceding-sibling::div[1]"
To get the specific text you require, you can do the following:
String text = driver.findElement(By.xpath("//div[#id='vendLogo']/preceding-sibling::div[1]")).getText();
text.replace(div.findElement(By.tagName("b")).getText(), "");
I'm having trouble reading a link inside a div.
Ok, here's what the div looks like:
<div id="AjaxStream" style="clear: both">
<a target="_blank" href="http://www.something.com/">
<img height="370" width="752" border="4" usemap="#Link" src="somefile.png">
</a>
</div>
The following code, to find the div works perfectly fine.
(I tried element.getAttribute("id") - which returned "AjaxStream")
WebElement element = river.findElement(By.xpath("//html/body/div/div[2]/div/div[11]"));
And here is what's not working:
WebElement element = driver.findElement(By.xpath("//html/body/div/div[2]/div/div[11]/a"));
This should actually fine the link-element, but it doesn't. Any ideas?
Thanks in advance.
##Edit:
Nevermind - I fixed it. The problem was that the element wasn't loaded. I added a Thread.sleep(1000) before trying to find the element - and now it works perfectly fine.
try
WebElement element = driver.findElement(By.xpath("//div[#id='AjaxStream']/a"));
String link = element.getAttribute("href");
//I need 6 characters but it's a 1 "char" fix
Have a look at your xpath...to me that is unreadable. If someone comes in later in a few months, are they able to translate that xpath in to tag you're looking for? A better solution would be a to add an id attribute to the tag you are interested, and find it by that ID.