How to find XPath of an ExtJS element with dynamic ID - selenium

All the elements in the application which i am testing have dynanic ID's . The test always passes when i replay it without refreshing the page but as soon as i refresh the page, The Test Fails because Id's of all the elements changes randomly and selenium cannot match the recorded id's with the new ones .
I tried to use Xpath-position, It works for some objects but in case of Dropdown list and Buttons, it dosent work!
Can anyone please tell me how to find the Xpath (Meathods in JAVA or S*elence*) of an object OR How to create a new Locator Finder for Dropdown list and Buttons
I can show the properties (Inspected by Firebug) of the dropdown which is teasing me.
properties of Dropdown :
<div id="ext-gen1345" class="x-trigger-index-0 x-form-trigger x-form-arrow-trigger x-form-trigger-last x-unselectable" role="button" style="-moz-user-select: none;"></div>
properties of Dropdown*Choice*:
<ul>
<li class="x-boundlist-item" role="option">Rescue</li>
</ul>

Please search before posting, I have been answering this over and over.
ExtJS pages are hard to test, especially on finding elements.
Here are some of the tips I consider useful:
Don't ever use dynamically generated IDs. like (:id, 'ext-gen1345')
Don't ever use absolute/meaningless XPath, like //*[#class='someclass']/li/ul/li[2]/ul/li[2]/table/tbody/tr/td[2]/div
Take advantage of meaningful auto-generated partial ids and class names. (So you need show more HTML in your example, as I can make suggestions.)
For example, this ExtJS grid example: (:css, '.x-grid-view .x-grid-table') would be handy. If there are multiple of grids, try index them or locate the identifiable ancestor, like (:css, '#something-meaningful .x-grid-view .x-grid-table'). In your case, (:css, '#something-meaningful .x-form-arrow-trigger')
Take advantage of button's text.
For example, this ExtJS example: you can use XPath .//li[contains(#class, 'x-boundlist-item') and text()='Rescue']. However, this method is not suitable for CSS Selector or multi-language applications.
The best way to test is to create meaningful class names in the source code. If you don't have the access to the source code, please talk to your manager, using Selenium against ExtJS application should really be a developer's job. ExtJS provides cls and tdCls for custom class names, so you can add cls:'testing-btn-foo' in your source code, and Selenium can get it by (:css, '.x-panel .testing-btn-foo').
Other answers I made on this topic:
How to find ExtJS elements with dynamic id
How to find unique selectors for elements on pages with ExtJS for use with Selenium?
How to click on elements in ExtJS using Selenium?
Using class names in Watir
how to click on checkboxes on a pop-up window which doesn't have name, label

I would suggest you build a xpath from any of the parent of your DIV. you may get messed if there is no immediate parent node has such one.
example,
//*[#id='parentof div']/div
//*[#class='grand parent of div']/div/div
i did even something like this,
//*[#class='someclass']/li/ul/li[2]/ul/li[2]/table/tbody/tr/td[2]/div
But still, its not encouraged to do so.

Related

Retrieving a element with multiple xpaths

This isn't much of a coding question but one about what options should I take next. I've just started using selenium about a week ago and started to get the hang of most of its function.
I was working on a work project to login into various websites until I ran into a issue where I was getting this error when I tried to find the password field
Exception in thread "main" org.openqa.selenium.ElementNotVisibleException: element not visible
I went ahead and double checked the name & id but I couldn't find the field using locators like .id, name, and xpath. I inspected the xpath with Firebug and noticed that it returned two results instead of one.
Current Xpath looks like this
.//*[#id='password']
I was wondering if anyone could point me to the right direct when dealing with something like this.
Normally, id attribute suppose to be unique value, but there are some cases when front-end developer just hide part of DOM, create similar and forget to remove hidden one.
In such case you can (if it possible) ask developer to get rid of redundant code or use index as
"(.//*[#id='password'])[2]"
In cases like this you need to use another unique DOM element (parent, ancestor, sibling, child) with connection to the element you are looking for. For example In those html snippets
<div id='a'>
<div id='password'></div>
</div>
And
<div id='b'>
<div id='password'></div>
</div>
.//*[#id='password'] will have two results
However
.//*[#id='b']/[#id='password']
Will have only one result
Let me try to answer your queries one by one:
error when I tried to find the password field : This is because the property which you have mentioned id/name/css/xpath was incorrect.
ElementNotVisibleException : I doubt it was for the password_field at all. Reason behind that is, normally login field & password field stays on the same container. Either those resides on the HTML DOM (which gets loaded completely once the page loading is complete) or they may reside within a frame/iFrame (there are other measures to handle them which I am not covering here). But those 2 elements stays on the same container. So if you have found out the login_field element, password_field is just a step away.
inspected the xpath with Firebug and noticed that it returned two results : That's because the xpath which you are using doesnot identifies an unique element. There can be multiple elements on the HTML DOM with the same id attribute set to "password". But definitely the xpathof those elements will be different and unique.
What you should do?
I will suggest you the following:
a. Try to identify each element on a webpage following the attributes in sequence: id, name, visibleText, css, xpath.
b. Try to identify a unique logical xpath for elements using the other properties of the elements defined within the HTML tag. Cross check your xpath through Firebug/Firepath. There are some other handy xpath checker available too. Take help of those.
Let me know if this answers your question.

Handling dynamic ids and classes

I am using selenium to test a web application, The ids and classes are always changing dynamically.So that I am not able to give correct identification, is it possible to get ids of the element in run time and is there any other method to handle this situation.
It depends on if ids are completely random or if there is some part of the id which remains the same. If yes, then cssSelector is the obvious choice
driver.findElement(By.cssSelector("div[id*=somePart]");
where id* means id contains. If you cant use this approach you will have to track down your element using xpath or again cssSelectors. XPath example is here and CSS selector could look like this
By.cssSelector("boyd table input");
I would strongly recommend locating elements by XPath -- with the caveat that you make your XPaths robust and not just "copy" the xpath using your browser's developer tools. XPath is very easy to learn. You can use XPaths to walk up and down the DOM, and identify elements by their text, or their attributes.
For example, maybe you need to click a button that has a span that contains the text that appears on the button:
<div class="btn-row random-generated-number-1234897395">
...
<button id="random-generated-number-239487340924257">
<span>Click Here!</span>
</button>
...
</div>
You could then use an xpath like this:
//div[contains(#class, 'btn-row')]//button/span[text()='Click Here!']/..
(The /.. at the end walks back up from the span to the button.)
XPath is powerful and flexible and easy to learn. Use it when the ids and classes aren't reliable.

many buttons with the same id

I am using selenium to test a page with multiple portlets made by liferay.
Every portlet is having a save button with the same id, it use the iframe id of the portlet to differentiate between the buttons.
How can I write a code in selenium that can understand which button I mean??
You need to use driver.switchTo().frame(IFrameElement). Any kind of IFrame you need to switch in/out of.
https://stackoverflow.com/a/9943605/1769273
You can use xpath or css selectors to find children dependent on parents.
paste your html and we can provide examples
Does this mean your portlets are all embedding iframes? Typically portlets just render HTML snippets into the same documents. In this case, your implementation would be considered flawed: Portlets must not use IDs that can conflict. E.g. you should not render
<input type="submit" id="save"/>
but
<input type="submit" id="<portlet:namespace/>save"/>
or similar - make sure the id is unique, as it ends up in the same HTML-DOM which - by specification - assumes ids are unique.
There are other methods to create unique ids, but keep in mind: If you come up with the prefix yourself, per portlet, someone might add the same portlet to the page twice and you can end up with the same id even though all different portlets have unique ids.
If you are indeed rendering many different iframes from your portlets, you can disregard this answer or take it as a suggestion to make better use of the portal environment by changing the implementation.

Finding clickon Element using Selenium. (JAVA)

I spend hours already trying to find the way to find the Element using Selenium WebDriver. I assume I need to use driver.findElement(By.xpath("")), but I am not quite sure how.
I somehow need to find and click on "clickon" element. The problem is that part of that element is changing (see screenshot) I need to pick up from the file and putted into the xpath.
I would appreciate any help.
We have been rigorously searching for automated functional testing solutions recently, and we began with Selenium. The entire reason we decided to search for other solutions was that our application also has dynamic IDs with no other obvious XPath mechanism to identify them. Selenium is unable to identify these elements on the page without some additional knowledge, just as you would be unable to identify these elements on the page if you didn't already know what they are.
If you are controlling the DOM creation, consider adding a unique ID or class to this element.
We recently came across eggPlant from testPlant, and it is an interesting approach to functional testing. It's essentially image based. Other viable solutions are Ranorex or HP's QTP or SmartBear's TestComplete.
You can use xpath. If the div class is constant, you can use something like:
driver.findElement(By.xpath("list-row field-item")).click();
To view the xpath, you can install firefox plugin called 'xpath checker' found here and right click on the dom element and click 'View Xpath' option to get the xpath of the element and then you can use that xpath in your code.
Or you can even use regex in the xpath which is suitable for the similar problems. Xpath with regex is really powerful.
It seems that you want to click the div that has the on click attribute that contains certain text that doesn't change, ignoring the part that does. In that case, use an xpath like this:
//div[contains(#onclick, '/challenge/index/rfp_id/')]
This will select the first div with an onclick attribute with a value containing /challenge/index/rfp_id.

How to handle dynamic id from xpath

I am trying to explore IDE with this site http://www.barnesandnoble.com/, by just recording and play back.
1.In the search box just enter any text to search,
2.Ten click on All Products, select Books.
When i record its xpath is as below
/html/body[#id='CDS']/div[#id='navContainer']/div[#id='bnnav2011']/div[#id='yui_3_3_0_1_1355746621091_93']/div[#id='bn-global-header']/div[#id='yui_3_3_0_1_1355746621091_92']/div[#id='yui_3_3_0_1_1355746621091_91']/form[#id='qs']/div[#id='yui_3_3_0_1_1355746621091_90']/div[#id='yui_3_3_0_1_1355746621091_89']/ul[#id='yui_3_3_0_1_1355746621091_88']/li[#id='yui_3_3_0_1_1355746621091_99']
But when we play ti again it gives error,[error] locator not found:
Wehn i search for its xpath , its chnaged and is as below
/html/body[#id='CDS']/div[#id='navContainer']/div[#id='bnnav2011']/div[#id='yui_3_3_0_1_1355748592221_91']/div[#id='bn-global-header']/div[#id='yui_3_3_0_1_1355748592221_97']/div[#id='yui_3_3_0_1_1355748592221_96']/form[#id='qs']/div[#id='yui_3_3_0_1_1355748592221_95']/div[#id='yui_3_3_0_1_1355748592221_94']/ul[#id='yui_3_3_0_1_1355748592221_93']/li[#id='yui_3_3_0_1_1355748592221_98']
Observe that, its ID's are changing.
Can any one tell me how to handle this ?
The IDE is not very smart at generating XPath queries, in fact, there isn't an automated tool out there that will calculate a reliable XPath query. Why? The reason is because to generate the XPath query, it will walk down the tree from the top (at the html element), down to the element you are interacting with.
Whilst this is fine for a lot of things, if you have elements that have dynamic values (dynamic text/ID/name/classes or even if it changes position), it's never going to work.
You'll need to look at a different way to get it, so you'll have to override what the IDE is giving you.
Looking at the source, they give whatever is selected a class value of ui-selectmenu-selected. So when the page loads, the 'All Products' list item (li) will have that class, when you change the item the new item will have that class.
So you could use this XPath:
//li[#class='ui-selectmenu-selected']
Or, this CSS selector:
li.ui-selectmenu-selected
Or, use this XPath to get the 'All Products' item specifically. It will start one level up, using the actual menu, then go down and find the item:
//ul[#class='ui-selectmenu']/li[text()='All Products' and not(#class='ui-selectmenu-hidden')]
You can try using xpath: Position. It seems that the IDs are changing all the time.
As an answer to your question you should move away from id's and try using xpath or css selectors where you can select the nth child of the parent.
Since you are new to selenium I would like to point to my notes here at.-
http://selenium-testing-notes.blogspot.in/
it will help you through a lot of other pitfalls I fell in.
The best way I found to help with selectors is to work with firebug with firepath installed. This setup can help you verifying your xpath and css selectors.
I saw your question based on that answer is first you need to add on fire-path in Firefox .Using firepath you can find the xpath locator. it is very simple to you
Example:
driver.find_element_by_xpath("see![image which i have attached in this question][1] the xpath path locator details").click()
Hi Arran i am able to click the All Products button using the xpath you have given ( xpath= //ul[#class='ui-selectmenu']/li[text()='All Products' and not(#class='ui-selectmenu-hidden')]
and also get the list available. But then not able to click the Books item from the Menu.