class Capybara::Screenshot::Screenshoter

Constants

PNG_EXTENSION

Attributes

capture_options[R]
comparison_options[R]
driver[R]

Public Class Methods

attempts_screenshot_paths(base_file) click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 33
def self.attempts_screenshot_paths(base_file)
  extname = Pathname.new(base_file).extname
  Dir["#{base_file.to_s.chomp(extname)}.attempt_*#{extname}"].sort
end
cleanup_attempts_screenshots(base_file) click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 38
def self.cleanup_attempts_screenshots(base_file)
  FileUtils.rm_rf attempts_screenshot_paths(base_file)
end
gen_next_attempt_path(screenshot_path, iteration) click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 51
def self.gen_next_attempt_path(screenshot_path, iteration)
  screenshot_path.sub_ext(format(".attempt_%02i#{screenshot_path.extname}", iteration))
end
new(capture_options, driver) click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 11
def initialize(capture_options, driver)
  @capture_options = capture_options
  @comparison_options = comparison_options
  @driver = driver
end

Public Instance Methods

capybara_screenshot_options() click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 29
def capybara_screenshot_options
  @capture_options[:capybara_screenshot_options] || {}
end
crop() click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 17
def crop
  @capture_options[:crop]
end
notice_how_to_avoid_this() click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 79
def notice_how_to_avoid_this
  unless defined?(@_csd_retina_warned)
    warn "Halving retina screenshot.  " \
           'You should add "force-device-scale-factor=1" to your Chrome chromeOptions args.'
    @_csd_retina_warned = true
  end
end
prepare_page_for_screenshot(timeout:) click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 87
def prepare_page_for_screenshot(timeout:)
  wait_images_loaded(timeout: timeout) if timeout

  blurred_input = BrowserHelpers.blur_from_focused_element if Screenshot.blur_active_element

  if Screenshot.hide_caret
    BrowserHelpers.hide_caret
  end

  blurred_input
end
process_screenshot(stored_path, screenshot_path) click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 66
def process_screenshot(stored_path, screenshot_path)
  screenshot_image = driver.from_file(stored_path)

  # TODO(uwe): Remove when chromedriver takes right size screenshots
  # TODO: Adds tests when this case is true
  screenshot_image = resize_if_needed(screenshot_image) if selenium_with_retina_screen?
  # ODOT

  screenshot_image = driver.crop(crop, screenshot_image) if crop

  driver.save_image_to(screenshot_image, screenshot_path)
end
screenshot_format() click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 25
def screenshot_format
  @capture_options[:screenshot_format] || "png"
end
take_comparison_screenshot(screenshot_path) click to toggle source

Try to get screenshot from browser. On ‘stability_time_limit` it checks that page stop updating by comparison several screenshot attempts On reaching `wait` limit then it has been failed. On failing we annotate screenshot attempts to help to debug

# File lib/capybara/screenshot/diff/screenshoter.rb, line 45
def take_comparison_screenshot(screenshot_path)
  capture_screenshot_at(screenshot_path)

  Screenshoter.cleanup_attempts_screenshots(screenshot_path)
end
take_screenshot(screenshot_path) click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 57
def take_screenshot(screenshot_path)
  blurred_input = prepare_page_for_screenshot(timeout: wait)

  # Take browser screenshot and save
  save_and_process_screenshot(screenshot_path)

  blurred_input&.click
end
wait() click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 21
def wait
  @capture_options[:wait]
end
wait_images_loaded(timeout:) click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 99
def wait_images_loaded(timeout:)
  return unless timeout

  deadline_at = Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout
  loop do
    pending_image = BrowserHelpers.pending_image_to_load
    break unless pending_image

    if Process.clock_gettime(Process::CLOCK_MONOTONIC) > deadline_at
      raise CapybaraScreenshotDiff::ExpectationNotMet, "Images have not been loaded after #{timeout}s: #{pending_image.inspect}"
    end

    sleep 0.025
  end
end

Private Instance Methods

capture_screenshot_at(screenshot_path) click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 126
def capture_screenshot_at(screenshot_path)
  new_screenshot_path = Screenshoter.gen_next_attempt_path(screenshot_path, 0)
  take_and_process_screenshot(new_screenshot_path, screenshot_path)
end
move_screenshot_to(new_screenshot_path, screenshot_path) click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 136
def move_screenshot_to(new_screenshot_path, screenshot_path)
  FileUtils.mv(new_screenshot_path, screenshot_path, force: true)
end
resize_if_needed(saved_image) click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 140
def resize_if_needed(saved_image)
  expected_image_width = Screenshot.window_size[0]
  return saved_image if driver.width_for(saved_image) < expected_image_width * 2

  notice_how_to_avoid_this

  new_height = expected_image_width * driver.height_for(saved_image) / driver.width_for(saved_image)
  driver.resize_image_to(saved_image, expected_image_width, new_height)
end
save_and_process_screenshot(screenshot_path) click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 117
def save_and_process_screenshot(screenshot_path)
  tmpfile = Tempfile.new([screenshot_path.basename.to_s, PNG_EXTENSION])
  BrowserHelpers.session.save_screenshot(tmpfile.path, **capybara_screenshot_options)
  # Load saved screenshot and pre-process it
  process_screenshot(tmpfile.path, screenshot_path)
ensure
  File.unlink(tmpfile) if tmpfile
end
selenium_with_retina_screen?() click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 150
def selenium_with_retina_screen?
  Os::ON_MAC && BrowserHelpers.selenium? && Screenshot.window_size
end
take_and_process_screenshot(new_screenshot_path, screenshot_path) click to toggle source
# File lib/capybara/screenshot/diff/screenshoter.rb, line 131
def take_and_process_screenshot(new_screenshot_path, screenshot_path)
  take_screenshot(new_screenshot_path)
  move_screenshot_to(new_screenshot_path, screenshot_path)
end