How to find an element having random id attribute through Selenium - java

How do I locate the input element by id where the last 2 numerical digits change randomly?
<input id="start-time-hours-c31" class="focused" name="startTimeHours" value="" placeholder="hh" maxlength="2" type="text">

Quick answer
When last 2 numerical digits change randomly,
driver.findElement(By.xpath("//input[contains(#id,'start-time-hours-c')]"));
Using 2 attributes of Input tag,
driver.findElement(By.xpath("//input[#name='startTimeHours' and #class='focused']"));
Please let us know if it resolved your query.

As the last 2 characters of the id attribute changes randomly, additionally you need to consider some other attributes as well and you can use either of the following Locator Strategies:
cssSelector:
WebElement elem = driver.findElement(By.cssSelector("input[id^='start-time-hours-c'][name='startTimeHours']"));
xpath:
WebElement elem = driver.findElement(By.xpath("//input[starts-with(#id, 'start-time-hours-c') and #name='startTimeHours']"));

As the html also has a name tag you can find the element by using that name tag, like:
WebElement element = driver.findElement(By.name("startTimeHours"));
And if the name tag startTimeHours is not unique on the page, then you can find the element by using the below xpath:
WebElement element = driver.findElement(By.xpath("//input[contains(#id,'start-time-hours')]"));

Agreed with #TheSociety answer, you can also be used as the combination of name and id
//input[contains(#id,'start-time-hours-c') and contains(#name,'startTimeHours')]

Use contains, sibling or Ancestor when the value is dynamic.
xpath - //input[contsins(#id,'start-time-hours-c')]

You can use either of them:
//input[starts-with(#id,'start-time-hours-c')]
(or)
//input[contains(#id,'start-time-hours-c')]
if the above returns a single webelement then you can use it or else if it returns multiple elements go for name attribute in the xpath.

Related

Java Selenium - Select a WebElement based on value attribute

I was wondering if there was a way to find an element on a webpage based on the value attribute.
<option value="abc">Some text here</option>
<option value="bcd">Some text here</option>
I figured I could just create a list of WebElements based on the tag name and traverse each one using .getAttribute("value"), but I was wondering if there was a more effective way of doing this similar to the way you can find an element based on its text using:
driver.findElement(By.xpath("//*[contains(text(), '" + term + "')]"))
You can do this:
driver.findElement(By.cssSelector("[value=\"abc\"]"))
and you would change the value of value depending on what you were trying to find.
To locate the element with value="abc" on a webpage `based on the value attribute of abc you can use either of the following Locator Strategies:
css-selectors:
driver.findElement(By.cssSelector("option[value='abc']"))
xpath:
driver.findElement(By.xpath("//option[#value='abc']"))

org.openqa.selenium.InvalidSelectorException: invalid selector while trying to locate an element

My element is displayed as:
<a class="main-item" href="#">Business Loans</a>
xpath is:
//*[#id='main-nav']/ul/li[1]/a[1]']
This returns invalid element locator
//*[#id='main-nav']/ul/li[1]/a']
driver.findElement(By.xpath("//*[#id='main-nav']/ul/li[1]/a[1]']"))
I am trying to get the element.
Welcome to SO. Here is the simple xpath.
//*[#id='main-nav]//a[#class='main-item' and .='Business Loans']
If you want to use the one which you mentioned, here is the corrected.
driver.findElement(By.xpath("//*[#id='main-nav']/ul/li[1]/a[1]"))
Try contains function in xpath, it can extract all the elements which matches a particular text value
//a[contains(text(),'Business Loans')]
This error message...
org.openqa.selenium.InvalidSelectorException: invalid selector
...implies that your xpath was not a valid one.
You can't use the single quote i.e. ' or the double quote i.e. " for both By value and attribute values.
Solution
You can use either of the following Locator Strategies:
cssSelector:
WebElement element = driver.findElement(By.cssSelector("#main-nav a.main-item"));
xpath:
WebElement element = driver.findElement(By.xpath("//a[#class='main-item' and text()='Business Loans']"));

Use Selenium Java to get string text from HTML

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.

Python/Selenium - Can't get HREF value of a tag

So I have this HTML element:
<h2 class="post-title">
This a link to Google!
</h2>
I am using driver.find_elements_by_class_name('post-title') to find this piece of HTML.
But how can I extract only the value of the "href" tag?
I've tried:
driver.get_attribute('href')
returns 'none'
Thanks
You have 2 problems:
you're trying to find h2 elements instead of a
you're trying to get attribute value from WebDriver instance
Try below code to get required output:
driver.find_element_by_css_selector('h2.post-title>a').get_attribute('href')
href belongs to <a> tag; so first you have to reach till that element as following:
elem = driver.find_element_by_xpath('//h2[#class="post-title"]/a')
attribute_value = elem.get_attribute('href')
Indeed the sibling whose tag is h2 has no href attribute and this is the one you target via searching elements by_class_name('post-title') . It is the sibling <a></a> which does.
What about searching by xpath ? If 'post-title' is a unique class identifier, you can search for your element as follows
xpth = "//*[#class='post-title']/a"
a_element = driver.find_element_by_xpath(xpth)
and finally
href = a_element.get_attribute('href')
Something you could do from what you (almost) have
h2_element = driver.find_element_by_class_name('post-title')
a_element = h2_element.find_element_by_tag_name("a")
href = a_element.get_attribute('href')

Selenium WebDriver Java locating an element with dynamic ID

I'm currently having troubles on locating this element with dynamic id. Here are the screenshots below.
What i have right now is the element of Variables (8) //a[contains(.,'Variables (8)')]. What i need is only the "Variables" since the number 8 is always changing.
Any thoughts on this? Any ideas will be much appreciated. Thanks
First of all 'Variables (8)' is not Id, its text. Id's are not dynamic since they represent unique identifier for the web element. This will look like this (based on your example):
<div class="field" id="fieldId">
As for your question, you can find the element by partial linked text:
driver.findElement(By.partialLinkText("Variables"));
This will give you the a element no meter what the number is.
You can try the below:
driver.findElement(By.cssSelector("a:contains('Variables')"));
If you want the word "Variables" , use the below:
String str = driver.findElement(By.cssSelector("a:contains('Variables')")).getText().split(" ")[0];
Hope this Helps....
What I understand from your question is you want to locate the <a> tag which contains text "Variables".
Try using this xpath:
//div[#class="field"]/a[contains(.,"Variables")]
This xpath will locate the <a> tag after the div tag with class name =field and Contains method with <a> tag will find the element which contains text "Variables"
try this:
String varText = driver.findElement(By.cssSelector("div.triggerFirst>div:nth-child(1)>a")).getText();

Categories

Resources