7
votes

I am working on screenshot automation. In particular, I am trying to achieve the following:

  1. Prompt the user for the links to different pages on the website X
  2. Prompt the user for the class name Y
  3. I should be able to visit a website X login page, provide login details (assume they are known), click on "submit" button, that should redirect me to the "home" page
  4. Then I look at the list of links, provided by the user, visit each page and take screenshots of all elements, that have class Y (or the entire page)
  5. Save them in the current directory

Please click on the link for visual representation

I wanted to implement the following solution in Ruby (but I am also open to any other suggestions):

1) Take a screenshot of the entire scrollable page on the website X 2) Find the element(s) of class Y, in particular its location on the page, width and height. 3) Crop the full screenshot so that only desired element is visible

Problem is the following:

I cannot take a screenshot of the entire page, I was only able to take a screenshot of the visible area of my screen.

This is what I tried and corresponding problems:

SOLUTION 1 (Ruby - General):

require 'selenium-webdriver'

driver = Selenium::WebDriver.for :firefox #:chrome

driver.navigate.to "https://some_very-very_long_page_on_website_X"
driver.manage.window.maximize # <- works for firefox only
driver.save_screenshot('picture1.png')

# Problem: it captures only the viewable area, 
# not an entire page

SOLUTION 2 (Ruby - Window Resizing):

require 'selenium-webdriver'

driver = Selenium::WebDriver.for :firefox #:chrome
driver.navigate.to 'https://some_very-very_long_page_on_website_X'

width  = driver.execute_script("return Math.max(document.body.scrollWidth,document.body.offsetWidth,document.documentElement.clientWidth,document.documentElement.scrollWidth,document.documentElement.offsetWidth);")
height = driver.execute_script("return Math.max(document.body.scrollHeight,document.body.offsetHeight,document.documentElement.clientHeight,document.documentElement.scrollHeight,document.documentElement.offsetHeight);")

driver.manage.window.resize_to(width, height) # <- resizes the window
driver.manage.window.full_screen  # <- works, but in chrome throws:
                                  # full_screen': undefined method `full_screen_window'

picture = driver.screenshot_as(:png)

File.open('picture2.png', 'w+') do |fh|
  fh.write picture
end

driver.quit

# Resizes the window only to the viewable area, as a result,
# it captures the viewable area only

SOLUTION 3 (Ruby- watir gem):

require 'watir'

b = Watir::Browser.new
b.goto 'https://some_very-very_long_page_on_website_X'
b.screenshot.save("picture.png")

# Issues: does not capture the entire page

SOLUTION 4 (Ruby - Single element capturing)

require "selenium-webdriver"

driver = Selenium::WebDriver.for :chrome

driver.get'https://some_very-very_long_page_on_website_X'

driver.manage.window.maximize
driver.execute_script("document.getElementById('some_id').scrollIntoView();")
driver.save_screenshot "picture3.png"

# Problem: captures the element, which I need, but only if its size is less than
# the viewable area

SOLUTION 5 (Ruby - Zooming)

require "selenium-webdriver"

driver = Selenium::WebDriver.for :firefox

driver.get 'https://some_very-very_long_page_on_website_X'

driver.manage.window.maximize
driver.execute_script("document.body.style.transform = 'scale(0.5)'")
#driver.execute_script("document.body.style.zoom = '50%'") <-- transform works better than zoom

driver.save_screenshot "picture3.png"

#Issues: works, but not for very long pages, in addition it may change the layout
# (some elements may start to overlap each other)
# Also I am not sure how to calculate the value of the parameter for scale
# for very long pages

SOLUTION 6 - (Ruby - Headless Chrome Resizing)

require "selenium-webdriver"

options = Selenium::WebDriver::Chrome::Options.new
options.add_argument('--headless')
driver = Selenium::WebDriver.for :chrome, options: options

driver.get "https://some_very-very_long_page_on_website_X"

width  = driver.execute_script("return Math.max(document.body.scrollWidth,document.body.offsetWidth,document.documentElement.clientWidth,document.documentElement.scrollWidth,document.documentElement.offsetWidth);")
height = driver.execute_script("return Math.max(document.body.scrollHeight,document.body.offsetHeight,document.documentElement.clientHeight,document.documentElement.scrollHeight,document.documentElement.offsetHeight);")

driver.manage.window.resize_to(width+2000, height+2000) # <-- if I do not have +2000, page looks squished
                                                        # the greater the number, the greater the quality
                                                        # but also the more white space is around the page
                                                        # and the picture is heavier
driver.manage.window.maximize

sleep 5             # <--- required waiting for page loading 
driver.save_screenshot "full.png"

# One of the best approaches, but it is not clear to me how to calculate 
# the parameters for resize_to

Tools/Technologies:

  • selenium-webdriver (3.12.0)
  • ChromeDriver 2.40
1
You're running into a limitation of the WebDriver spec - w3c.github.io/webdriver/#screen-capture - which defines the area of the screen when taking a screenshot as "the top-level browsing context’s initial viewport". WebDriver also specifies a method for taking a picture of a specific element but that doesn't appear to be made available through selenium-webdriver yet, and I'm not sure whether or not Chrome/chromedriver have implemented it yet or not (and would still be limited by current size of the window)Thomas Walpole
You can capture the full screenshot with Firefox, but Chrome just grabs the visible area. To capture the full page screenshot on Chrome you have to invoke the dev-tools. I have the code in python if you want I can post it.Ywapom
stackoverflow.com/questions/45199076/… has what you need I thinkYwapom
I follow your Solution 6, Can you please assist me to take full page screenshotSiva Ganesh

1 Answers

0
votes

You can use the watir-screenshot-stitch gem to do exactly what you want:

require 'watir-screenshot-stitch'
b = Watir::Browser.new :firefox
b.goto "https://github.com/mozilla/geckodriver/issues/570"
b.base64_geckodriver # => returns a base64-encoded full page screenshot.