mattheworiordan / capybara-screenshot

Automatically save screen shots when a Capybara scenario fails
MIT License
1.02k stars 168 forks source link

Screenshot not getting entire page #284

Open mfaughn opened 3 years ago

mfaughn commented 3 years ago

I am using capybara-selenium w/ Chrome headless. The screenshots that are saved on failure are not getting the entire page. The error I'm having is farther down on the page than what is shown in the saved PNG file. Is there some way to configure things to capture the entire page or to take an image that is positioned relative to the last successful focus from capybara?

n-rodriguez commented 3 years ago

A solution would be to get the document height/width on the fly with some JS :

height = Math.max($(document).height(), $(window).height())
width = Math.max($(document).width(), $(window).width())

see: https://stackoverflow.com/a/14744331

and do the screenshot with these values instead of using the configured :window_size

I've done the test on my side :

Here my Capybara config :

def register_driver(driver_name)
  opts = {
    js_errors: true,
    timeout: 15,
    window_size: [1920, 1200],
    browser_options: {
      'no-sandbox': nil,
      'disable-gpu': nil,
      'disable-dev-shm-usage': nil,
      'disable-infobars': nil,
      'disable-extensions': nil,``
      'disable-popup-blocking': nil,
    }
  }

  Capybara.register_driver(driver_name) do |app|
    Capybara::Cuprite::Driver.new(app, opts)
  end

  Capybara::Screenshot.register_driver(driver_name) do |driver, path|
    driver.save_screenshot(path)
  end
end

# Register our own custom drivers
register_driver(:headless_chrome)

# Configure Capybara JS driver
Capybara.current_driver    = :headless_chrome
Capybara.javascript_driver = :headless_chrome

capybara-screenshot generates 1920x1200 images.

I've made a full page screenshot with the Firefox tool (right click / make a screenshot) and it generates a 2548x2465 image.

Running the JS above in a console returns (of course) the right values :

Math.max($(document).width(), $(window).width())
2548
Math.max($(document).height(), $(window).height())
2465
n-rodriguez commented 3 years ago

After studying the various API this does the trick for Cuprite (tested in CI) :

Capybara::Screenshot.register_driver(driver_name) do |driver, path|
  driver.save_screenshot(path, full: true)
end

See:

https://github.com/rubycdp/ferrum/blob/master/lib/ferrum/page/screenshot.rb#L31 https://github.com/rubycdp/ferrum/blob/master/lib/ferrum/page/screenshot.rb#L175

n-rodriguez commented 3 years ago

Ferrum doc : https://github.com/rubycdp/ferrum#screenshots

TylerRick commented 2 years ago

It looks like it already passes full: true to save_screenshot for the driver named :cuprite as of e19db98b1f6a142a63084e694677f1250bd8e4d4.

So it looks like you only ran into this because you weren't using the default name for the driver (you're calling yours :headless_chrome, which is a great name, by the way—I think I may copy that).

(I've run into similar problems when I've tried to use names that make more sense to me, like calling my Firefox driver :firefox instead of using the default name of :selenium.)

It would be nice if Capybara::Screenshot looked up the adapter code for the current driver based on page.driver.class (Capybara::Cuprite::Driver) rather than Capybara.current_driver (:headless_chrome). Then it wouldn't matter which custom name you had used to register the driver with Capybara (Capybara.register_driver)—it would find it regardless of the name used!

Does that sound reasonable to you guys? If so, here's a MR; please merge. :smile:

huda-kh commented 4 months ago

I am having the issue with selenium. If I set full: true I get:

WARN: Screenshot could not be saved. An exception is raised: #<ArgumentError: unknown keyword: :full>.
cycomachead commented 3 months ago

In Selenium full was renamed to full_page, which explains the last error.

However, note that it only is supported in Firefox. https://github.com/SeleniumHQ/selenium/issues/14116