Reputation: 19
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.
Upvotes: 1
Views: 3205
Reputation: 968
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.
Upvotes: 2
Reputation: 1806
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.
Upvotes: 0
Reputation: 19
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 "));
Upvotes: 0
Reputation: 9058
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()]"
Upvotes: 1
Reputation: 193208
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");
Upvotes: 0