How to pass browser parameter to Watir - ruby

I am using Ruby and am using the latest gem version of Watir. I plan to use headless browser such as PhantomJS. How can one pass paramater to the Phantom JS browser when it get executed.
My purpose is so that Phantom JS do not need to load images.

As described on the PhantomJS command line page, there is an option to control the loading of images:
--load-images=[true|false] load all inlined images (default is true). Also accepted: [yes|no].
During the initialization of a Watir::Browser, these settings can be specified, as an array, in the :args key. For example:
args = %w{--load-images=false}
browser = Watir::Browser.new(:phantomjs, :args => args)
A working example:
require 'watir-webdriver'
# Capture screenshot with --load-images=true
browser = Watir::Browser.new(:phantomjs)
browser.goto 'https://www.google.com'
browser.screenshot.save('phantomjs_with_images.png')
# Capture screenshot with --load-images=false
args = %w{--load-images=false}
browser = Watir::Browser.new(:phantomjs, :args => args)
browser.goto 'https://www.google.com'
browser.screenshot.save('phantomjs_without_images.png')
Which gives the screenshot with images loaded:
And the screenshot without images loaded:
Notice that the Google image of the page is not loaded in the second screenshot (as expected since load-images was set to false).

Related

WATIR: Is there a reason why browser scrolling won't work?

I'm trying to use browser.scroll.to :bottom but nothing happens.
I know that it works because I've tried it on public facing sites such as the BBC and Wikipedia, but for some reason, these scroll commands don't work on our in-house browser based app.
Does anyone know of any reasons or settings that could be preventing this from happening?
Things such as browser.refresh and browser.window.maximize work fine but the scrolling literally refuses to budge.
Here's what my code looks like:
require 'watir'
require_relative 'regression_config_bob01.rb'
require 'date'
require 'faker'
require 'slack-notifier'
require 'watir-scroll'
user_name = "blah"
password = "blah"
test_env = "the Site"
browser = Watir::Browser.new
browser.goto(test_env)
# Login
browser.text_field(:name => 'P101_USERNAME').set user_name
browser.text_field(:tabindex=> '2').set password
browser.link(:text => "Log in").click
sleep 20
browser.wd.action.scroll_by(0, 1000).perform # Suggested Scroll line
print "done"
sleep 30
temporary_exp.rb:62:in <main>': undefined method scroll_by' for #<Selenium::WebDriver::W3CActionBuilder:0x000000014ac54bd0 #bridge=#<Selenium::WebDriver::Remote::W3C::Bridge:0x000000014ac1e440 #capabilities=#<Selenium::WebDriver::Remote::W3C::Capabilities:0x000000014ac1e940 #capabilities={:proxy=>nil, :browser_name=>"chrome", :browser_version=>"106.0.5249.119", :platform_name=>"mac os x", :accept_insecure_certs=>false, :page_load_strategy=>"normal", :implicit_timeout=>0, :page_load_timeout=>300000, :script_timeout=>30000, :remote_session_id=>nil, :accessibility_checks=>nil, :profile=>nil, :rotatable=>nil, :device=>nil, "chrome"=>{"chromedriverVersion"=>"105.0.5195.52 (412c95e518836d8a7d97250d62b29c2ae6a26a85-refs/branch-heads/5195#{#853})", "userDataDir"=>"/var/folders/hb/h_0h2t79183fkkppsr6r19nc0000gn/T/.com.google.Chrome.BV85VD"}, "goog:chromeOptions"=>{"debuggerAddress"=>"localhost:50818"}, "networkConnectionEnabled"=>false, "setWindowRect"=>true, "strictFileInteractability"=>false, "unhandledPromptBehavior"=>"dismiss and notify", "webauthn:extension:credBlob"=>true, "webauthn:extension:largeBlob"=>true, "webauthn:virtualAuthenticators"=>true}>, #session_id="8c59128dd44054681f62819d2fed25cf", #http=#<Watir::HttpClient:0x000000014ab6e298 #open_timeout=60, #read_timeout=nil, #server_url=#<URI::HTTP http://127.0.0.1:9515/>, #proxy=nil, #http=#<Net::HTTP 127.0.0.1:9515 open=true>>, #file_detector=nil, #escaper=#URI::RFC2396_Parser:0x000000014b0cbbc8, #manage=#<Selenium::WebDriver::W3CManager:0x000000014ab640b8 #bridge=#<Selenium::WebDriver::Remote::W3C::Bridge:0x000000014ac1e440 ...>, #window=#<Selenium::WebDriver::Window:0x000000014aa17ca0 #bridge=#<Selenium::WebDriver::Remote::W3C::Bridge:0x000000014ac1e440 ...>>>>, #devices=[#<Selenium::WebDriver::Interactions::PointerInput:0x000000014ac54f40 #name="mouse", #actions=[], #kind=:mouse>, #<Selenium::WebDriver::Interactions::KeyInput:0x000000014ac54d38 #name="keyboard", #actions=[]>], #async=false> (NoMethodError)
The current scroll implementation is using javascript to move the page around. For some reason your app is not responding to the JS commands in the normal way.
Selenium has recently released native scrolling via the drivers that Watir has not yet been updated. Take a look at the Selenium documentation on it: https://www.selenium.dev/documentation/webdriver/actions_api/wheel/?language=ruby
To use this in watir, you just need to add the line to the top: driver = browser.wd
So to scroll down by 2000 pixels, you can do:
driver = browser.wd
driver.action
.scroll_by(0, 2000)
.perform
like Titus said, Watir is a wrapper for Selenium and lets you write shorter and prettier code, like
browser.scroll.to :bottom
browser.scroll.to :top
browser.element(id: "asd").scroll.to
but when (for any reason) it doesn't work you can use Selenium syntax directly by sending commands to browser.wd instead browser like this:
browser.wd.action.scroll_by(0, 1000).perform #this scrolls bottom
browser.wd.action.scroll_by(0, -1000).perform #this scrolls top
browser.wd.action.scroll_to(browser.wd.find_element(id: "asd")).perform
but instead of writing browser.wd every time you need to talk to driver directly, you can type driver = browser.wd so your code is more clear:
driver = browser.wd
driver.action.scroll_by(0, 1000).perform #this scrolls bottom
driver.action.scroll_by(0, -1000).perform #this scrolls top
some_element = driver.find_element(id: "asd")
driver.action.scroll_to(some_element).perform
There are countless examples where using Watir is more efficient than talking to driver directly, you just happened to encounter an edge case.
Also try avoiding sleep when possible, instead, wait for something to show, like:
browser.element(id: 'asd').wait_until(&:present?)
browser.element(id: 'asd').wait_until({ |el| el.text == "Success" })
some_element = browser.element(id: 'asd')
browser.wait_until(30){some_element.present?}
Instead of .element you can use correct subclass like .div, .button, .span etc

Full-page screenshot with URL in ruby ​and watir

With the code below, I get a screenshot of only one part of the screen, but I would like to take a full screenshot, which shows the URL of the page as well.
Is it possible?
AfterStep do
encoded_img = #browser.driver.screenshot_as(:base64)
embed("data:image/png;base64,#{encoded_img}",'image/png')
end
Watir doesn't have this provision to capture the screenshot along with a URL. But we can use win32ole to do this.
require 'win32/screenshot'
Win32::Screenshot::Take.of(:desktop).write(image_path)
In my case for capturing the full-screenshot with a URL, I do the following
# Code to capture the full-page screenshot with a URL
require 'watir'
require 'win32ole'
require 'win32/screenshot'
# Launch a browser and navigate to the page
browser = Watir::Browser.new :ie
browser.goto "https://www.google.com"
win_title = browser.title #Fetch the Title
# Use AutoIt to get the focus of the browser to front
WIN32OLE.new("AutoItX3.Control").ControlFocus(win_title, "", "")
# Capture the screen shot of the desktop
sleep 2 # Hold for 2s
image_path = "image_path#{rand(10000)}.png"
Win32::Screenshot::Take.of(:desktop).write(image_path)
In my case for capturing the Full-screenshot with URL, I do the following
#Code to capture the Full-Page screenshot with URL
require 'watir'
require 'win32ole'
require 'win32/screenshot'
#Launch Browser and navigate to page
browser = Watir::Browser.new :ie
browser.goto "https://www.google.com"
#Fetch the Title
win_title = browser.title
#Use AutoIt to get the focus of the browser to front
WIN32OLE.new("AutoItX3.Control").ControlFocus(win_title, "", "")
#Capture the screen shot of the desktop
sleep 2 # Hold for 2s
image_path = "image_path#{rand(10000)}.png"
Win32::Screenshot::Take.of(:desktop).write(image_path)

How can I check whether new page is completely loaded or not using Watir

Is there any way I can check whether a particular page completely loaded or not using Watir?
I tried with browser.status but it's not printing anything.
Depending on what you mean by completely loaded? All HTML or all HTML and JavaScripts.
For HTML
browser = Watir::Browser.new
#To check if page has been loaded
ready = browser.ready_state.eql? "complete"
#To wait until page has been loaded
browser.wait
For JavaScript and HTML. For these you have to wait for each specific element
This code will wait until the element i enable, meaning clickable.
browser = Watir::Browser.new
browser.text_field(:id => 'id_of_object').wait_until_present

Watir doesn't see element with Phantomjs

I'm trying to take a screenshot of form with this code:
require 'watir'
browser = Watir::Browser.new :phantomjs
browser.driver.manage.window.maximize
browser.goto 'https://www.binbank.ru/landing/credits/'
browser.ul(class: 'r-buttons').li(text: '6').click
sleep 2
browser.screenshot.save 'a.png'
And a.png doesn't capture form. With Firefox as browser form is seen on a.png. Why is that? How can I interact with this form with PhantomJS?
PhantomJS seems to have problems with SSL on that page. You somehow need to pass --ignore-ssl-errors=true to the underlying webdriver.
Judging by How to pass browser parameter to Watir this can be done like this:
args = %w{--ignore-ssl-errors=true}
browser = Watir::Browser.new(:phantomjs, :args => args)

Save image with watir-webdriver

How could i save image, which is loaded via watir-webdriver? All manuals and examples show only fetching src of image, and using open-uri saving it. But i need to save that image, which was generated when my page was loaded. How can i do this?
Could i use watir, and watir-webdriver at the same time? For example:
require 'watir-webdriver'
require 'watir'
#driver = Watir::Browser.new :firefox
#driver.goto (#base_url)
#img = #driver.image(id: 'CaptchaImage').save("2131.png")
How can i do something like this? Or else how to get it from cache?
Could anybody help me with it?
OpenURI will help you ..
require "watir-webdriver"
require "open-uri"
b = Watir::Browser.new :chrome
b.goto "http://stackoverflow.com/"
File.open("target_file.jpg", 'wb') do |f|
f.write open(b.img(:class, "sponsor-tag-img").src).read
end
Hope you are not doing anything bad.. :)
Please let me know if it helped.
require 'watir-webdriver'
And if you're doing it frequently, you can extend Watir's Image class with:
Watir::Image.class_eval do
def save path_to_new_file
#so that src can be opened without raising:
#Errno::ENOENT: No such file or directory # rb_sysopen
require 'open-uri'
open(path_to_new_file, 'wb') do |file|
file << open(src).read
end
end
end
so it can be used as follows:
browser = Watir::Browser.start 'google.com'
image = browser.img
image.save 'our_images/hi.png'
According to the watir-webdriver documentation, there is no Image#save method because it hasn't been implemented.
On the other hand, watir-classic does have a Image#save method. This is the example from the rdoc:
browser.image.save("c:/foo/bar.jpg")
This turned out to be a lil harder than it should be, but I needed to accomplish this since an image was only accessible when a valid session cookie is set. This is how I finally managed to accomplish this:
1. Install watir-extentions-element-screenshot
https://github.com/ansoni/watir-extensions-element-screenshot
You probably want to do gem install watir-extensions-element-screenshot.
2. Resize the browser window
This also works with headless phantomJS. After you initialize the browser, set the window size to something rather big to prevent a bug from happening when the image is larger than the browser window.
browser = Watir::Browser.new :phantomjs
browser.window.resize_to(1900, 1080)
3. Get the image element and screenshot it
In my case, the entire site is an image. Luckily, browser.html does show that the image is still encapsulated in an <img> tag, so we can access the image (in this example all images on the page) like so:
browser.elements( :tag_name => "img" ).each do |x|
x.screenshot("file_name.png")
end
This will save the image to file_name.png. It's not the exact same file, rather a screenshot of it. But as far as image download is concerned, this is a perfect solution for me and hopefully for others too!

Resources