Selenium - how to select an element with variable text - java

<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+')]

Related

How to select classes that have dash "-" with jsoup?

Suppose I want to select the following html with jsoup:
<p class="foo bar-baz">Hello World!</p>
I can select it from the Document object doc with doc.select("p.foo"). This look for paragraphs with class foo. I want to be more specific so I then try to go with doc.select("p.foo.bar-baz"). I know I can specify additional classes if I separate with dot however in the example above the dash seems to be causing problems. What do I need to do to also select class bar-baz?
Turns out the problem was that I was relying on the html from developers tools in chrome but the html of the Document object was different. It's not the same code but what happened essentially was that chrome would show this:
<p class="foo bar-baz">Hello World!</p>
When the html of the Document object in reality only had this:
<p class="foo">Hello World!</p>
Naturally that was the reason for the null pointer. I then tried to select elements with dashes and it had problem dealing with them (as pointed by luksch in a comment above).
Iam not sure why they would show different html but now I know I can only rely on the Document html to select elements.

Xpath. Unable to select text of label - when another element like <input> is between the <label> tags

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.

Is there a way to call nextElementSibling in Selenium Webdriver with Java?

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!

How to search node by exact text match using Xpath in webdriver

I need a little help regarding searching an exact text using xpath in webDriver.
Suppose i have the html as follows..
<html><body>
<table>
<tr>
<td><button>abcd</button></td>
<td><button>abc</button></td>
</tr>
</table>
</body></html>
Now i want to click button "abc"
I used xpath as //button[contains(text(),'abc')] but it is always performing on button "abcd" as it also contain the text "abc". In this regards I need a predicate or some other procedure which can search exact text instead of containing text.
I also tried with //button[matches(text(),'abc')], //button[matches($string,'abc')], //button[Text='abc')], //button[.='abc')] and many more but none of these worked out to identify "abc" button.
I do not know if there is any problem regarding my xpath version as I'm not aware of the version. But I'm using java 1.6 JDK.
Though my exact scenario is not the example shown but similar logic needs to be applied.
Hence any help or suggestion would be highly appreciated.
I would use next xpath //button[text()='abc']. You have mentioned text() function but I'm not sure syntax was correct. Also you tried to use contains() -- it searches partial text and WebDriver gets first element found. I your case it is <button>abcd</button> button
To find the element 'abcd' you can simply use:
//button[contains(text(),'abcd')]
To find 'abc' use the normalize-space() function which will clean up your text for comparison purposes.
//button[normalize-space(text())='abc']
For exact search:
button[text()='abc']
For pattern matching search:
button[starts-with(.,'abc')]
//button[.="abc"]
The dot before the equality operator will do the text comparison. Another example is /PROJECT[.="MyProject"] from the xPath Java tutorial.
Try with ends-with instead of contains. If the buttons dont have unique attributes, you can add the parent hierarchy as well. Like //table/tr/td[1].
Using something like below worked perfectly fine for me.
//button[(contains(.,'abc')) and not(contains(.,'abcd'))]
For exact search:
.//button[./text()='abc']
Note: make you there is no space is available into

Parsing HTML content with sibling tags in Java (or) Finding content between two <open> tags

Background: I'm writing a Java program to go through HTML files and replace all the content in tags that are not <script> or <style> with Lorem Ipsum. I originally did this with a regex just removing everything between a > and a <, which actually worked quite well (blasphemous I know), but I'm trying to turn this into a tool others may find useful so I wouldn't dare threaten the sanctity of the universe any more by trying to use regex on html.
I'm trying to use HtmlCleaner, a Java library that attracted me because it has no other dependencies. However, trying to implement it I've been unable to deal with html like this:
<div>
This text is in the div <span>but this is also in a span.</span>
</div>
The problem is simple. When the TagNodeVisitor reaches the div, if I replace its contents with the right amount of lipsum, it will eliminate the span tag. But if I drill down to only TagNodes with no other children, I would miss the first bit of text.
HtmlCleaner has a ContentNode object, but that object has no replace method. Anything I can think of to deal with this seems like it must be far too complicated. Is anyone familiar with a way to deal with this, with HtmlCleaner or some other parsing library you're more familiar with?
You can pretty much do anything you want with JSoup setters
Would that suit you ?
Element div = doc.select("div").first(); // <div></div>
div.html("<p>lorem ipsum</p>"); // <div><p>lorem ipsum</p></div>
HtmlCleaner's ContentNode has a method getContent() that returns a java.lang.StringBuilder. This is mutable and can be changed to whatever value you want.

Categories