Search code examples
rubyfirefoxselenium-webdriverwatirgeckodriver

How to take full page screenshots with Watir and geckodriver + Firefox?


I upgraded my Watir / Firefox automation stack to the latest version, and added geckodriver with it. I was surprised to see that now screenshots are of the viewport only by default.

require 'watir'
require 'mini_magick'

b = Watir::Browser.new :firefox
b.goto "https://daringfireball.net"
base = b.screenshot.base64
blob = Base64.decode64(base)
image = MiniMagick::Image.read(blob)
image.height
 => 1760 # macOS 'Retina' resolution doubling
b.execute_script "return window.innerHeight"
 => 880 # 880 * 2 = 1760
b.execute_script "return document.documentElement.scrollHeight"
 => 34692

geckodriver does not have any API for full page screenshots, though reintroducing this feature is planned (on an infinite timescale).

How can I take screenshots of the full page with Watir driving Firefox without rolling back my environment?


Solution

  • It is now possible to do this in Firefox, employing a geckodriver feature. As far as I know, this feature is not baked into Selenium / probably not a part of the W3C spec.

    require 'watir'
    
    browser = Watir::Browser.new :firefox
    bridge = browser.driver.session_storage.instance_variable_get(:@bridge)
    
    server_uri = bridge.instance_variable_get(:@http).instance_variable_get(:@server_url)
    sid = bridge.instance_variable_get(:@session_id)
    driver_path = "session/#{sid}/moz/screenshot/full"
    request_url = server_uri.to_s + driver_path
    
    url = URI.parse(request_url)
    req = Net::HTTP::Get.new(request_url)
    raw = Net::HTTP.start(url.host, url.port) {|http| http.request(req) }.body
    
    base64_screenshot = JSON.parse(raw, symbolize_names: true)[:value]
    

    This approach is also now an option in the watir-screenshot-stitch gem:

    require 'watir-screenshot-stitch'
    b = Watir::Browser.new :firefox
    b.goto "https://github.com/mozilla/geckodriver/issues/570"
    base64_screenshot = b.base64_geckodriver