verify scroller button works with preloaded data with watir-webdriver - ruby

I am trying to verify that a scroller button is working correctly. The button is an arrow image that slides a row of images/links, showing 5 out of the 10 images that are all loaded at page load. Whats making it difficult is that images are populated from a 3rd party provided so the urls change all the time. The only other identifier is by its class and text, the class is the same for all of them.
Since they are all loaded at the same time its hard to determine if the images are changing.
If you go to http://www.hayneedle.com/product/curiousgeorgepeelstickgiantmural.cfm and scroll to "Suggestions For You" you can see the on the right to scroll to a new set of suggestions. This button has broke before so need a simple way to regression it.
Any suggestions?

You can check if an image is actually visible to the user by using the present? method. You could also use the visible? method, but it throws an exception if the element does not exist. You can see a comparison of these and the .exists? method in the blog post, "Checking for an element – exists?, visible?, present?".
Knowing this, you could click the scrolling arrow and then check if last image is present (ie actually visible).
# Go to the page
browser = Watir::Browser.new :firefox
browser.goto 'http://www.hayneedle.com/product/curiousgeorgepeelstickgiantmural.cfm'
# This is the scroller control
scroller = browser.div(:id => 'HN_PP_RelatedCats')
# (optional) Check that the last image is *not* displayed
puts browser.div(:class => 'HN_Scroller_Cont').link(:index => 9).present?
#=> false
# Click the right scroller
scroller.div(:class => 'HN_Scroller_R').click
# Check that the last image is displayed
puts browser.div(:class => 'HN_Scroller_Cont').link(:index => 9).when_present.present?
#=> true
Note that the check for the last link/image is using when_present.present?. The when_present allows the scrolling to finish. Without it, you might end up checking the element before the scrolling is done (ie you false negative). The present? is there to return a true/false result.

Related

Ruby Watir reference Chrome Print Preview

I'm writing a script to cycle through some links and print to PDF.
When you click on one of the links a new window pops up of the document to be printed and on top of that new window Chrome's print preview box pops up.
I'm trying to change the printer and then click the print button.
What's happening with my code however is that watir is only looking at the window html and not the print preview html so the elements are unable to be located.
My code looks like this:
begin
browser.window(title: 'Window Title Name').use do
browser.div(:id => "navbar-scroll-container").button(:class => "destination-settings-change-button").click
sleep(1)
browser.element(:title => "CutePDF Writer").click
browser.button(:visible_text => 'Print').click
end
rescue Watir::Exception::NoMatchingWindowFoundException
retry
end
I have tried using just "browser.windows.last.use do" instead of the title name but that also doesn't work.
I know it can only see the underlying window's html because when I puts browser.html the output is that underlying windows html.
If you want to look at the html situation just Ctrl+P this page (in chrome) to see what I mean.
Of course, after posting a question I soon found a sort of answer; basically chrome opens 2 browser windows and the print preview one couldn't be accessed by title (because it had the same title as the underlying one) but could be accessed by browser.window(:index => 1).use do. not sure why browser.windows.last.use do didn't work. Also following that I would have thought browser.window(:index => 2).use do would have been the correct one as index 0 would be the originally opened one, index 1 the popup and index 2 the print preview.

Is there a way to determine if an element is clickable in Chrome Browser using Selenium and Watir?

As I understand it, this question is really only relevant when performing web test automation using Chrome browser due to the manner in which a click event is implemented with Selenium Webdriver and Chromedriver. To preface, I use and am aware of finding an element through the use of the Watir element function "present?", which as I understand is essentially a combination of "visible?" and "exists?". I could also, at need find an element with Webdriver element functions to identify if an element is present with a rescue for an exception if it is not. What I am trying to determine is the following:
At times, due to a lack of responsiveness to a page, there will be page elements that will be found and pass all validation tests for it's existence, but cannot actively actually be interacted with due to the aforementioned lack of page responsiveness. Using Chrome browser (with Chromedriver) attempts to interact with these elements will result in the error:
irb(main):003:0> #browser.button(:id, "button_login").present?
=> true
irb(main):004:0> #browser.button(:id, "button_login").click
Selenium::WebDriver::Error::UnknownError: unknown error: Element ... is not clickable at point (915,
nt would receive the click: ...
(Session info: chrome=66.0.3359.181)
(Driver info: chromedriver=2.38.552522 (437e6fbedfa8762dec75e2c5b3ddb86763dc9dcb),platform=Windows NT 6.3.9600 x86_64)
from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/response.rb:69:in 'assert_ok'
from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/response.rb:32:in 'initialize'
from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/http/common.rb:83:in 'new'
from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/http/common.rb:83:in 'create_response'
from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/http/default.rb:107:in 'request'
from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/http/common.rb:61:in 'call'
from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/bridge.rb:170:in 'execute'
from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/oss/bridge.rb:579:in 'execute'
from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/oss/bridge.rb:328:in 'click_element'
from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/common/element.rb:74:in 'click'
from C:/Ruby23/lib/ruby/gems/2.3.0/gems/watir-6.4.1/lib/watir/elements/element.rb:131:in 'block in click'
from C:/Ruby23/lib/ruby/gems/2.3.0/gems/watir-6.4.1/lib/watir/elements/element.rb:656:in 'element_call'
from C:/Ruby23/lib/ruby/gems/2.3.0/gems/watir-6.4.1/lib/watir/elements/element.rb:122:in 'click'
from (irb):4
from C:/Ruby23/bin/irb.cmd:19:in ''
I know I can rescue at this point, but that entails that I actually click the element. Essentially I want to write a special function "clickable?" that will return a boolean output without actually clicking the element and possibly navigating away from the page. I would prefer not to attempt this with a type of --ctrl+click, if new window return true, close window, set focus on first window, rescue return false-- workflow.
Watir 6.15.0+
Element#obscured? has been added to check for this scenario. You can now do:
browser.element(id: 'target').wait_while(&:obscured?).click
Watir pre-6.15.0
For older versions, you will need to take a different approach.
I would try waiting for the overlapping element to go away. If the overlapping is something like an overlay that will eventually disappear, it's relatively straightforward - eg:
browser.element(id: 'overlapping_element').wait_while(&:present?)
If the overlapping element gets moved rather than disappears or you don't know the overlapping element, you could try approximating the overlapping element check. When Chrome clicks an element, it gets the element's center location and then clicks at that point. If there the top-level element at that point is not your element, the exception is thrown. The following wait will do this check until there is no overlapping element:
target = browser.button
target_children = target.elements.to_a
browser.wait_until do
location = target.location
size = target.size
center = [location.x + size.width/2, location.y + size.height/2]
element_at_point = browser.execute_script("return document.elementFromPoint(#{center[0]}, #{center[1]});")
[target, target_children].flatten.include?(element_at_point)
end
target.click
Note that I haven't had to do this before, so I don't know if there are edge cases. Seemed to work with Chrome and Firefox.
I can suggest you to wait this button to show on the web page. I experienced the same problem (I was using XPath in my tests). To fix it:
Firstly I defined 2 helper methods because I had to reuse them a lot. One for searching of a exact element on the page(this method is usually takes a while to return a result so you don't need to sleep the browser) and one for clicking a button with given "id".
module Helpers
module Common
def wait_for_element_id(value)
find(:xpath, "(//*[#id='#{value}'])[1]")
end
def click_button_with_id(value)
first(:xpath, "//button[#id='#{value}']").click
end
end
end
After that in your test you can use the helper methods like:
it 'clicks on the login button and magic is executed' do
logout(user)
wait_for_element_id('button_login')
click_button_with_id('button_login')
expect(magic).to be_executed
end
I am also not sure but you can also experience the same problem because of the browser window size (button is not shown because the size is too low) or because of the "headless" mode of your tests.

how to scroll a web page using watir

I am trying to scroll a web page to find and click on a content that is lazily loaded when the page is scrolled. I am using following command
require 'watir-webdriver'
#browser = Watir::new :firefox
#browser.send_keys :space
I am using web-driver with firefox and I am on ubuntu but it is not working. In the following ruby code I am trying to scroll the page down until I don't find the element with :id. The element is loading lazily.
I am getting timeout after few seconds, any idea what is wrong with the following code.
When /^deal (\d+) is loaded$/ do |id|
(0..5).each do |click|
#browser.send_keys :space
end
end
What is the best way to scroll a page using watir-driver ?
If you have JavaScript enabled, you can access the underlying driver and execute some JavaScript to scroll on the page.
#browser.driver.executeScript("window.scrollBy(0,200)")
will scroll down the page 200 pixels along the y axix.
See here for documentation of the method:
http://www.w3schools.com/jsref/met_win_scrollby.asp
I use a gem called "watir-scroll" to assist me with this. Though it usually needs places to scroll to, it also will scroll to coordinates.
https://github.com/p0deje/watir-scroll
Since Watir v6.16 watir-scroll gem merged into watir
You can either scroll to a specific element
button1 = #browser.input(:class => "mileage_rate")
#browser.scroll.to button1
Or just scroll to the top middle or center
#browser.scroll.to :top
#browser.scroll.to :center
#browser.scroll.to :bottom
Or scroll to a coordinate
browser.scroll.to [0, 200]
This saved me a bunch of time:
browser.div(:id => 'start-date-holder').wd.location_once_scrolled_into_view
Sorry I could not comment on the last answer since I am new here and do not have enough rep pts yet so I just created a new answer. Anyways, if anyone is having issues with scrolling multiple times try this (add a loop and sleep):
maximum_times_needed = max # of times you need the page to scroll down
maximum_times_needed.each do
#browser.driver.executeScript("window.scrollBy(0,200)")
sleep 0.15
end
0.15 may vary depending on how long it takes the page to load. 0.15 is 0.15 seconds so adjust as needed to allow for enough time for the page to load. The 200 may also need to be adjusted to a larger pixel amount.
300.times do
#browser.driver.execute_script("window.scrollBy(0,200)")
sleep 0.05
end
You can access the underlying driver and execute some javascript. For instance if you wanted to scroll to the bottom of the page you would use
#browser.driver.execute_script( "window.scrollBy(0,document.body.scrollHeight)" )
which scrolls to the bottom of the page on the y-axis.
It works
evaluate_script("document.getElementsByTagName('body')[0].scrollTop=0;")

How can I automate a slider using watir-webdriver and ruby?

I am trying to automate a Jquery UI slider using watir-webdriver and ruby but am having no luck. I want to be able to manipulate the slider to either increase or decrease the value. I have searched everywhere and asked a few of my colleagues but no one has an answer. I am attaching a piece of HTML code for the slider. Any help would be much appreciated.
URL link: http://www.whatcar.com/new-car-deals/ (price range slider)
I haven't done any coding for the slider as I have no idea how to go about it. If I could be set on the right path that would be fantastic. Also it seems the HTML code doesn't seem to be showing on the question I am asking.
it's a Jquery widget that appears (looking at the scripts) to respond to key presses once one of the handles has been clicked on. the handles are link objects, inside a pair of divs, the outer one has the ID value 'slider-range'
You should be able to address them via browser.div(:id => 'slider-range').link(:index => n) where n = 0 for the lefthand one and n=1 for the right hand one.
Try this manually first
Click on the left handle for the slider
Then press arrow keys on the keyboard.. it will move 1K(pounds) up or down with each right or left arrow keypress.
Once you have moved it right, click the Home key and it should reset to its min value
repeat above for the right handle but reset it to far right using the End key.
In theory you could fire a click event at the right slider to get focus, then fire off some keypress events to first set it far right (end) followed by enough left arrows to move it down to the top value you want.
Repeat for the left handle, setting it to the left end with the home key, and moving it with right arrow keypresses
I don't have the time right now to experiment further and develop an exact script, but I think you could probably create two little functions even that took an upper and lower range value and did the required number of keypresses to move the lower up from 5K to the right amount, and the upper down from 100k
Note that this thing is very very event driven, it responds (at least when watching the dev tools while playing with it) to being moused over, mousedown, mouseup, etc.. if using click does not work to 'get the attention' of the control so it will respond to keypresses, try using the onmousedown event instead.
Using the code from your answer, to move the left slider to 12K I'd try
browser.div(:id => 'slider-range').link(:index => 0).click #make sure it has focus
browser.div(:id => 'slider-range').link(:index => 0).send_keys :home #set to 5K
7.times do
browser.div(:id => 'slider-range').link(:index => 0).send_keys :arrow_right
end
Thank you very much Chuck. I got it working. Here is the script I used:
#browser.link(:xpath, "/html/body/div/div[3]/div[4]/div/div/div/a").send_keys :arrow_right
Still needs a bit of tweaking, but I should be ok now.
This worked great. We just added these sliders to our website and my first thought was "how are we going to automate that!?"
I wanted to add an example will full code that is available publicly for people to experiment with. The following interacts with an example on jqueryui.com.
require "watir-webdriver"
#browser = Watir::Browser.new :chrome
#browser.goto "http://jqueryui.com/slider/#default"
#browser.frame(:class => "demo-frame").span(:class =>"ui-slider-handle").click
#browser.frame(:class => "demo-frame").span(:class =>"ui-slider-handle").send_keys :home
puts "clicked home"
7.times do
#browser.frame(:class => "demo-frame").span(:class =>"ui-slider-handle").send_keys :arrow_right
end
To achieve this using Rspec and Watir-Webdriver with Page-Object gem I used:
div(:slider, id: "slider-range") #in page file
#then in spec file
browser.slider_element.input.send_keys :home
This answer comes from http://watir.com/guides/special-keys/

how to scroll with selenium

I have here a challenge that I spent some time addressing.
Selenium tells me that it cannot click a link that is not visible, so that means I need to scroll my canvas? I am using ubuntu 10, firefox 3, selenium 0.1, ruby 1.9.2, and selenium-webdriver 2.5.0
My code is
driver = Selenium::WebDriver.for :firefox;
driver.get login_url
wait = Selenium::WebDriver::Wait.new(:timeout => 2)
wait.until {
driver.find_element(:name => 'j_password')
}
driver.find_element(:name => 'j_username').send_keys(username)
driver.focus(:name => 'j_username')`
and it says that focus() is not defined. How should I modify my code to put the input element on screen?
Um, this is a hypothetical example, I really need to scroll so that some other element is on the screen, but for simplicity I would like to be able to scroll s.t. any element is on the screen, even
location_once_scrolled_into_view to scroll using ruby.
As per your question your element is not visible, so selenium web driver is unable to click on it.
Simple solution to this is:
Store the xpath of the element which is visible and nearby to your element.
Scroll till that visible element, to make your element visible.
Ensure your element is now visible, click on it
eg code:
element = dirver.find_element(:xpath, "xpath of nearby visible element")
element.location_once_scrolled_into_view
my_element = driver.find_element(:xpath, "xpath of your element")
my_element.click
I had an element at the bottom of the page with no other element close enough to select first. Finally got around it by tabbing from the last field in the form on the page.
element.send_keys(:tab)
When the documentation says "not visible" it's not refering the view port, but to the status of the element on the page. If something is hidden with CSS it cannot be clicked.
If you want to scroll on the firefox window using selenium webdriver, one of the way is to use javaScript in the java code, The javeScript code to scroll down is as follows:
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("window.scrollTo(0,Math.max(document.documentElement.scrollHeight," +
"document.body.scrollHeight,document.documentElement.clientHeight));");
I'm not aware of ruby but the above code can be used as a java Script which will scroll down the whole page.You can even define the area you want to scroll in the view window by simply hard- coding the window.scrollTo(200,350);

Resources