element not supported by watir webdriver - xpath

So element_by_xpath has been removed from watir webdriver and I am wondering if there is something similar to this still in existence. Basically there is a path element (pie chart) that is clickable and I need to have a regression test set up to for it. The people who designed the website apparently thought it would be cool to have everything inside this thing to be custom tags and there is nothing supported by watir webdriver that I can point to, at least to my knowledge.

element_by_xpath was replaced with an :xpath locator, which is used like any other locator such as :text.
For example, say you have a custom 'asdf' element in your html:
<html>
<body>
<asdf>text</asdf>
</body>
</html>
Then you could locate the element via xpath like:
browser.element(:xpath => '//asdf').text
#=> "text"
The usual suggestion is to avoid xpath. If you are only using the xpath because of the tag name, you can use the :tag_name locator instead:
browser.element(:tag_name => 'asdf').text
#=> "text"

Related

Ruby Watir - how to select <a onclick="new Ajax.Request

Hi I'm trying to select an edit button and I am having difficulty selecting it.
<td>
<a onclick="new Ajax.Request('/media/remote/edit_source/3', {asynchronous:true, evalScripts:true}); return false;" href="#">
<img title="Edit" src="/media/images/edit.gif?1258500617" alt="Edit">
</a>
I have the number at the end of ('/media/remote/edit_source/3') the which changes and I have stored it in #rep_id variable.
I can't use xpath because the table changes often. Any suggestions? Any help is greatly appreciated. Below is what I have tried and fails. I am fairly new to watir and love it, but occasionally I run into things like this and get stumped.
browser.a(:text, "/media/remote/edit_source/#{#rep_id}").when_present.click
The line:
browser.a(:text, "/media/remote/edit_source/#{#rep_id}").when_present.click
fails because:
The content you are looking for is in the onclick attribute (rather than the text)
The locator is passed a string for the second parameter. This means that it is looking for something that exactly matches that. Given that you are only using part of the text/attribute, you need to use a regexp.
If you are using watir-webdriver, there is support for locating an element by its :onclick attribute. You can use a regexp to partially match the :onclick attribute.
browser.link(:onclick => /#{Regexp.escape("/media/remote/edit_source/#{#rep_id}")}/).when_present.click
If you are also using watir-classic (for IE testing), the above will not work. Instead, you can check the html of the link. Checking the html also works in watir-webdriver, but could be less robust than using :onclick.
browser.link(:html => /#{Regexp.escape("/media/remote/edit_source/#{#rep_id}")}/).when_present.click
From your example, it looks like you are using the URL from the onclick event handler as a :text locator, which I'd expect to fail unless that text does exist.
You could potentially click on the img. Examples:
browser.image(:title, "Edit").click
browser.image(:src, "/media/images/edit.gif?1258500617").click
browser.image(:src, /edit\.gif\?\d{10}/).click # regex the src
Otherwise, you might need to use the fire_event method to trigger the event handler, which looks like this:
browser.link(:id, "foo").fire_event "onclick"
These are the links to the fire_event docs for watir and watir-webdriver for reference.

Nokogiri/Mechanize xpath locator breaks when there is a stray start tag

I loaded a page using Mechanize:
url = 'http://www.blah.com'
agent = Mechanize.new
page = agent.get(url)
and tried to access an element using an XPath selector:
found = page.at('/html/body/table')
It returns nil because the HTML, which is out of my control, has an opening tag where it shouldn't be:
<html>
<body>
<tr>
<table>
. . .
The "stray start tag," as Firefox calls it, is ignored when the browser renders the page in real life (and Firefox gives me xpaths that ignore it), but Nokogiri can't see anything past that extra <tr>.
Is there any way to clean the HTML of hanging tags like this?
In your example it would be:
page.at '/html/body/tr/table'
But maybe it makes more sense to just do:
page.at 'table'
Use a less brittle XPath query?
found = page.at('//table')
You can clean this using Nokogiri easily:
require 'nokogiri'
html = '<html><body><tr><table><tr><td>foo</td></tr></table></tr></body></html>'
doc = Nokogiri::HTML(html)
inner_table = doc.at('//body/tr/table')
if (inner_table)
doc.at('body tr').replace(inner_table)
end
puts doc.to_html
With the result being:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><table><tr><td>foo</td></tr></table></body></html>
If your HTML is more complex, then find some sort of marker similar to the <body><tr><table> node-chain, and substitute it into the code above.
Note that I'm mixing both XPath and CSS accessors. I prefer CSS for their readability, but sometimes XPath makes it easier to get at something or is more self-documenting.
Also notice that I'm using both XPath and CSS with Nokogiri's at method. Though Nokogiri supports both at, at_css and at_xpath, I rely on at unless I need to explicitly tell Nokogiri that what I'm using as an accessor is CSS or XPath. It's a convenience thing. The same applies to Nokogiri's search method.

How to get a mail address from HTML code with Nokogiri

How can I get the mail address from HTML code with Nokogiri? I'm thinking in regex but I don't know if it's the best solution.
Example code:
<html>
<title>Example</title>
<body>
This is an example text.
Mail to me
</body>
</html>
Does a method exist in Nokogiri to get the mail address if it is not between some tags?
You can extract the email addresses using xpath.
The selector //a will select any a tags on the page, and you can specify the href attribute using # syntax, so //a/#href will give you the hrefs of all a tags on the page.
If there are a mix of possible a tags on the page with different urls types (e.g. http:// urls) you can use xpath functions to further narrow down the selected nodes. The selector
//a[starts-with(#href, \"mailto:\")]/#href
will give you the href nodes of all a tags that have a href attribute that starts with "mailto:".
Putting this all together, and adding a little extra code to strip out the "mailto:" from the start of the attribute value:
require 'nokogiri'
selector = "//a[starts-with(#href, \"mailto:\")]/#href"
doc = Nokogiri::HTML.parse File.read 'my_file.html'
nodes = doc.xpath selector
addresses = nodes.collect {|n| n.value[7..-1]}
puts addresses
With a test file that looks like this:
<html>
<title>Example</title>
<body>
This is an example text.
Mail to me
A Web link
<a>An empty anchor.</a>
</body>
</html>
this code outputs the desired example#example.com. addresses is an array of all the email addresses in mailto links in the document.
I'll preface this by saying that I know nothing about Nokogiri. But I just went to their website and looked at the documentation and it looks pretty cool.
If you add an email_field class (or whatever you want to call it) to your email link, you can modify their example code to do what you are looking for.
require 'nokogiri'
require 'open-uri'
# Get a Nokogiri::HTML:Document for the page we’re interested in...
doc = Nokogiri::HTML(open('http://www.yoursite.com/your_page.html'))
# Do funky things with it using Nokogiri::XML::Node methods...
####
# Search for nodes by css
doc.css('.email_field').each do |email|
# assuming you have than one, do something with all your email fields here
end
If I were you, I would just look at their documentation and experiment with some of their examples.
Here's the site: http://nokogiri.org/
CSS selectors can now (finally) find text at the beginning of a parameter:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
blah
blah
EOT
doc.at('a[href^="mailto:"]')
.to_html # => "blah"
Nokogiri tries to track the jQuery extensions. I used to have a link to a change-notice or message from one of the maintainers talking about it but my mileage has varied.
See "CSS Attribute Selectors" for more information.
Try to get the whole html page and use regular expressions.

How to get Text value of <legend> tag using xpath in ruby watir.(using IE)

I have following code in my ie web page. I want text value of tag (means "ABCD:"). I am using ruby watir for that.
<fieldset>
<legend class="fieldset">ABCD:</legend>
<fieldset>
I have tried with below code, but I don't why its not working and giving error(undefined method `text' for nil:NilClass)
ie.element_by_xpath("//legend[contains(#class, 'fieldset')]/").text
Is there any other way or is there anything wrong in my code.
Is that the only time the class of 'fieldset' is used on the page?
The list of supported elements shows unknown for Watir and supported for Watir-Webdriver for the legend tag.
Have you tried using Watir-Webdriver and code along these lines?
puts browser.legend(:class => 'fieldset').text
That's cleaner, easier to read, and will likely be faster. Only resort to using xpath if nothing else works

how do I assert that a hyperlink points to a given URL?

I am using Selenium IDE and Selenium RC to check links on a website, but I am having trouble finding a way to assert that a link points to a specified url and has the specified text.
Constraints:
locating the element by dom or xpath is not feasible for it will make the test brittle
there are multiple link elements with identical link text
The HTML:
link text
link text
The test I'd like to do (rspec):
page.is_element_present?("Href=path_y, Link=link text").should be_true
#locator parameters are in order of preference
Any ideas?
i guess get_attribute should help. you should get href from link, it is attribute.
You could use isElementPresent as follows:
assertTrue(selenium.isElementPresent("//a[text()='Example Link' and #href='http://www.example.com/']");
Given the following HTML:
<html>
<body>
<a id="myLink" href="http://www.example.com">Example Link</a>
</body>
</html>
You could use the following Selenium commands (using Java/TestNG, and Selenium 1.x)
assertEquals(selenium.getText("id=myLink#href"), "Example Link");
assertEquals(selenium.getAttribute("id=myLink#href"), "http://www.example.com/");
Using Selenium 2.x the example would be:
WebElement myLink = driver.findElement(By.id("myLink"));
assertEquals(myLink.getText(), "Example Link");
assertEquals(myLink.getAttribute("href"), "http://www.example.com/");

Resources