How to click a link using XPath and Selenium IDE - xpath

I’m new to both XPath and Selenium. I have a need to be able to click a link with Selenium based on whether or not a span is as a certain text. The example code is:
<div>
<span>Fri</span>
<ul>
<li>
<a href=#></a>
</li>
</ul>
</div>
<div>
<span>Sat</span>
<ul>
<li>
<a href=#></a>
</li>
</ul>
</div>
My XPath expression is //*[text()[contains(.,'Fri')]] which finds the correct span. Now I thought I could use //*[text()[contains(.,'Fri')]]../ul/li/a, but that doesn't work.
How can I do it?

The Selenium IDE command will be:
command: click
target : //span[contains(text(),'Fri')]/following::a
From here:
following:: All nodes that are after the context node in the tree,
excluding any descendants, attribute nodes, and namespace nodes.
Notice, that you may not write [1] at the end of the XPath expression to select the first node from all occurrences as the Selenium IDE does it by default.
As you use the IDE you can also use easier to read CSS selector:
command: click
target : css=span:contains('Fri')+ul a
As for your initial XPath expression, you missed one slash before ../:
//*[text()[contains(.,'Fri')]]/../ul/li/a

Related

How to access second element using relative Xpath

Given this page snippet
<section id="mysection">
<div>
<div>
<div>
<a href="">
<div>first</div>
</a>
</div>
<div>
<a href="">
<div>second</div>
</a>
</div>
</div>
</div>
</section>
I want to access the second a-element using relative Xpath. In FF (and locating with Selenium IDE) this
//section[#id='mysection']//a[1]
works but this does not match
//section[#id='mysection']//a[2]
What is wrong with the second expression?
EDIT: Actually I do not care so much about Selenium IDE (just use it for quick verification). I want to get it going with selenium2library in Robot Framework. Here, the output is:
ValueError: Element locator with prefix '(//section[#id' is not
supported
for the suggested solution (//section[#id='mysection']//a)[2]
You can use this. This would select the anchor descendants of section and get you the second node. This works with xslt processor, hope this works with Selenium
//section[#id='mysection']/descendant::a[2]
Try this way instead :
(//section[#id='mysection']//a)[2]
//a[2] looks for <a> element within the same parent. Since each parent <div> only contains one <a> child, your xpath didn't match anything.
With this:
//section[#id='mysection']//a[1]
you are matching all first 'a' elements within any context (inside one div, for example), but with this
//section[#id='mysection']//a[2]
you are trying to match any second 'a' element with any context, but you dont have more than one 'a' element in any of nodes.
The icrementing sibling node thus should be a parent div node to those 'a' tags.
Very simple:
//section[#id='mysection']//a[1] - both elements
This is why previous answer with paranthesis around the whole thing is correct.
//section[#id='mysection']//div[1]/a - only first element
//section[#id='mysection']//div[2]/a - only second elemnt
Other way to mach each 'a' separately:
//section[#id='mysection']//a[div[text()='first']]
//section[#id='mysection']//a[div[text()='second']]
Other ways to reach to the second a-element can be by using the
<div>second</div>, call this bottom-up approach
instead of starting from section-element
<section id="mysection">, call this top-down approach
Using the div child of a-element, the solutions should look like this:
//div[.='second']/..

Need help finding an element in selenium

Can some one help me to locate an element (without using xpath) which is displayed using : <i id="ext-gen759" class="icon-tool"></i> under a <div> tag. The HTML is as follows:
<div id="ext-comp-1089" class=" MiniTbar">
<a href="javascript:void(0);" id="ext-gen760" class=" active">
<i id="ext-gen759" class="icon-tool"></i> -->> need to locate this.
</a>
</div>
I don't want to use:
By.Id --> id is dynamic
By.XPath --> not stable
I have tried the following without getting a result:
By.className("icon-tool") -- > not working
By.partialLinkText("icon-tool") --> not working
Any solution?
You can rely on the part of the id using, for example, starts-with():
//div[starts-with(#id, "ext-comp-")]/a[starts-with(#id, "ext-gen")]/i[#class="icon-tool"]
Or a CSS selector:
div[id^=ext-comp-] a.active[id^=ext-gen] i.icon-tool[id^=ext-gen]
using xpath should do this. You may need to make sure that's the only element i with same criteria on the page
//i[contains(#id,'ext-gen')]
Give a chance to the find element by css selector ?
driver.find_element_by_css_selector('i.icon-tool')
The python documentation is here http://selenium-python.readthedocs.org/en/latest/locating-elements.html
You can find it using css selector:
driver.findElement(By.cssSelector("i[class='icon-tool']"));

XPath is broken when changes are made

This is the current situation: There are several files and folders in a specific location.
Once you hover over a file or a folder, an icon appears then you can click on that icon and a menu will appear. From that menu a user can select any action(rename, move,etc). The problem is that the XPath which is provided by FirePath is broken whenever a new file/folder is created/added in the location.
This is the initial line of code which works fine until the XPath is broken:
webDriver.findElement(By.xpath("//*[#id='main_files_view']/ol/li[6]/ul/li[4]")).click();
Whenever a new item is added in the location, the index with value "6" can change to "7" (new position of the file) and the XPath generated is now slightly different:
webDriver.findElement(By.xpath("//*[#id='main_files_view']/ol/li[7]/ul/li[4]")).click();
How can I change that XPath and makes it robust so that no matter the number of items added/removed, the XPath will not break?
Below is the section of the HTML which is related to the XPath provided by FirePath.
When the XPath is provided, the last class is also highlighted.
<li class="storage_item document file_object even ui-draggable" data-thumb-translation="Translated" data-possible-actions="Rename Delete Share Move View" data-file-size="0 bytes" data-item-type="file" data-display-name="solids_A" data-name="solids_A.raas" data-id="bd48453c752043d98afb237b86ee88a3">
<a class="file_name" href="#/Item/Details?id=bd48453c752043d98afb237b86ee88a3&itemtype=File&tab=Default">
<img class="file_list_icon" width="16" height="16" src="https://api-staging.autodesk.com/content/gateway/2013.1.307595.626/z/Content/images/fileIcons/small/raas.png"/>
<div class="name_container">
<ul class="tools">
<li class="preview_trigger"/>
<li class="comment_balloon none has_tooltip" data-tooltip-contents="#comment_balloon_tooltip" data-comments="0">
<li class="categorize action has_tooltip" data-tooltip="Categories"/>
<li class="document_tools has_tooltip" data-tooltip="Actions"/>
</ul>
</li>
I am using Selenium 2.0, on Eclipse IDE.
If the data-name is unique, then you have
//*[#id='main_files_view']/ol/li[#data-name='solids_A.raas']/ul/li[contains(#class, 'document_tools')]
Css Selector is even better than XPath in this case:
#main_files_view li[data-name='solids_A.raas'] .document_tools
Try this:
By.XPath("//*[#id='main_files_view']/ol/li/ul/li[4]")
You do not have to define every index in an xpath and often if it's just one that change, removing that index will work.
In general you should avoid xpaths in your tests. Css selectors are faster (especially in IE) and more readable. If data-name is unique then this should work:
webDriver.findElement(By.cssSelector("#main_files_view li[data-name='solids_A.raas'] li.document_tools"));
If you really need an xpath the one provided by user1177636 will also do the job.

discover a certain part of a page with selenium

I have a webpage looks something like this:
<html>
...
<div id="menu">
...
<ul id="listOfItems">
<!--- repeated block start -->
<li id="item" class="itemClass">
...
<span class="spanClass"><span class="title">title</span></span>
...
</li>
<!-- repeated block end-->
<li id="item" class="itemClass">
...
<span class="spanClass"><span class="title">title something</span></span>
...
</li>
<li id="item" class="itemClass">
...
<span class="spanClass"><span class="title">title other thing</span></span>
...
</li>
</ul>
...
</div>
...
</html>
I would like to know what is the xpath of the titles ("title", "title something", "title other thing"). The point is that the order of the <li> elements are not specified. It could be different after every page loading. Is there any method how to discover a certain structure of the page with xpath? I have an notion about how to solve this issue, but before I'm going to write iterations with C# to discover the page I ask you.
Thanks in advance!
First of all, id's should be unique, so your portrayed webpage would not work well when it comes to testing.
I did however test, and got some XPath locators to work for selecting specific titles (although I recommend you fix your webpage instead of actually using this):
//li[#id='item']/span/span
//li[#id='item'][1]/span/span
//li[#id='item'][3]/span/span
If you're after all three titles, you could try Dimitre Novatchev's suggestion:
//span[#class='title']
This should get all titles on the page.
I would like to say one thing however, if you're getting into Selenium, I recommend you download the Selenium IDE extension for Firefox. It's a great tool for beginners. It helps you both to make your Selenium tests by recording your clicks on a website, and it also helps you auto-generate and test your XPath locators and other locators.
And again: I urge you to not make a website with duplicate id elements :-)
Does Selenium support XPath expressions like:
//span[#class='title']
If yes, than use the above XPath expression. It selects every span element in the XML document, whose class attribute has string value of "title".
I recommend to use a tool like the XPath Visualizer to play with different XPath expressions and see the selected nodes highlighted in the source XML document.

xpath locator works in FF3, but won't work in IE7

After switching from firefox testing to internet explorer testing, some elements couldn't be found by selenium anymore.
i tracked down one locator:
xpath=(//a[#class='someclass'])[2]
While it works as it should under firefox, it could not find this element in ie.
What alternatives do i have now? JS DOM? CSS Selector? How would this locator look like?
Update:
I will provide an example to make my point:
<ul>
<li>
<a class='someClass' href="http://www.google.com">BARF</a>
</li>
<li>
<a class='someClass' href="http://www.google.de">BARF2</a>
</li>
</ul>
<div>
<a class='someClass' href="http://www.google.ch">BARF3</a>
</div>
The following xpath won't work:
//a[#class='someclass'][2]
In my understanding this should be the same as:
//a[#class='someclass' and position()=2]
and i don't have any links that are the second child of any node. All i want is, to address one link from the set of links of class 'someClass'.
Without knowing the rest of your HTML source it's difficult to give you alternatives that are guaranteed to work. Hopefully the following suggestions will help point you in the right direction:
//a[#class='someClass'][2]This is like your example, but the parantheses are not needed.
//a[contains(#class, 'someClass')][2] This will work even if the link has other classes.
css=a.someClass:nth-child(2) This will only work if the link is the 2nd child element of it's parent.
Update
Based on your update, try the following: //body/descendant::a[#class='someClass'][2]

Resources