I'm accessing a website with webdriver, and I want to change an element in it.
I want to know how to access an element and change it. In this case I want to add text to an element i.e. transform this:
<span data-id="tag-dist-Lisboa" title="Para eliminar uma das opções, faça duplo clique.">
</span>
Into this:
<span data-id="tag-dist-Lisboa" title="Para eliminar uma das opções, faça duplo clique.">
Some random text
</span>
My main problem has been finding the element.
I have added above some of the HTML, if you need more information please say so.
As I have already posted one answer on your previous question-
Use following code to set value for the span tag-
int textLength = driver.findElement(By.xpath("//span[#data-id='tag-dist-Lisboa']")).getText().length();
if(textLength<=0)
{
WebElement element = driver.findElement(By.xpath("//span[#data-id='tag-dist-Lisboa']"));
JavascriptExecutor js= (JavascriptExecutor)driver;
js.executeScript("arguments[0].innerText = 'Your Text Here'", element);
}
Explanation :-
Find your required span tag with data-id attribute and check if it contains text or not If yes then use that text value as per your choice.
If not then set your required text for that span tag
Let us know is it as per your question or some other you want to do ?
Related
I need to get a text from child tag(html tag: a) which displays only when the data entered is invalid.
if the data enetred is valid, child tag(html tag: a) doesnot display.
how to write an xpath to suit both the scenarios or how to get the text from the above html tags
HTML code looks as below:
<label id="pt" class="test">
some text is displayed
<a href=javascript:void(0);>some text</a>
Some text is displayed
</label>
//'a' tag displays only when there is an for the label in the UI
You have to check for the existence of the a first and then get the text.
Here is the logic.
// get the list of links under label
List<WebElement> links = driver.findElements(By.xpath("//label[#id='pt']/a"));
// check if the link exists
if (links.size()>0) {
//print the link text
System.out.println(links.get(0).getText());
}
You can use this way
try
{
//if element is present do the operations for that scenario here
WebElement alerttext = driver.findelement(by.xpath("//label[#id='pt']/a[1]"));
if(alerttext.isDisplayed()){
// Print the text - alerttext.getText();
}
catch(NoSuchElementFoundException ex){
//if element is not present do the operation for that scenario here
}
Hope this will resolve your problem.
I'm trying to get the price from a product on a webpage.
Specifically from within the following html. I don't know how to use CSS but these are my attempts so far.
<div class="pd-price grid-100">
<!-- Selling Price -->
<div class="met-product-price v-spacing-small" data-met-type="regular">
<span class="primary-font jumbo strong art-pd-price">
<sup class="dollar-symbol" itemprop="PriceCurrency" content="USD">$</sup>
399.00</span>
<span itemprop="price" content="399.00"></span>
</div>
</div>
> $399.00
This obviously resides further within a webpage but here is the java code i've attempted to run this.
String url ="https://www.lowes.com/pd/GE-700-sq-ft-Window-Air-Conditioner-115-Volt-14000-BTU-ENERGY-STAR/1000380463";
Document document = Jsoup.connect(url).timeout(0).get();
String price = document.select("div.pd-price").text();
String title = document.title(); //Get title
System.out.println(" Title: " + title); //Print title.
System.out.println(price);
First you should familiarize yourself with CSS Selector
W3School
has some resource to get you started.
In this case, the thing you need resides inside div with pd-price class
so div.pd-price is already correct.
You need to get the element first.
Element outerDiv = document.selectFirst("div.pd-price");
And then get the child div with another selector
Element innerDiv = outerDiv.selectFirst("div.met-product-price");
And then get the span element inside it
Element spanElement = innerDiv.selectFirst("span.art-pd-price");
At this point you could get the <sup> element but in this case, you can just call text() method to get the text
System.out.println(spanElement.text());
This will print
$ 399.0
Edit:
After seeing comments in other answer
You can get cookie from your browser and send it from Jsoup to bypass the zipcode requirement
Document document = Jsoup.connect("https://www.lowes.com/pd/GE-700-sq-ft-Window-Air-Conditioner-115-Volt-14000-BTU-ENERGY-STAR/1000380463")
.header("Cookie", "<Your Cookie here>")
.get();
Element priceDiv = document.select("div.pd-price").first();
String price = priceDiv.select("span").last().attr("content");
If you need currency too:
String priceWithCurrency = priceDiv.select("sup").text();
I'm not run these, but should work.
For more detail see JSoup API reference
I want to get Selenium with Chromedriver to recognize and import a line of html text into a Webelement variable.
Given this HTML:
<li id="password_rules">
<strong>Password Rules</strong>
<p>The database password rules conform with...:</p>
<ul>
<li>The password can not be the same as the user id.</li>
<li>Password length must be between 8 and 25 characters.</li>
</ul>
</li>
I want to grab the text in the last list element ("Password length must be between 8 and 25 characters.").
This is the java code I'm attempting to use:
WebElement passwordCriteria = driver.findElement(By.xpath("//*[#id = 'password_rules']//*[contains(text(), 'Password length must be between ')]"));
String lineText = passwordCriteria.getText();
When that Java executes, it returns an error saying the element cannot be found:
Exception in thread "main"
org.openqa.selenium.InvalidSelectorException: invalid selector: Unable
to locate an element with the xpath expression //[contains((text(),
'Password length must be between ')] because of the following error:
SyntaxError: Failed to execute 'evaluate' on 'Document': The string
'//[contains((text(), 'Password length must be between ')]' is not a
valid XPath expression.
Any insight is much appreciated.
If you are grabbing a WebElement by it's id, then you don't need your extra specific xPath. id is supposed to be unique by convention. If you have other html elements with the same id, consider changing them to a class.
You should be able to grab the element like this:
WebElement passwordCriteria = driver.findElement(By.id("password_rules"));
If you're committed to finding the element by the id containing some text then the way you should do it is as follows:
WebElement passwordCriteria = driver.findElement(By.xpath("//*[contains((text(),'Password length must be between')]"));
Also, sometimes Selenium will complain if elements are not visible on the page when you try and reference them. Sometimes you need to wait, other times you need to perform some other action to make the text visible before referencing it, like hovering the mouse over a dropdown, etc.
For example
Suppose the html you pasted here is an error message. This error message does not start out as being 'visible', but instead it is shown after the user types their password in incorrectly. In such an instance, Selenium won't let you reference the text from an element inside this div, since it's not currently view-able. Instead, what you would have to do is use Selenium to input the incorrect password in the fields, wait for the error message to be displayed, and then finally reference the WebElement, only after it is able to be seen.
EDIT:
I misread OP's intention. The element that OP is trying to reference is NOT the element with the id, but rather a child of that element. Instead of rewriting my answer, I will point out that #Grasshopper answer has both css and xPath solutions.
You can try these locators if the concerned li is always the last child.
Css - "li[id='password_rules'] > ul > li:last-child"
xpath - "//li[#id='password_rules']/ul/li[last()]"
As per your question as the desired text is within Password Rules you have to induce WebDriverWait with ExpectedConditions as textToBePresentInElementLocated and then retrieve the text as follows :
new WebDriverWait(driver, 20).until(ExpectedConditions.textToBePresentInElementLocated(By.xpath("//li[#id='password_rules']//ul//li"), "Password length"));
String lineText = driver.findElement(By.xpath("//li[#id='password_rules']//ul//li[contains(.,'Password length')]")).getAttribute("innerHTML");
Thank you for the help everyone. I finally got it using the following:
new WebDriverWait(driver, 20).until(ExpectedConditions.textToBePresentInElementLocated(By.xpath("//li[#id = 'password_rules']"), "Password length must be between "));
WebElement passwordCriteria = driver.findElement(By.xpath("//li[#id = 'password_rules']/ul/li[2]);
String lineText = passwordCriteria.getText();
Your original example had // which should only be used at the beginning of an xpath.
I testautomated a small part of Outlook Web App. Here I check a test mailbox that our company sends emails to. Within a certain email there are texts I want to check by using Assert. The problem is that I have difficulties finding the right xpath. The HTML looks like this:
<div align="left">
<font size="2" face="Tahoma">
<br>
Wij hebben uw bouwdepotdeclaratie verwerkt.
</font>
<br>
</div>
To use driver.findElement(By.xpath(xpath)) I used the following xpath first:
//font[contains(text(),'Wij hebben uw bouwdepotdeclaratie verwerkt')]/br, but that gives me just the <br> tag.
Afther that I tried //font[contains(text(),'Wij hebben uw bouwdepotdeclaratie verwerkt')]/text() and that seemed to give me the xpath that I wanted, because in element inspector it highlighted the text Wij hebben uw bouwdepotdeclaratie verwerkt. That is the actual text that I want the selenium webdriver to find and use to store (with .getText()) in a String. But when I used that with driver.findElement(By.xpath(xpath)).getText() it gave me a NoSuchElementException.
What did I do wrong? What would be the right xpath that I can use with the webdriver to get the text?
The way your HTML is set up and given what you want, you want to get the FONT tag. In your first XPath you are pulling the BR tag, which is why it didn't work. Your second XPath is using text() which, if I remember correctly, isn't supported by Selenium. The easier way is to modify your first XPath to just get the FONT tag (just remove /br).
//font[contains(text(),'Wij hebben uw bouwdepotdeclaratie verwerkt')]
Using this XPath, the code below should work.
String s = driver.findElement(By.xpath(xpath)).getText().trim();
I added trim() to remove the BR spacing and other possible whitespace. You can remove it if it's not needed/wanted.
Based on OP's feedback, I would use the XPath above but I would change the assert to
By locator = By.xpath("//font[contains(text(),'Wij hebben uw bouwdepotdeclaratie verwerkt')]");
List<WebElement> e = driver.findElements(locator);
Assert.assertTrue(e.size() > 0, "Verify text exists in email");
let me know did it help you or not,
If the current node is the font element, then something like this:
text()|span
otherwise you have to always combine with | the two complete XPath - the one for text and the one for span, e.g.:
font/text()|font/span
if the current node is just above font - or
//a[text()='View Larger Map']/../../../../div[contains(#class, 'paragraph')][3]/font/span|//a[text()='View Larger Map']/../../../../div[contains(#class, 'paragraph')][3]/font/text()
if starting from the root with some complex selection criteria.
If you have complex paths like the last one probably it is better to store a partial one in a variable - e.g. inside an XSLT:
<xsl:variable name="font" select="//a[text()='View Larger Map']/../../../../div[contains(#class, 'paragraph')][3]/font"/>
. . .
<xsl:for-each select="$font/span|$font/text()">
. . .
</xsl:for-each>
Another possibility is to do something like this:
//a[text()='View Larger Map']/../../../../div[contains(#class, 'paragraph')][3]/font/node()[name()='span' or name()='']
that works because name() returns an empty string for text() nodes - but I am not 100% sure that it works that way for all XPath processors, and it could match by mistake comment nodes.
below xpath should work
//font[contains(.,'Wij hebben uw bouwdepotdeclaratie verwerkt')]
or
//font[contains(text()[2],'Wij hebben uw bouwdepotdeclaratie verwerkt')]
As you were able to figure out the WebElement through the xpath //font[contains(text(),'Wij hebben uw bouwdepotdeclaratie verwerkt')]/text() but through your script you are getting NoSuchElementException you need to induce WebDriverWait for the element to be visible as follows :
String myText = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("xpath_of_the_element"))).getText();
Update
As you are getting TimeoutException as an alternative you can induce WebDriverWait for the parent element to be visible and use Java Split method to extract the desired text as follows :
String myText = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//font[contains(text(),'Wij hebben uw bouwdepotdeclaratie verwerkt')]")));
String[] myTextParts = myText.split(Pattern.quote("<br>"));
String myPart = myTextParts[1];
System.out.println(myPart);
I am trying to get the rating of each movie but I cant seem to use the select method in the right way. I am trying to get the 7.0 part from the webpage:
http://www.imdb.com/title/tt0800369/
<div class="star-box giga-star">
<div class="titlePageSprite star-box-giga-star"> 7.0 </div>
I am using this line in java:
Element rating = doc.select("star-box giga-star").first();
System.out.println(rating);
Thanks in advance!
You can select an element by its class using .star-box-giga-star, and use text() to get the textual content of the element.
doc.select(".star-box-giga-star").text();
Problem with your selector is that you are using ancestor child selector instead of .class or element.class like div.star-box. Notice that to use multiple class you need to use element.class1.class2 or just .class1.class2 if you don't want to specify element.
Also if you want to specify parent child relationship you will have to use > so try maybe something like
Document doc = Jsoup.connect("http://www.imdb.com/title/tt0800369/").get();
Element rating = doc
.select("div.star-box.giga-star > div.titlePageSprite.star-box-giga-star")
.first();
System.out.println(rating);
Unfortunately this will print
<div class="titlePageSprite star-box-giga-star">
7.0
</div>
so if you want to get only text contend from that element use System.out.println(rating.text());
BTW since there is only one element with class star-box-giga-star you can just use
String rating = doc.select(".star-box-giga-star").text();
as shown in Alex answer