lib/capybara/screenshot/diff/capybara_setup.rb in capybara-screenshot-diff-0.5.3 vs lib/capybara/screenshot/diff/capybara_setup.rb in capybara-screenshot-diff-0.6.0
- old
+ new
@@ -95,12 +95,12 @@
end
end
teardown do
if Capybara::Screenshot::Diff.enabled && @test_screenshots
- test_screenshot_errors =
- @test_screenshots.map { |args| assert_image_not_changed(*args) }.compact
+ test_screenshot_errors = @test_screenshots
+ .map { |caller, name, compare| assert_image_not_changed(caller, name, compare) }.compact
fail(test_screenshot_errors.join("\n\n")) if test_screenshot_errors.any?
end
end
def screenshot_section(name)
@@ -112,39 +112,39 @@
@screenshot_counter = 0
return unless Capybara::Screenshot.active? && name.present?
FileUtils.rm_rf screenshot_dir
end
- def screenshot(name)
+ def screenshot(name, color_distance_limit: Capybara::Screenshot::Diff.color_distance_limit,
+ area_size_limit: nil)
return unless Capybara::Screenshot.active?
return if window_size_is_wrong?
if @screenshot_counter
name = "#{format('%02i', @screenshot_counter)}_#{name}"
@screenshot_counter += 1
end
name = full_name(name)
file_name = "#{self.class.screenshot_area_abs}/#{name}.png"
- org_name = "#{self.class.screenshot_area_abs}/#{name}_0.png~"
- new_name = "#{self.class.screenshot_area_abs}/#{name}_1.png~"
FileUtils.mkdir_p File.dirname(file_name)
- committed_file_name = check_vcs(name, file_name, org_name)
- previous_file_exists = committed_file_name && File.exist?(committed_file_name)
- previous_size = File.size(committed_file_name) if previous_file_exists
- take_stable_screenshot(file_name, previous_size)
- return unless previous_file_exists
- (@test_screenshots ||= []) << [caller[0], name, file_name, committed_file_name, new_name, org_name]
+ committed_file_name = check_vcs(name, file_name)
+ comparison = Capybara::Screenshot::Diff::ImageCompare.new(committed_file_name, file_name,
+ dimensions: Capybara::Screenshot.window_size, color_distance_limit: color_distance_limit,
+ area_size_limit: area_size_limit)
+ take_stable_screenshot(comparison)
+ return unless comparison.old_file_exists?
+ (@test_screenshots ||= []) << [caller[0], name, comparison]
end
private def window_size_is_wrong?
selenium? && Capybara::Screenshot.window_size &&
(!page.driver.chrome? || ON_WINDOWS) && # TODO(uwe): Allow for Chrome when it works
page.driver.browser.manage.window.size !=
Selenium::WebDriver::Dimension.new(*Capybara::Screenshot.window_size)
end
- def check_vcs(name, file_name, org_name)
+ private def check_vcs(name, file_name)
svn_file_name = "#{self.class.screenshot_area_abs}/.svn/text-base/#{name}.png.svn-base"
if File.exist?(svn_file_name)
committed_file_name = svn_file_name
else
svn_info = `svn info #{file_name} #{SILENCE_ERRORS}`
@@ -153,21 +153,25 @@
checksum = svn_info.slice(/(?<=Checksum: ).*$/)
if checksum
committed_file_name = "#{wc_root}/.svn/pristine/#{checksum[0..1]}/#{checksum}.svn-base"
end
else
- committed_file_name = org_name
- redirect_target = "#{committed_file_name} #{SILENCE_ERRORS}"
- `git show HEAD~0:./#{self.class.screenshot_area}/#{name}.png > #{redirect_target}`
- if File.size(committed_file_name) == 0
- FileUtils.rm_f committed_file_name
- end
+ committed_file_name = restore_git_revision(name,
+ Capybara::Screenshot::Diff::ImageCompare.annotated_old_file_name(file_name))
end
end
committed_file_name
end
+ private def restore_git_revision(name, org_name)
+ committed_file_name = org_name
+ redirect_target = "#{committed_file_name} #{SILENCE_ERRORS}"
+ `git show HEAD~0:./#{self.class.screenshot_area}/#{name}.png > #{redirect_target}`
+ FileUtils.rm_f(committed_file_name) if File.size(committed_file_name) == 0
+ committed_file_name
+ end
+
IMAGE_WAIT_SCRIPT = <<EOF.freeze
function pending_image() {
var images = document.images;
for (var i = 0; i < images.length; i++) {
if (!images[i].complete) {
@@ -188,32 +192,37 @@
"Images not loaded after #{timeout}s: #{pending_image.inspect}"
sleep 0.1
end
end
- def take_stable_screenshot(file_name, original_file_size = nil)
+ private def take_stable_screenshot(comparison)
assert_images_loaded
- old_file_size = original_file_size
+ previous_file_size = comparison.old_file_size
screeenshot_started_at = last_image_change_at = Time.now
loop do
- save_screenshot(file_name)
+ save_screenshot(comparison.new_file_name)
# TODO(uwe): Remove when chromedriver take right size screenshots
- reduce_retina_image_size(file_name)
+ reduce_retina_image_size(comparison.new_file_name)
# EMXIF
break unless Capybara::Screenshot.stability_time_limit
- new_file_size = File.size(file_name)
- break if new_file_size == original_file_size
- break if new_file_size == old_file_size &&
- (Time.now - last_image_change_at) > Capybara::Screenshot.stability_time_limit
- last_image_change_at = Time.now if new_file_size != old_file_size
- old_file_size = new_file_size
- sleep 0.1
+ break if comparison.quick_equal?
+ if comparison.new_file_size == previous_file_size
+ if (Time.now - last_image_change_at) > Capybara::Screenshot.stability_time_limit
+ break
+ end
+ else
+ last_image_change_at = Time.now
+ end
+
assert (Time.now - screeenshot_started_at) < Capybara.default_max_wait_time,
"Could not get stable screenshot within #{Capybara.default_max_wait_time}s"
+
+ previous_file_size = comparison.new_file_size
+ comparison.reset
end
end
private def reduce_retina_image_size(file_name)
return if !self.class.macos? || !selenium? || !Capybara::Screenshot.window_size
@@ -223,14 +232,16 @@
height = (width * saved_image.height) / saved_image.width
resized_image = saved_image.resample_bilinear(width, height)
resized_image.save(file_name)
end
- def assert_image_not_changed(caller, name, file_name, committed_file_name, new_name, org_name)
- if Capybara::Screenshot::Diff::ImageCompare.compare(committed_file_name, file_name,
- Capybara::Screenshot.window_size)
- "Screenshot does not match for '#{name}'\n#{file_name}\n#{org_name}\n#{new_name}\nat #{caller}"
- end
+ def assert_image_not_changed(caller, name, comparison)
+ return unless comparison.different?
+ "Screenshot does not match for '#{name}' (area: #{comparison.size} #{comparison.dimensions}" \
+ ", max_color_distance: #{comparison.max_color_distance.round(1)})\n" \
+ "#{comparison.new_file_name}\n#{comparison.annotated_old_file_name}\n" \
+ "#{comparison.annotated_new_file_name}\n" \
+ "at #{caller}"
end
end
end
# rubocop:enable Metrics/ClassLength