lib/capybara/screenshot/diff/stabilization.rb in capybara-screenshot-diff-1.7.1 vs lib/capybara/screenshot/diff/stabilization.rb in capybara-screenshot-diff-1.8.0

- old
+ new

@@ -1,184 +1 @@ -# frozen_string_literal: true - -require_relative "os" - -module Capybara - module Screenshot - module Diff - module Stabilization - include Os - - def take_stable_screenshot(comparison, stability_time_limit:, wait:, crop:) - previous_file_name = comparison.old_file_name - screenshot_started_at = last_image_change_at = Time.now - clean_stabilization_images(comparison.new_file_name) - - 1.step do |i| - take_right_size_screenshot(comparison, crop: crop) - if comparison.quick_equal? - clean_stabilization_images(comparison.new_file_name) - break - end - - comparison.reset - - if previous_file_name - stabilization_comparison = make_stabilization_comparison_from( - comparison, - comparison.new_file_name, - previous_file_name - ) - if stabilization_comparison.quick_equal? - if (Time.now - last_image_change_at) > stability_time_limit - clean_stabilization_images(comparison.new_file_name) - break - end - next - else - last_image_change_at = Time.now - end - end - - previous_file_name = build_snapshot_version_file_name( - comparison, - i, - screenshot_started_at, - stabilization_comparison - ) - - FileUtils.mv(comparison.new_file_name, previous_file_name) - - check_max_wait_time( - comparison, - screenshot_started_at, - max_wait_time: max_wait_time(comparison.shift_distance_limit, wait) - ) - end - 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.' - @_csd_retina_warned = true - end - end - - private - - def build_snapshot_version_file_name(comparison, iteration, screenshot_started_at, stabilization_comparison) - "#{comparison.new_file_name.chomp(".png")}" \ - "_x#{format("%02i", iteration)}_#{(Time.now - screenshot_started_at).round(1)}s" \ - "_#{stabilization_comparison.difference_coordinates&.to_s&.gsub(", ", "_") || :initial}.png" \ - "#{ImageCompare::TMP_FILE_SUFFIX}" - end - - def make_stabilization_comparison_from(comparison, new_file_name, previous_file_name) - ImageCompare.new(new_file_name, previous_file_name, comparison.driver_options) - end - - def reduce_retina_image_size(file_name, driver) - return if !ON_MAC || !selenium? || !Capybara::Screenshot.window_size - - expected_image_width = Capybara::Screenshot.window_size[0] - saved_image = driver.from_file(file_name) - 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) - end - - def stabilization_images(base_file) - Dir["#{base_file.chomp(".png")}_x*.png#{ImageCompare::TMP_FILE_SUFFIX}"].sort - end - - def clean_stabilization_images(base_file) - FileUtils.rm stabilization_images(base_file) - end - - def prepare_page_for_screenshot(timeout:) - assert_images_loaded(timeout: timeout) - - if Capybara::Screenshot.blur_active_element - blurred_input = blur_from_focused_element - end - - if Capybara::Screenshot.hide_caret - hide_caret - end - - blurred_input - end - - def take_right_size_screenshot(comparison, crop:) - driver = comparison.driver - - save_screenshot(comparison.new_file_name) - - # TODO(uwe): Remove when chromedriver takes right size screenshots - reduce_retina_image_size(comparison.new_file_name, driver) - # ODOT - - if crop - image = driver.from_file(comparison.new_file_name) - cropped_image = driver.crop(crop, image) - driver.save_image_to(cropped_image, comparison.new_file_name) - end - end - - def check_max_wait_time(comparison, screenshot_started_at, max_wait_time:) - return if (Time.now - screenshot_started_at) < max_wait_time - - annotate_stabilization_images(comparison) - # FIXME(uwe): Change to store the failure and only report if the test succeeds functionally. - fail("Could not get stable screenshot within #{max_wait_time}s\n" \ - "#{stabilization_images(comparison.new_file_name).join("\n")}") - end - - def annotate_stabilization_images(comparison) - previous_file = comparison.old_file_name - stabilization_images(comparison.new_file_name).each do |file_name| - if File.exist? previous_file - stabilization_comparison = make_stabilization_comparison_from( - comparison, - file_name, - previous_file - ) - if stabilization_comparison.different? - FileUtils.mv stabilization_comparison.annotated_new_file_name, file_name - end - FileUtils.rm stabilization_comparison.annotated_old_file_name - end - previous_file = file_name - end - end - - def max_wait_time(shift_distance_limit, wait) - shift_factor = shift_distance_limit ? (shift_distance_limit * 2 + 1) ^ 2 : 1 - wait * shift_factor - end - - def assert_images_loaded(timeout:) - return unless respond_to? :evaluate_script - - start = Time.now - loop do - pending_image = pending_image_to_load - break unless pending_image - - assert( - (Time.now - start) < timeout, - "Images not loaded after #{timeout}s: #{pending_image.inspect}" - ) - - sleep 0.1 - end - end - end - end - end -end \ No newline at end of file