I am trying to scrape a page, and need to click on some links within a menu. If I use the search method, I am then stuck with a Nokogiri object, and therefore can not use the click method.
agent.page.search('.right-menu').links_with(href: /^\/blabla\//).each do |link|
region = link.click
end
The following would tell me that links_with is not defined. How can I make a select links from a specific menu? Is there a way I can parse the object back to a Mechanize object?
You can try something like this:
agent.page.search('.youarehere > a').each do |a|
link = Mechanize::Page::Link.new(a.attr('href'), agent, agent.page)
region = link.click
end
not the cleanest way to do it I guess, but Mechanize is doing almost the same in its source code: http://mechanize.rubyforge.org/Mechanize/Page.html#method-i-links
Would be a nice addition though, instead of going through this.
Related
I have created this method to loop through the links in a certain div in the web site. My porpose of the method Is to collect the links insert them in an array then click each one of them.
require 'watir-webdriver'
require 'watir-webdriver/wait'
site = Watir::Browser.new :chrome
url = "http://www.cnn.com/"
site.goto url
box = Array.new
container = site.div(class: "column zn__column--idx-1")
wanted_links = container.links
box << wanted_links
wanted_links.each do |link|
link.click
site.goto url
site.div(id: "nav__plain-header").wait_until_present
end
site.close
So far it seems like I am only able to click on the first link then I get an error message stating this:
unable to locate element, using {:element=>#<Selenium::WebDriver::Element:0x634e0a5400fdfade id="0.06177683611003881-3">} (Watir::Exception::UnknownObjectException)
I am very new to ruby. I appreciate any help. Thank you.
The problem is that once you navigate to another page, all of the element references (ie those in wanted_links) become stale. Even if you return to the same page, Watir/Selenium does not know it is the same page and does not know where the stored elements are.
If you are going to navigate away, you need to collect all of the data you need first. In this case, you just need the href values.
# Collect the href of each link
wanted_links = container.links.map(&:href)
# You have each page URL, so you can navigate directly without returning to the homepage
wanted_links.each do |link|
site.goto url
end
In the event that the links do not directly navigate to a page (eg they execute JavaScript when clicked), you will need to collect enough data to re-locate the elements later. What you use as the locator will depend on what is known to be static/unique. As an example, I will assume that the link text is a good locator.
# Collect the text of each link
wanted_links = container.links.map(&:text)
# Iterate through the links
wanted_links.each do |link_text|
container = site.div(class: "column zn__column--idx-1")
container.link(text: link_text).click
site.back
end
I tried to click on link (see screenshots)
http://imgur.com/q66g7z6
http://imgur.com/KNF1y7z
I tried using few examples
e.g
#browser.button(:class=> '//*[#class="login"]//ul/li[0]/a').click
and
browser.button(:xpath=> "//a[#data-viewmodel='PagesAsync/RegisterPrivate/RegisterPrivateViewModel']").click
but is not correct
I can see the message that unable to locate element
Can somebody help?
The main problem is that you are telling Watir to look for a button when you actually want a link. While the UI may be styled to look like a button, you will notice that the HTML has a a tag instead.
The first example, which also has the wrong locator type, should be:
#browser.link(:xpath => '//*[#class="login"]//ul/li[0]/a').click
The second example should be:
browser.link(:xpath => "//a[#data-viewmodel='PagesAsync/RegisterPrivate/RegisterPrivateViewModel']").click
Note that the second example would be more Watir-like if you use the normal attribute locators:
browser.link(data_viewmodel: 'PagesAsync/RegisterPrivate/RegisterPrivateViewModel').click
There are two options. One is get your developers to add better IDs.
If that is not possible, try this:
how does ruby webdriver get element with hyphen in <name, value> pair
It worked for me in several similar situations.
I wonder how you can find a button by using an xpath to a link. It is also not clear whether you use browser or #browser. You would need to look into how the browser instance is defined, which likely is one of these:
#browser = Watir::Browser.new :chrome
###or###
browser = Watir::Browser.start 'example.com', :firefox
and if you haven't create a browser instance, then you would need to do it before you can use Watir-Webdriver. ;)
As for your question, you could try searching using the text if it is unique like this, though it may be a brittle test:
#browser.div(:class => 'login').link(:text => /For priva/).click
but I would recommend to double check the number of elements found using the div and link locators like this to make sure you got the right element:
#browser.divs(:class => 'login').length
#browser.div(:class => 'login').links(:text => /For priva/).length
I am trying to retrieve, modify, and reinsert some text in a pop up dialog using watir web-driver. All was going swimmingly until I tried to find a way to click the "Save Book Info" button pictured here: http://i.stack.imgur.com/pGdln.png
However I am unable to find the button. To access the pop up box I gather all the links with the correct name into an array:
#browser.imgs.each do |img| #The links are imgs
if img.title.include?('Edit/Delete Book')
#books << img
end
end
From there I can access the links with #books[index].click. I am able to access and edit the text_fields with:
url = #browser.text_field(:name=>'url').value
... do stuff with url ..
#browser.text_field(:name=>'url').set url
But when I try and find the "Close" button I only get the buttons that are on the main page. After many headaches I managed to find the title of the window I want to work with using #browser.div(:class=>'dijitDialogTitleBar').title, which returns "Edit Book". Success! No. I still can't figure out how to access the buttons on that popup!
If anyone could help me with this I would be most grateful. This is my first time using Watir so it's probably a simple answer...
If more information is needed I'd be happy to supply it. Thanks in advance.
EDIT
Here is the html for the button:
<span id="dijit_form_Button_2_label"
class="dijitReset dijitInline dijitButtonText"
dojoattachpoint="containerNode">Save Book Info</span>
It looks like you have a span tag that is styled to be looked like a button. You need to access it is a span instead of a button.
Try:
#browser.span(:text => 'Save Book Info').click
I'm automating IE with watir, and I want to know what html element(s) are clicked (selected). Can this be done using watir? win32ole? In a last chance, without ruby?
Something like:
Click a button -> button with id=213 and class=btn_class was clicked.
Click a text field -> text field with id=123 and value=my_text was clicked.
Try one of the recorders, Selenium IDE for example.
I'm not sure if I completely understand either, but would a custom function like this work?
def click(item, how, what)
#browser.item(how, what).click
puts "#{item} with #{how}->#{what} was clicked"
end
click("button", ":id", "awesome")
Edit: If you're attempting to identify page elements so that you can then use them in a Watir script, the Developer Toolbar is perfect for this application, much like Firebug for Firefox.
http://www.microsoft.com/download/en/details.aspx?id=18359
Your comment to me & your response to Zeljko appear to contradict each other. If you want to use WATIR for this task, the code above will execute a mouse click and post the information to console. The only other way to get information is to locate the object in WATIR and fish for more details:
object = #browser.button(:name, /myButton/)
object.id
object.title
object.status
object.height, etc.
or
#browser.divs.each do |div|
puts div.id, div.title
end
I'd recommend a strong look at the capabilities of the various developer tools, such as are provided with Chrome, Firefox, and IE. those are generally the best means to get this kind of information.
Watir is really about driving the browser, and getting info out of the DOM. it's not really setup to report on manual interactions with the browser.
I'm a bit further along in converting some sample test/specs from Watir to Selenium. After my last question here and suggested response, I began using Selenium 2.0 with WebDriver instead of Selenium 1.
The example in question deals with gathering all links within a table into an array -- that part is complete. However, once the links are in the array, the only meaningful way that I can interact with them appears to be .text. Using #driver.navigate.to Array[1] gives a URL format error in the browser, and link.href or .src are not valid options.
The Watir implementation gathered these links (pages added by users via CMS), stored them in an array and then visited each page one by one, submitting a lead form. I believe I could get this to work using Selenium and revisiting the "home" page that contains all of the links between lead form submissions, but that could mean hundreds of extra page loads, cached or not.
The code so far:
' #countries = Array.new
#browser.navigate.to "http://www.testingdomain{$env}.com/global"
#browser.find_elements(:xpath, "//table[#class='global-list']//a").each do |link|
#countries << [link.text, link.href] ## The original WATIR line that needs an update
end #links
#countries.uniq! #DEBUG for false CMS content'
The closest item I could find in the selenium-webdriver documentation was the (string).attribute method, but again, am unsure of what attributes
I was not sure of the format for use with the attribute method, but after some experimenting I was able to move past this step.
#countries = Array.new
#browser.navigate.to "http://www.testingdomain{$env}.com/global"
#browser.find_elements(:xpath, "//table[#class='global-list']//a").each do |link|
text = link.attribute("text")
href = link.attribute("href")
#countries << [text, href]
end #links
`#countries.uniq! #DEBUG for false CMS content
Looks like you found your answer to your question on your own.
Indeed, element.attribute allows you to pull any HTML attribute a tag could possibly have. Thus, since you were wanting to pull the URL of the element, you used element.attribute('href') to return the element's href="" attribute. The same can be done for any other attributes, including class, id, style, etc.