selenium can't find the element - xpath

I'm testing my webapp using selenium webdriver, but the driver can't find my element, the element's style is set to display:none visible,and I'm using xpath to retrieve that element here is my xpath
By.XPath(".//*[#id='box']/table/tbody/tr[3]/td[4]")
Please advise.
Many thanks

the tbody looks suspicious to me. This is often implicitly inserted by some browsers. I don't know anyone who uses it in html.
Therefore, you could try an XPath without it:
By.XPath("//*[#id='box']/table/tr[3]/td[4]")
If this doesn't help: Could you add an (X)HTML snippet?

Remove that leading dot:
By.XPath("//*[#id='box']/table/tbody/tr[3]/td[4]")

Maybe, for debugging reasons (and maybe not only for that) you should split up your xpath. For example (in pseudo-python):
tables = driver.findElementsByXPath("//*[#id='box']/table")
if len(tables) == 0:
break
trs = tables[0].findElementsByXPath("/tr")
if len(trs) == 0:
break
tds = trs[3].findElementsByXPath("/td") # or maybe trs[2]
if len(tds) == 0:
break
td = tds[4] # or maybe tds[3]

Related

Is it possible to use Following and preceding in combination in Selenium?

On this page
https://en.wikipedia.org/wiki/Trinity_Seven#Episode_list
I have:
//*[text()='Reception']//preceding::th[contains(#id, 'ep')]//following::I
But it only registers following.
The default firepath selector is: .//*[#id='mw-content-text']/div/table[5]/tbody/tr/td[1]/I but this kind of selector is known to break quite frequently. Just wondering if there is a better way of doing this and I thought this might be a way.
Thanks!
:)
- You can see that it's getting stuff under the table which is not what I want :S
Try to use below XPath to match required elements:
//th[contains(#id, 'ep')]/following::I[./following::*[text()='Reception']]
This looks more simple
//tr[contains(#class, 'vevent')]//i
Don't overcomplicate things. You need I tag inside each row. So just find row locator tr[contains(#class, 'vevent')] and get it's I
Another good approach in case you want to check that inside of parent element is located some special element, but you want to find some 3rd element is to use such style: //element[./specific]//child , so in your case:
//tr[contains(#class, 'vevent')][./th[contains(#id,'ep')]]//i
so it's I tag inside row that contains #id,'ep' in header

Handling Dynamic Xpath

Am automating things using Selenium. Need your help to handle Dynamic Xpath as below:
Driver.findElement(By.xpath("//[#id='INQ_2985']/div[2]/tr/td/div/div[3]/div")).click();
As above INQ_2985 changes to 2986,2987,2988 etc during each run
HTML CODE:
< div> class="context-menu-item-inner" style="background-image:url(../images/productSmall.png);">Tender Assignment < /div>
Tried different combinations as below but with no success:
// Driver.findElement(By.name("//input[#name='Tender Assignment']")).click();
// Driver.findElement(By.className("context-menu-item-inner")).click();`
Can you help me on this.
you can try using contains() or starts-with() in xpath,
above xpath can be rewritten as follows,
Driver.findElement(By.xpath("//*[starts-with(#id,'INQ')]/div[2]/tr/td/div/div[3]/div")).click();
if you can post more of your html, we can help improve your xpath..
moreover using such long xpath's is not recommended, this may cause your test to fail more often
for example,if a "new table data or div" is added to the UI, above xpath will no longer be valid
you should try and use id, class or other attributes to get closer to the element your trying to find
i personally recommend using cssSelectors over xpath
you can use many methods,
use implicity wait;
driver.findElement(By.xpath("//*[contains(#id,'select2-result-label-535')]").click();
driver.findElement(By.xpath("//*[contains(text(), 'select2-result-label-535')]").click();
Good to use Regular expression
driver.findElement(By.xpath("//*[contains(#id,'INQ_')]")
Note: If you have single ID with name starts from INQ_ then you can take action on the element . If a bunch of ID then you can extract as a List<WebElements> and then match with the specific text of the element ( element.getText().trim() =="Linked Text" and if it matched then take action. You can follow other logic to traverse and match.
you can use css -
div.context-menu-item-inner
Use this xpath:
driver.findElement(By.cssSelector("div.context-menu-item-inner").click();
The best choice is using full xpath instead of id which you can get easily via firebug.
e.g.
/html/body/div[3]/div[3]/div[2]/div/div[2]/div[1]/div/div[1]
if your xpath is varying
Ex: "//*[#id='msg500']" , "//*[#id='msg501']", "//*[#id='msg502']" and so on...
Then use this code in script:
for (int i=0;i<=9;i++) {
String mpath= "//*[#id='msg50"+i+"']";
driver.findElement(By.xpath(mpath)).click();
}

Translating jQuery to Watir

It's entirely possible that I'm missing something fundamental, but this is a new realm for me and I could use some pointers. I'm getting started using Ruby and Watir to drive/test a web application that's all AJAX-built. Many of the items don't have explicit classes/ids, and the dev team of course uses jQuery to get to them. I'm looking for a way to translate their jQuery into Watir to use/modify/check values of the same objects.
For example, they use this to see if there are values in a data grid's fifth column:
$("div.dataTable table tbody tr").has("td:eq(4):not(:empty)").length > 0
How would I go about doing something similar?
You could make the same check in Watir using:
#Get the rows of the table (assuming there is just one dataTable)
table_trs = browser.div(:class, 'dataTable').table.tbody.trs
#Find how many rows have data in the 5th cell
# Note that both jQuery and Watir are 0-based index (ie 4 means 5th cell)
rows_with_data = table_trs.count{ |tr| tr.td(:index, 4).text != '' }
#Do your comparison
rows_with_data > 0
You can write it all as one line, but I broke it up here for readability.
You could also use Pincers. It's a small ruby gem, like Watir, but offers an API similar to jQuery on top of Webdriver.
Example:
require('selenium-webdriver')
require('pincers')
driver = Selenium::WebDriver.for :firefox
pincers = Pincers.for_webdriver driver
pincers.goto 'www.somesite.com'
pincers.css('a#link-id').click
(Disclosure: I work at Platanus.)

htmlagilitypack identify inconsistancy

I use htmlagilitypack & xpath.
How can I identify insconsistancy in html. For example:
<table><tr><td>
<b>Car1</b><span>Color123</span>
<bCar2</b><span>Color333</span>
<b>Car3</b><span>Color221</span>
<b>Car4 <span>Color224</span>
<b>Car5</b><span>Color621</span>
</table></tr></td>
Car2 & Car4 bold are broken.
The problem is that i use root.SelectNodes("//b[1]")[Index] and it misses index position2 (Car2) and put on its place Car3 and I don't even know that such thing happened if i don't inspect the results manually. At least, i need to have "empty" position2 (Car2) and a correct position3 (Car3).
HtmlAgility pack can't indetify and fix it automatically. doc.ParseErrors can't identify it.
Can you offer some combination of XPath functions like Substring, Boolean, Concat, Number etc.? I'm not good enough in XPath, but I feel that these functions can help in identifying inconsistancy.
p.s. Html Tidy library can't fix it. It sometimes decides that:
<b>Car4 <span>Color224</span></b>
Which is not the correct fix.
HtmlDocumemt.ParseErrors does contains 3 errors for your example:
- Start tag <b> was not found (because there is a closing b without an opening one)
- Start tag <tr> was not found (because the tr is inside an opening b without a closing one)
- Start tag <td> was not found (same as tr)
In the general case, it's impossible to 1) identify errors the way you want, and 2) much more difficult to fix them. You would have to exactly define what's the expected format.
You can use the Html Agility Pack to identify errors with specific requirements. For example here is a piece of code, that validates your doc, base on the functional requirement that "every child element of a TD must be a B or a SPAN and must not contain more than one grand child element":
HtmlDocument doc = new HtmlDocument();
doc.Load("MyFile.htm");
foreach (HtmlNode childOfTd in doc.DocumentNode.SelectNodes("//td/*"))
{
if ((childOfTd.Name != "b") && (childOfTd.Name != "span") || (childOfTd.ChildNodes.Count > 1))
{
Console.WriteLine("child error, outerHtml=" + childOfTd.OuterHtml);
}
}
To fix this requires raw text access (maybe a Regex, and BTW, a Regex can also identify simple errors) because the Html Agility Pack builds a DOM that does not let you access incorrect syntax nodes, by design.

HtmlUnit getByXpath returns null

I am coding with Groovy, however, I don't believe its a language specific set of questions.
I actually have two questions
First Question
I've run into an issue while using HtmlUnit. It is telling me that what I am trying to grab is null.
The page I'm testing it on is:
http://browse.deviantart.com/resources/applications/psbrushes/?order=9&offset=0#/dbwam4
My code:
client = new WebClient(BrowserVersion.FIREFOX_3)
client.javaScriptEnabled = false
page = client.getPage(url)
//coming up as null
title = page.getByXPath("//html/body/div[4]/div/div[3]/div/div/div/div/div/div/div/div/div/div/h1/a")
println title
This simply prints out: []
Is this because the page uses onclick()? If so, how would I get around that? Enabling javascript creates a mess in my cmd prompt.
Second Question
I am wanting to also get the image but am having trouble because when I attempt to get the XPath (via firebug) it shows up as: //*[#id="gmi-ResViewSizer_img"]
How do I handle that?
First Answer:
/html/body/div[3]/div/div[3]/div/div/div/div/div/div/div/div/div/div/h1/a
Your XPATH was off by one in the predicate filter for the 4th div of the body, it should be the 3rd div. It appears the HTML for the site can/does change from when you had origionally snagged the XPATH using Firebug. You may need to adjust your XPATH to accommodate for potential change and be less sensitive to some differences in document structure.
Maybe something like this:
/html/body//div/h1/a
Second Answer: The XPATH that you listed will work. It may look odd/short(and may not be the most efficient), but // starts at the root node and looks throughout every node in the tree, * matches on any element(to include the img) and the [] predicate filter restricts it to those that have an id attribute who's value equals "gmi-ResViewSizer_img".
There are many other options for XPATHs that could work as well. It will also depend on how often the HTML structure changes. This is one that also works for the page referenced to select that img:
/html/body/div/div/div/div/img[1]
I had the same problem, I solved when I realize iframe tags on page, try call
((HtmlPage)current_page.getFrames()[n].getEnclosedPage()).getElementByXPath(...
where n is the position in frame in iframe collection. It's work for me !!!
Thanks a lot.

Resources