I am working with a really messy page structure and the fragment that I am stuck on looks something like this:
<div>
<h3>...</h3>
<ul>...</ul>
<h3>...</h3>
<ul>...</ul>
...
</div>
I want to get one of the <ul> elements, so I could dig deeper into it and retrieve the actual value that I really need from there (it has a table inside it). Currently I am able to get the <h3> element that precedes the <ul> I am looking for. Since ul-elements don't have any unique identifiers that I could use to get them directly, I am hoping to achieve it by getting the element that comes after the h3-tag (on the same level). Is there a way to get what seems to be nextElementSibling?
Thank you!
NB! h3 and ul elements don't have strict sequence number - there may or may not be a few elements before them, so getting an n-th child does not seem to be an option there.
You can achieve this with either xpath or by executing some javascript.
Xpath:
driver.find(By.xpath("//div/h3/following-sibling::ul[1]"));
JavaScript:
JavaScriptExecutor jsExec = (JavaScriptExecutor)driver;
WebElement ulElement = jsExec.executeScript("return arguments[0].nextSibling;", driver.find(By.cssSelector("div h3")));
Hope that helps!
Related
Java dev and new to Xpath. Googled and RTFM-ed quite a bit but stuck. Company has a large webapplication written in Java, using the Java Wicket framework. Using Selenium in combination with Cucumber and Junit for testing. Hence Lots of Xpath expressions are needed to be written. Stuck with the following.
A screen with a form and two toggles () and text behind it . Relevant snippet.
<label>
<input id="idf1" name="removeConditionViaTreeStep:resultsRadioGroup" value="radio3" checked="checked" type="radio">
Safe to delete
</label>
<label>
<input id="idf2" name="removeConditionViaTreeStep:resultsRadioGroup" value="radio4" type="radio">
Unsafe to delete
</label>
Note: Using the Wicket framework means that the attributes id and value are/can be different each time the application runs so can NOT use them. Can NOT change the html either.
Plan A
I wanted to select a specific toggle (and emulate clicking/selecting it) by using the label text as a uniq selector but the fact that between the tags there are .. gives me problems. In clean label situations I can select a certain label without problems.
Can't get things like //label[contains(text(),'Unsafe to delete')] to work in this case.
Gave up and went for plan B.
Using firepath addon for firebug for testing and came up with the following: //input[#name='removeConditionViaTreeStep:resultsRadioGroup']
This results in firepath in two matches. I hoped to use something like [2] to select the second toggle, but could not figure it out.
Plan C - resorting to Java and Xpath worked.
List elements = findElementsByXpath("//input[#name='removeConditionViaTreeStep:resultsRadioGroup']");
elements.get(1) // select second toggle.
Have this feeling "//label[contains(text(),'Unsafe to delete')]" does not work because everything is streamed and nothing is held in memory by the Webdriver of selenium. Hence the element breaks the stream or something like that......
Perhaps someone can give a few hints and pointers or even a solution for plan A and B.
Edit corrected the closing parenthesis typo as mentioned by Bill Hileman.
I know you said you can not change the HTML, but maybe you can run the application in wickets development mode on the test environment? This way, if I remember correctly, wicket:id should be rendered and you would have an easier time to select elements.
Your xpath attempt as you typed it is:
//label[contains(text(),'Unsafe to delete']
Unless that was a typo here only, you missed a closing parenthesis.
//label[contains(text(),'Unsafe to delete')]
That xpath should work.
<div class="order-number">
<h3>"Order number: "<strong>123-123123</strong> </h3>
</div>
Any idea how to select the order number? I use Selenium 2. I tried this:
driver.findElement(By.xpath(".//*[matches(text(),'\\d+-\\d+']"));
But it's not working. Does Xpath2 support regex?
The number of the order is always different, but the style of XXX-XXXXXX is always the same.
A different approach would be to search by CSS selector instead:
By.cssSelector(".order-number H3 STRONG")
It's a bit more frail if the page structure changes though.
A better solution (if you are able to change the page code) is to put an ID on the <strong> tag and use By.id. That's much quicker, less frail, and more readable than XPaths or CSS-Selectors.
Simply try
driver.findElement(By.xpath("//div[#class='order-number']//strong")).getText();
Also note that selenium supports matches() in XPath. The cause of your issue seem to be missing closing parenthesis:
now
matches(text(),'\\d+-\\d+'
should be
matches(text(),'\\d+-\\d+')
working one
//h3/strong[matches(text(),'\d+-\d+')]
I have this code
WebElement element = driver.findElement(By.id("j_idt9:usuario"));
I want to know how I can use XPath to search for a specific ID. In this case, I want to search for the "usuario" portion because the "j_idt9" portion changes. I know that it can be done using a CSS Selector but I am required to use XPath.
You should tell your professor that CSS selectors are not just for classes... and if s/he really did say that, they should be embarrassed and go do some reading. They can start with these two references:
https://www.w3.org/TR/selectors/#selectors
https://saucelabs.com/resources/articles/selenium-tips-css-selectors
If you have to use XPath, it would look like
"//*[ends-with(#id, 'usuario')]"
You'd be better off using a CSS selector because it's faster and has better, more consistent browser support. It would look like
"[id$='usuario']"
In general, your locator strategy should look like this...
By.id
By.linkText, By.partialLinkText
By.cssSelector
then as a last resort, By.xpath
By.xpath should only be used when the other methods won't work. Cases like you need to find an element by the text it contains or you have to do some parent/child shifts that CSS can't do.
I am currently using JSoup CSS selection to get a list of some elements in an HTML document.
Though to verify the robustness of my algorithm I have to know in which order the elements do get browsed and, therefore, returned.
My concern is strictly linked to nested elements. If i do search for all the elements in a document which is like the following:
<div> Something <span style='color:red;'>special</span> for me </div>
and i run in JSoup:
Document doc = Jsoup.parse(myCode);
Elements els = doc.select("*");
in which order will those two elements be traversed, and therefore returned? I am currently looking at the documentation page for the select method, but no information is provided on the traversal order. Is there any more precise reference I can look at?
Clearly i can proceed in a trial-and-error to infer the ordering, but I would like to know if this is already known/someone has already digged into it, since I do not know the HTML structure of the documents I have to parse beforehand.
Thanks!
I am trying to achieve the following:
If a specific element exists, click it and go back to the home page.
Otherwise, just go back to home page so the test continues on without failing
I have come up with the code below, this but it is really slow. I am not sure there is any better way to implement this? Any comments will be appreciated!!
boolean exists = driver.findElements( By.id("xxx")).size() != 0;
if (exists)
{
driver.findElement(By.id("xxx")).click();
driver.findElement(By.cssSelector("xxx")).click();
}
else
{
driver.findElement(By.cssSelector("xxx")).click();
}
I worked out what's slowing down the performance. It is this line:
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
Because of that statement, it will wait for the element to be verified for 30 seconds.
After changing it to:
driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
.. it now works like a charm...:)
What are you using for CSS selectors? You might be able to improve the performance just by tweaking those. Another thing that will slow it down is when the page has too many DOM elements.
It would be helpful to see the CSS selectors and an example of what DOM elements you are scanning over.
For example, if your page is full of 1000 DIV elements, with a class like this:
<div class="smallItem">...</div>
<div class="largeItem">...</div>
<div class="smallItem">...</div>
and you use a css selector like this:
".smallItem"
to select all of the DIV elements, it has to scan over each DOM element and compute on the class attribute.