Watir WebDriver select list without standard html - ruby

Just started using Watir-WebDriver, came across website with and facing an problem.
1) Goto "https://www.smiles.com.br/home"
2) How to get/set values to drop down selections like selecting number of adults in "Adulto"
Selection list initially is hidden but when clicked on the text field it become visible in browser.
But when I tried using to click and check its existence it returning false
1) b.text_field(:id => "inputOrigin").click
2) irb(main):049:0> b.a(:id => 'yui_patched_v3_11_0_1_1467245841395_1777').exist?
=> false
Since its not actually a selection list, how do I set values?
Thanks in advance.

The ID is dynamic so it changes every time. It looks like it might be based on the time, but this should be sufficiently unique:
b.link(id: /^yui_patched_v3_11_0_1_/)

After clicking on <input id="inputOrigin">, you need to perform another click to trigger the "dropdown" list. Otherwise, you'll get a element not visible error. You could do something like this:
require 'watir-webdriver'
b = Watir::Browser.new :chrome
b.goto('https://www.smiles.com.br/home')
b.text_field(:id => "inputOrigin").when_present.click
b.div(:id => "dk_container_qtdAdult").when_present.click #trigger "dropdown" menu
b.div(:class => "adult").link(:text => "02").when_present.click
# b.div(:class => "adult").link(:data_dk_dropdown_value => "02").click #an alternative
Once selected, you can get the option using the .text method:
puts b.div(:id => "dk_container_qtdAdult").link(:class => "dk_toggle dk_label").text
Lastly, you could use regex locators, but you might have more success by trying to identify more discrete (and--ideally--unique) page elements.

Related

ruby watir - get all divs inner contents from search

I am attempting to scrape a website (respectfully). I tried with Nokogiri, then mechanize, then because the website i am scraping is loading a form dynamically, I was forced to use a webdriver. I am currently using ruby's watir.
What i am trying to do, is to fill out the dynamic form with a select, clicking submit, going to the results part of the page (form renders result on same page), and collecting all the divs with the information (traversing through sub-divs looking for hrefs).
def scrape
browser = Watir::Browser.new
browser.goto 'http://www.website-link.com'
browser.select_list(:id => 'city').select('cityName')
browser.link(:id, 'btnSearch').click
# this part; results from search are in this div w/ this ID
# however, iterating through this list does not work the way i expected
browser.div(:id, 'resultsDiv').divs.each do |div|
p div
end
browser.close
end
right now this returns
#<Watir::Div: located: true; {:id=>"resultsDiv", :tag_name=>"div"} --> {:tag_name=>"div", :index=>0}>
#<Watir::Div: located: true; {:id=>"resultsDiv", :tag_name=>"div"} --> {:tag_name=>"div", :index=>1}>
#<Watir::Div: located: true; {:id=>"resultsDiv", :tag_name=>"div"} --> {:tag_name=>"div", :index=>2}>
which looking at the page source looks like there are 3 divs inside of the resultsDiv which is probably what those indexes are. I guess what i was expecting (coming from Nokogiri/Mechanize) is an object to manipulate.
does anyone have any experience doing this that could point me to the right direction?
If you known the order that you want, you can do:
browser.driver.find_elements(:id => 'resultsDiv')[n].click
or
browser.div(:id => 'resultsDiv')[n].click
or
browser.div(:id, 'resultsDiv').div(:id,'id_n').click

Ruby selenium gem: open hyperlinks in multiple tabs

Goal: In irb, open a series of hyperlinks in new tabs and save a screenshot of each.
Code:
require "rubygems"
require "selenium-webdriver"
browser = Selenium::WebDriver.for:firefox
browser.get 'https://company.com'
browser.find_element(:name, "username").send_keys("myUsername")
browser.find_element(:name, "password").send_keys("myPassword")
browser.find_element(:name, "ibm-submit").click
body = browser.find_element(:tag_name => 'body')
body.send_keys(:control, 't')
parent = browser.find_element(:xpath, "//div[#id='someid']")
children = parent.find_elements(:xpath,"//a")
children.each do |i| ;
body.send_keys(:control, 't')
i.click
browser.save_screenshot("{i}")
end
Problem:
Selenium::WebDriver::Error::StaleElementReferenceError: Element not found in the cache - perhaps the page has changed since it was looked up
Question: What am I doing wrong?
Basically you can't share WebElements across pages, yet you're trying to access body across multiple tabs. Try not to think of them as self-contained objects, but as proxies to something on a real page.
The solution is to only ever perform actions on the 'current' page. In your case that means sending the Ctrl-T event on the tab that you've created. Having done that the first time, you're switched to the new tab. You then need to re-perform the lookup:
newTabsBody = browser.find_element(:tag_name => 'body')
and then:
newTabsBody.send_keys(:control, 't')
to create the next one. Continue for each child.

How do I read text from non visible elements with Watir (Ruby)?

There is a div on a page that is not visible but has some value I want to capture. Calling text on it returns me an empty string.
How do I get the value displayed without having to deal with the raw html? Can I force .text to return me the actual value regardless of the visiblity of the text in the browser?
irb(main):1341:0> d.first.visible?
=> false
irb(main):1344:0> d.first.html
=> "<div class=\"day\">7</div>"
irb(main):1345:0> d.first.text
=> ""
PS: There are many many divs (the page is caching response and display them accordingly). I considered changing all the display:none in the page or clicking to make them visible but I'd prefer to avoid this if possible.
If not possible a solution with changing all the display none would be the preferred work around.
PPS: Damned, I tried to overload the visible? method in the Watir::Element class to always return true, but that didn't do the trick.
irb(main):1502:0> d.first.visible?
=> true
irb(main):1504:0> d.first.text
=> ""
For the newer versions of Watir, there is now an Element#text_content method that does the below JavaScript work for you.
e = d.first
e.text_content
#=> "7"
For Old Versions of Watir (Original Answer):
You can use JavaScript to get this.
e = d.first
browser.execute_script('return arguments[0].textContent', e)
#=> "7"
Note that this would only work for Mozilla-like browsers. For IE-like browsers, you would need to use innerText. Though if you are using watir-classic it would simply be d.first.innerText (ie no execute_script required).
Using attribute_value:
Turns out you can make it simpler by using the attribute_value method. Seems it can get the same attribute values as javascript.
d.first.attribute_value('textContent')
#=> "7"
Using inner_html
If the element only includes text nodes (ie no elements), you can also use inner_html:
d.first.inner_html
#=> "7"
Try using the execute_script method do change the value of "visible" to visible. Something like document.getElementById('id').style.visibility = 'visible' assuming it has an ID. If it does not you can always ask the devs to put a test-id on the element (or just do it yourself).

Clear input field and enter new info using Watir? (Ruby, Watir)

Pretty positive you have to use .clear, or maybe not as it doesn't seem to be working for me, maybe i'm just implementing it wrong I'm unsure.
Example:
browser.div(:id => "formLib1").clear.type("input", "hi")
Can anyone tell me how to simply clear a field then enter in a new string?
Assuming we are talking about a text field (ie you are not trying to clear/input a div tag), the .set() and .value= methods automatically clear the text field before inputting the value.
So one of the following would work:
browser.text_field(:id, 'yourid').set('hi')
browser.text_field(:id, 'yourid').value = 'hi'
Note that it is usually preferred to use .set since .value= does not fire events.
I had a similar issue, and, for some reason, .set() and .value= were not available/working for the element.
The element was a Watir::Input:
browser.input(:id => "formLib1").to_subtype.clear
after clearing the field I was able to enter text.
browser.input(:id => "formLib1").send_keys "hi"
I had a similar issue, and, for some reason, .set() and .value= were not available for the element.
The element was a Watir::HTMLElement:
[2] pry(#<Object>)> field.class
=> Watir::HTMLElement
field.methods.grep /^(set|clear)$/
=> []
I resorted to sending the backspace key until the value of the field was "":
count = 0
while field.value != "" && count < 50
field.send_keys(:backspace)
count += 1
end
field.send_keys "hi"

Initiate Button click action using Watir Ruby library

Watir::Browser.default = "firefox"
ie = Watir::Browser.start("http://cars.com")
ie.select_list(:id, 'make_1').set('Chevrolet')
ie.select_list(:id, 'model_1').set('Cobalt')
ie.select_list(:id, 'pricehighnew').set('No Max')
ie.select_list(:id, 'rdnew').set('30 miles')
ie.text_field(:name, "zc").set "44109"
ie.form(:method, "GET").submit #Here is the problem...
URL: http://www.cars.com/
Can anyone help me initiate button click action searching for "New Cars" form on the top left. Seems like they are using JavaScript as well. I appreciate any help.
There's probably a way to do it with JavaScript, but taking just a minute I was able to click the button two different ways:
ie.span(:text=>"Search New").click
ie.link(:href=>"javascript:checkZipFirst(document.newForm, quickSubmitNew, document.newForm.zc.value);").click
Also any of these would work:
browser.a(:class => "button primary zc-submit").click
or
browser.link(:name => "submit").click
or
browser.a(:id => "submit", :index => n).click
where n is the index number

Resources