Finding an element by XPath in Selenium - xpath

I am trying to use Selenium to navigate a webpage. There is a button I am trying to get to via its xpath. For other buttons on the site, it works fine. But for this particular one, I keep getting the error that the element can't be located. Firebug is just giving me the xpath in this format: //*[#id="continueButton"].
I notice that the button has wrappers around it. They are structured like
<div class = "cButtonWrapper">
<div class = "cButtonHolder">
<input type="image" id="continueButton" name="Continue" alt="Continue" src="/store/images/btn_continue.gif" value="Continue">
</div>
</div>
Could the wrappers around the button have anything to do with not being able to locate it?

Maybe the <input> element cannot be properly located by XPath because you are using invalid HTML. Try using <input id="continueButton"/> or <input id="continueButton"></input> in your page source.

Related

Finding a weird symbol in Capybara

I'm currently trying to find a symbol on a page. I have the HTML tag and the find method that I'm using. However it's not able to find this symbol. I'm not sure what I'm doing wrong to do so.
<div class="ui-grid-selection-row-header-buttons ui-grid-icon-ok clickable bg-pristine bg-valid bg-scope bg-not-empty bg-touched" bg-class="{'ui-grid-row-selected': row.isSelected}" tabindex="0" bg-click="selectButtonClick(row, $event)" bg-keydown="selectButtonKeyDown(row, $event)" role="checkbox" bg-model="row.isSelected" aria-checked="true" aria-invalid="false"> </div>
As you can see this is a weird html tag. I'm trying to avoid full xpath if possible.
Here is what I"m doing.
find(:css, "ui-grid-selection-row-header-buttons[button = 'selectButtonClick']")
To identify the symbol on the page you can use either of the following locator strategies:
find(:css, ".ui-grid-selection-row-header-buttons[bg-click^='selectButtonClick']")
or
find(:css, ".ui-grid-selection-row-header-buttons[bg-model$='isSelected']")

not able to click radio button element by xpath in selenium using python

Below is my HTML
<div id="slectrole" class="collapse in" role="tabpanel" aria-labelledby="selectrole">
<div class="panel-body">
<div class="dropdown">
<input class="search-control jsSayt jsRolesFreeText" onfocus="this.placeholder = ''" onblur="this.placeholder = 'Eg: Delivery, BPO, Driver'" placeholder="Eg: Delivery, BPO, Driver" value="" aria-expanded="false" aria-haspopup="true" data-toggle="dropdown" type="text">
<ul class="jsSaytList jsRolesFilter">
<li id="jsFilter_subRole_1" class="checkbox-inline jsFilterSubRole jsRoleValue_1" data-value="Accountant">
<input id="Accountant" class="radio-custom jsFilterRadio jsRole" value="Accountant" name="Role" data-roleid="1" type="radio">
<label class="radio-custom-label" for="Accountant">Accountant</label>
Below is the code I am using to click the radio button:
wait.until(EC.visibility_of_element_located((By.XPATH, "//div[#id='slectrole']/descendant::li[#data-value='Accountant']/label[#for='Accountant']")))
driver.find_element_by_xpath("//div[#id='slectrole']/descendant::li[#data-value='Accountant']/label[#for='Accountant']").click()
The code runs ok but it does not select the radio button.
OK, so I can understand your frustration, I tried your code and wasn't able to .click() (select) the element when located via xpath. See bellow print-screen:
As you can see, it was only clicking the radio-button when issuing a .click() via a CSS-located element.
Question No.1: Are you bound to the xpath locator strategy in one way or another?
If NOT, then just use a regulat CSS selector: 'input[id="Accountant"]'.
Else, you have to figure out what is wrong with the website you are testing, or switch to another WebElement locator strategy. (e.g.: ID, Class, CSS, LinkText, etc.)
If you would opt to go with the CSS locator-strategy, then your code would look like this:
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "label[for='Accountant']")))
driver.find_element_by_css("input[id='Accountant']").click()
Alternatively, you can try to click on the <label> tag attached to the radio-button, which in my console works the same way:
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "label[for='Accountant']")))
driver.find_element_by_css("label[for='Accountant']").click()
Explanation: In a real-life scenario, you can select the radio-button both via the actual radio-button, or via its label. That's why your solution worked.
Question No.2: Why are you using such a long xpath selector?
In order to have a optimal selector, you should ALWAYS go with the shortest, combination of tags/attributes that will UNIQUELY identify your target element. Else you will be susceptible to website changes, flaky test cases, etc.
You can perform the click on the drop down and then wait for the radio button to appear, before clicking it. Hence, try following:
driver.find_element_by_xpath("//div[#id='slectrole']/div/div[#class='dropdown']/input[1]")).click()
wait = WebDriverWait(driver, 10)
wait.until(EC.visibility_of_element_located((By.XPATH, '//div[#id='slectrole']/descendant::li[#data-value='Accountant']/input[1]')))
driver.find_element_by_xpath("//div[#id='slectrole']/descendant::li[#data-value='Accountant']/input[1]").click()
Let me know, if above code works for you.

How to get value from a placeholder using xpath

All of the elements are dynamic. I can see only Placeholder which is unique from the following html:-
<input
id="ext-gen1617"
type="text"
size="20"
class="x-form-field x-form-text x-form-focus"
autocomplete="off"
aria-invalid="false"
placeholder="Gender"
data-errorqtip=""
role="textbox"
aria-describedby="combobox-1166-errorEl"
aria-required="true"
style="width: 78px;"
/>
I need to get the value displayed in
placeholder="Gender".
I tried using
//input[#placeholder='Gender']
But my webdriver script failed to identify it.
Can anyone please help me out with possible solution to it?
String s=driver.findElement(By.xpath("//input[#placeholder='Gender']")).getAttribute("placeholder");
System.out.println(s);
To get an attribute for a filed, you can use the .getAttribute() method.
I assume you are dealing with (front end)script generated web elements, then you must need to embrace lean way of thinking. Don't try to pull out a web element by it's property alone. If you are not getting them try to build a xpath from its parent or siblings.
say, the HTML goes like this,
<div id="somestatic id">
<div id="xyz">
<input name="dynamic one"/>
</div>
</div>
Then you can build a xpath as ,
//*[#id='staticID']/div/input
for the HTML,
<div id="staticID"></div>
<input name="dynamic one"/>
the xpath is ,
//*[#id='staticID']/following-sibling::input
similarly there are n number of option available. Give them a try
Try
driver.findElement(
By.cssSelector("input[id*='ext-gen']")
).getAttribute("placeholder")
Let me know is the above statement is working or not.
The best way is to find the element with CSS selector in this case -
input[placeholder='Gender'], which can easily find the element.

Generic Xpath in selenium

I'm new to Selenium Webdriver. I have been using Firebug & Firepath to generate xpath (copy pasting the given xpath) for the web elements, but I am facing problems when using such xpaths(Such as "Xpath cannot be evaluated into an web elemnt").
Please help me with the below example of xpath of a Webelement to create a flexible & generic xpath:
<input type="text" maxlength="15" length="40" value="" name="ST_ACK_NUM"/>
Like the people say in the comments it is better to create a more relative path to your elements. Maybe you can post some more input so the XPath can be created more efficiently.
To get the input with a absolute XPath you can do:
//input[#name='ST_ACK_NUM']
Above XPath will search the complete source to all <input> elements where attribute name equals the value ST_ACK_NUM
When you look at your source maybe you can adjust the XPath and add more dependencies. For example if your input looks like:
<div class="DivClass">
<form name="FormName">
<input type="text" maxlength="15" length="40" value="" name="ST_ACK_NUM"/>
</form>
</div>
You could use a XPath like:
//div[#class='DivClass']/form[#name='FormName']/input[#name='ST_ACK_NUM']
This will also find the <input> element, but with a lot more dependencies.

Writing XPath for elements which have no ID or Name in Selenium

I'm trying to automate testing of the code... well, written without testing in mind (no IDs on many elements, and a lot of elements with the same class names). I would appreciate any help (questions are below the code):
<div id="author-taxonomies" class="menu-opened menu-hover-opened-inactive" onmouseover="styleMenuElement(this)" onmouseout="styleMenuElement(this)" onclick="toggleSFGroup(this)">Author</div>
<div id="author-taxonomies-div" class="opened">
<div id="top-level-menu" class="opened">
<div id="top-level-menu-item-1" class="as-master">
<div class="filter-label"> Name</div>
</div>
<div id="top-level-menu-item-1" class="as-slave"
style="top: 525px; left: 34px; z-index: 100; display: none;"> </div>
<div id="top-level-menu-item-2" class="as-master">
<div class="filter-label">Title</div>
</div>
<div id="top-level-menu-item-2" class="as-slave">
<div id="top-level-menu-item-2" class="as-slave-title as-slave-title-subgroup"
>Title</div>
<div id="top-level-menu-item-2" class="as-slave-body"> </div>
<div class="as-slave-buffer"> </div>
</div>
<div id="top-level-menu-item-3" class="as-master">
<div class="filter-label">Location</div>
</div>
<div id="top-level-menu-item-3" class="as-slave"> </div>
</div>
</div>
The question is: how to refer particular labels of this menu and the properties with xPath expressions? For example, if I want to:
verify the "Location" label is there
check if "Title" with class "as-slave" is not visible at the moment
It would be something similar to:
//div[#id="top-level-menu-item-3"]/div[#class="filter-label"]
//div[#id="top-level-menu1"] --- and check in code for display: none ... assuming it is selenium rc you are using
Update: also be sure to install the following firefox addin, it is Really useful when trying different xpath expressions on a site https://addons.mozilla.org/en-US/firefox/addon/1095
As a side note: try to avoid using xpath locators in Selenium, if possible. If you have a long xpath expression, it can be up to 20 times slower for Selenium to find the element compared to identifying it using its unique ID. Of course, sometimes there is no alternative to using xpath. However, when you do use it, keep '//' expressions to minimum - this is a real performance killer.
If you're just starting with Selenium, download the selenium add-on for Firefox. As you click on DOM elements, Selenium shows you the xpath to access it.
I am currently working on an open source library for generating xpath expressions through a fluent .Net API. The idea is to be able to generate xpath based selenium locators without having to know xpath.
Here's an example of how the library can be used in your case:
XPathFinder.Find.Tag("div").With.Attribute("id", "top-level-menu-item-3").And.Child("div").With.Attribute("class", "filter-label").ToXPathExpression();
This will produce the following xpath:
"//div[#id='top-level-menu-item-3']/div[#class='filter-label']"
Check it out at
http://code.google.com/p/xpathitup/
You can use firepath that can be installed over firebug(both firefox plugin). When you get a xpath, dont forget to append // before using it. Either in code or in selenium IDE. You are not appending it thats why its unusable. There are two types of xpath absolute and relative. If you use absolute then it will take care of dynamic ids. But if you use relative it will break with each run.

Resources