1
votes

I'm struggling to find a solution to this, having tried many options.

My ideal goal is to be able to screenshot

  • Grab a specific CSS element
  • Grab the full height of the element (even if longer than the height of the page)
  • Wait for any assets contained to have fully loaded
  • Fast

First attempt (using selenium-webdriver with chromedriver installed)

Gemfile

gem 'selenium-webdriver'

App.rb

require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome 
driver.get url
driver.save_screenshot("screenshot.png")

This works to a degree, but the screenshot is trimmed to a maximum height (which looks like a very old issue with Chromedriver https://code.google.com/p/chromedriver/issues/detail?id=294)

Second attempt (using poltergeist to switch to phantomjs instead)

Gemfile

gem 'capybara'
gem 'poltergeist'

App.rb

require "capybara/dsl"
require "capybara/poltergeist"
Capybara.run_server = false
Capybara.register_driver :poltergeist do |app|
  Capybara::Poltergeist::Driver.new(app, {
    # Raise JavaScript errors to Ruby
    js_errors: true,
    # Additional command line options for PhantomJS
    phantomjs_options: ['--ignore-ssl-errors=yes', '--ssl-protocol=any'],
  })
end
Capybara.current_driver = :poltergeist

class Screenshot
  include Capybara::DSL

  # Captures a screenshot of +url+ saving it to +path+.
  def capture(url, path)
    # Open page
    visit url

    if page.driver.status_code == 200
      page.driver.save_screenshot(path, :full => true)
      puts "screenshot saved"
    else
      # Handle error
      puts "there was a problem #{page.driver.status_code}"
    end
  end
end

screenshot = Screenshot.new
screenshot.capture url, "screenshot.png"

This has different problems,

Third Attempt (using Capybara to try to take advantage of page.save_screenshot(path, :full => true))

Gemfile

gem 'selenium-webdriver'
gem 'capybara'

App.rb

require 'selenium-webdriver'
require "capybara/dsl"

Capybara.register_driver :chrome do |app|
  Capybara::Selenium::Driver.new(app, :browser => :chrome)
end

Capybara.current_driver = :chrome

class Screenshot
  include Capybara::DSL

  # Captures a screenshot of +url+ saving it to +path+.
  def capture(url, path)
    # Open page
    visit url

    page.save_screenshot(path, :full => true)
    puts "screenshot saved"

  end
end

screenshot = Screenshot.new
screenshot.capture url, "screenshot.png"

Short version - this doesn't help

Fourth Attempt (Using Watir)

Gemfile

gem 'watir-webdriver'

App.rb

require 'watir-webdriver'
b = Watir::Browser.new
b.goto url
b.screenshot.save 'screenshot.png'

This works (launches Firefox), but has the same issue over DevicePixelRatio for the ability to take a retina screenshot.

Fifth attempt (back to using Chrome)

App.rb

require 'watir-webdriver'
b = Watir::Browser.new :chrome
b.goto url
b.screenshot.save './tmp/watir.png'

Straight back to the cropped page issue.

Ideally I think that there may be a way to achieve this using the mobile emulation options of the latest ChromeDriver v2.12

Specifying Individual Device Attributes

It is also possible to enable Mobile Emulation by specifying individual attributes. To enable Mobile Emulation this way, the “mobileEmulation” dictionary can contain a “deviceMetrics” dictionary and a “userAgent” string. The following device metrics must be specified in the “deviceMetrics” dictionary: “width” - the width in pixels of the device’s screen “height” - the height in pixels of the device’s screen “pixelRatio” - the device’s pixel ratio

https://sites.google.com/a/chromium.org/chromedriver/mobile-emulation

But haven't managed to get it working.

Any suggestions would be really appreciated thanks!

1

1 Answers

1
votes

As this question hasn't been answered by anyone else I thought I'd outline the solution that I used to get as close to the ideal as possible.

Ultimately until these issues with phantom JS are solved

it appears the only driver capable of ensuring a full height screenshot is the Firefox driver.

Although it doesn't support retina using device pixels for my purposes I was able to transform using CSS the scale to 200% and the majority of elements (except bitmap images) are accurate.

For a working example of screen capturing a specific tweet at retina resolution in Ruby see here : https://github.com/chrism/twitter-screenshot