lib/capybara/screenshot/diff/screenshoter.rb in capybara-screenshot-diff-1.8.3 vs lib/capybara/screenshot/diff/screenshoter.rb in capybara-screenshot-diff-1.9.0
- old
+ new
@@ -20,114 +20,133 @@
def wait
@capture_options[:wait]
end
+ def screenshot_format
+ @capture_options[:screenshot_format] || "png"
+ end
+
+ def capybara_screenshot_options
+ @capture_options[:capybara_screenshot_options] || {}
+ end
+
def self.attempts_screenshot_paths(base_file)
- Dir["#{base_file.to_s.chomp(".png")}.attempt_*.png"].sort
+ extname = Pathname.new(base_file).extname
+ Dir["#{base_file.to_s.chomp(extname)}.attempt_*#{extname}"].sort
end
def self.cleanup_attempts_screenshots(base_file)
FileUtils.rm_rf attempts_screenshot_paths(base_file)
end
# 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
def take_comparison_screenshot(screenshot_path)
- new_screenshot_path = Screenshoter.gen_next_attempt_path(screenshot_path, 0)
+ capture_screenshot_at(screenshot_path)
- take_screenshot(new_screenshot_path)
-
- FileUtils.mv(new_screenshot_path, screenshot_path, force: true)
Screenshoter.cleanup_attempts_screenshots(screenshot_path)
end
def self.gen_next_attempt_path(screenshot_path, iteration)
- Pathname.new(screenshot_path).sub_ext(format(".attempt_%02i.png", iteration))
+ screenshot_path.sub_ext(format(".attempt_%02i#{screenshot_path.extname}", iteration))
end
+ PNG_EXTENSION = ".png"
+
def take_screenshot(screenshot_path)
blurred_input = prepare_page_for_screenshot(timeout: wait)
# Take browser screenshot and save
- browser_save_screenshot(screenshot_path)
+ save_and_process_screenshot(screenshot_path)
- # Load saved screenshot and pre-process it
- process_screenshot(screenshot_path)
- ensure
blurred_input&.click
end
- def browser_save_screenshot(screenshot_path)
- BrowserHelpers.session.save_screenshot(screenshot_path)
- end
+ def process_screenshot(stored_path, screenshot_path)
+ screenshot_image = driver.from_file(stored_path)
- def process_screenshot(screenshot_path)
# TODO(uwe): Remove when chromedriver takes right size screenshots
# TODO: Adds tests when this case is true
- if selenium_with_retina_screen?
- reduce_retina_image_size(screenshot_path)
- end
+ screenshot_image = resize_if_needed(screenshot_image) if selenium_with_retina_screen?
# ODOT
- if crop
- image = driver.from_file(screenshot_path)
- cropped_image = driver.crop(crop, image)
- driver.save_image_to(cropped_image, screenshot_path)
- end
- end
+ screenshot_image = driver.crop(crop, screenshot_image) if crop
- def reduce_retina_image_size(file_name)
- expected_image_width = Screenshot.window_size[0]
- saved_image = driver.from_file(file_name.to_s)
- return 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)
- resized_image = driver.resize_image_to(saved_image, expected_image_width, new_height)
-
- driver.save_image_to(resized_image, file_name)
+ driver.save_image_to(screenshot_image, screenshot_path)
end
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.'
+ 'You should add "force-device-scale-factor=1" to your Chrome chromeOptions args.'
@_csd_retina_warned = true
end
end
def prepare_page_for_screenshot(timeout:)
- wait_images_loaded(timeout: timeout)
+ wait_images_loaded(timeout: timeout) if timeout
- blurred_input = if Screenshot.blur_active_element
- BrowserHelpers.blur_from_focused_element
- end
+ blurred_input = BrowserHelpers.blur_from_focused_element if Screenshot.blur_active_element
if Screenshot.hide_caret
BrowserHelpers.hide_caret
end
blurred_input
end
def wait_images_loaded(timeout:)
- start = Time.now
+ 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 (Time.now - start) >= timeout
- raise Capybara::Screenshot::Diff::ASSERTION, "Images not loaded after #{timeout}s: #{pending_image.inspect}"
+ 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
+
+ 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
+
+ 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
+
+ def take_and_process_screenshot(new_screenshot_path, screenshot_path)
+ take_screenshot(new_screenshot_path)
+ move_screenshot_to(new_screenshot_path, screenshot_path)
+ end
+
+ def move_screenshot_to(new_screenshot_path, screenshot_path)
+ FileUtils.mv(new_screenshot_path, screenshot_path, force: true)
+ end
+
+ 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
def selenium_with_retina_screen?
Os::ON_MAC && BrowserHelpers.selenium? && Screenshot.window_size
end
end