Skip to content

Commit

Permalink
refact: extracted default reporter
Browse files Browse the repository at this point in the history
  • Loading branch information
pftg committed Dec 10, 2023
1 parent 7a0da8e commit 97e10ad
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 58 deletions.
3 changes: 3 additions & 0 deletions lib/capybara/screenshot/diff.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@
require "capybara/screenshot/diff/test_methods"
require "capybara/screenshot/diff/screenshoter"

require "capybara/screenshot/diff/reporters/default"

module Capybara
module Screenshot

mattr_accessor :add_driver_path
mattr_accessor :add_os_path
mattr_accessor :blur_active_element
Expand Down
8 changes: 6 additions & 2 deletions lib/capybara/screenshot/diff/difference.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@
module Capybara
module Screenshot
module Diff
class Difference < Struct.new(:region, :meta, :comparison)
class Difference < Struct.new(:region, :meta, :comparison, :failed_by)
def different?
!(blank? || tolerable?)
failed? || !(blank? || tolerable?)
end

def failed?
!!failed_by
end

def base_image
Expand Down
84 changes: 29 additions & 55 deletions lib/capybara/screenshot/diff/image_compare.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def initialize(image_path, base_image_path, options = {})
@driver_options = options.dup

@driver = Drivers.for(@driver_options)
@reporter = Capybara::Screenshot::Diff::Reporters::Default.new(self, @annotated_image_path, @annotated_base_image_path)
end

def self.build(image_path, base_image_path, options = {})
Expand Down Expand Up @@ -68,24 +69,23 @@ def quick_equal?
def different?
@error_message = nil

@error_message = _different?
@difference = find_difference

clean_tmp_files unless @error_message
@error_message = reporter.generate(@difference)

!@error_message.nil?
clean_tmp_files unless @difference.different?

@difference.different?
end

def build_error_for_different_dimensions(comparison)
change_msg = [comparison.base_image, comparison.new_image]
.map { |i| driver.dimension(i).join("x") }
.join(" => ")

"Screenshot dimension has been changed for #{@new_file_name}: #{change_msg}"
reporter.build_error_for_different_dimensions(
{ comparison: comparison, new_file_name: new_file_name }
)
end

def clean_tmp_files
@annotated_base_image_path.unlink if @annotated_base_image_path.exist?
@annotated_image_path.unlink if @annotated_image_path.exist?
reporter.clean_tmp_files
end

def save(image, image_path)
Expand All @@ -106,22 +106,26 @@ def without_tolerable_options?
(@driver_options.keys & TOLERABLE_OPTIONS).empty?
end

def _different?
raise "There is no original (base) screenshot version to compare, located: #{@base_image_path}" unless @base_image_path.exist?
raise "There is no new screenshot version to compare, located: #{@image_path}" unless @image_path.exist?
def find_difference
raise ArgumentError, "There is no original (base) screenshot version to compare, located: #{@base_image_path}" unless @base_image_path.exist?
raise ArgumentError, "There is no new screenshot version to compare, located: #{@image_path}" unless @image_path.exist?

comparison = load_and_process_images

unless driver.same_dimension?(comparison)
return build_error_for_different_dimensions(comparison)
return Difference.new(
nil,
{ difference_level: nil, max_color_distance: 0 },
self,
{ different_dimensions: { comparison: comparison, new_file_name: new_file_name } }
)
end

return not_different if driver.same_pixels?(comparison)

@difference = driver.find_difference_region(comparison)
return not_different unless @difference.different?

different(@difference)
if driver.same_pixels?(comparison)
no_difference
else
driver.find_difference_region(comparison)
end
end

def load_and_process_images
Expand All @@ -130,15 +134,6 @@ def load_and_process_images
Comparison.new(new_image, base_image, @driver_options)
end

def build_error_message(difference)
[
"(#{difference.inspect})",
new_file_name,
annotated_base_image_path.to_path,
annotated_image_path.to_path
].join(NEW_LINE)
end

def skip_area
@driver_options[:skip_area]
end
Expand All @@ -151,11 +146,6 @@ def dimensions
@driver_options[:dimensions]
end

def different(difference)
annotate_and_save_images(difference)
build_error_message(difference)
end

def preprocess_images(images)
images.map { |image| preprocess_image(image) }
end
Expand Down Expand Up @@ -191,33 +181,17 @@ def new_file_size
end

def not_different
nil
end

def annotate_and_save_images(difference)
annotate_and_save_image(difference, difference.comparison.new_image, @annotated_image_path)
annotate_and_save_image(difference, difference.comparison.base_image, @annotated_base_image_path)
no_difference.different? || nil
end

def annotate_and_save_image(difference, image, image_path)
image = annotate_difference(image, difference.region)
image = annotate_skip_areas(image, difference.skip_area) if difference.skip_area
save(image, image_path.to_path)
def no_difference
@difference = Difference.new(nil, { difference_level: nil, max_color_distance: 0 }, self).freeze
end

DIFF_COLOR = [255, 0, 0, 255].freeze

def annotate_difference(image, region)
driver.draw_rectangles([image], region, DIFF_COLOR, offset: 1).first
def reporter
@reporter ||= Capybara::Screenshot::Diff::Reporters::Default.new(self)
end

SKIP_COLOR = [255, 192, 0, 255].freeze

def annotate_skip_areas(image, skip_areas)
skip_areas.reduce(image) do |memo, region|
driver.draw_rectangles([memo], region, SKIP_COLOR).first
end
end
end

class Comparison < Struct.new(:new_image, :base_image, :options)
Expand Down
96 changes: 96 additions & 0 deletions lib/capybara/screenshot/diff/reporters/default.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# frozen_string_literal: true

module Capybara::Screenshot::Diff
module Reporters
class Default
attr_reader :comparer, :annotated_image_path, :annotated_base_image_path

def initialize(comparer, annotated_image_path = nil, annotated_base_image_path = nil)
@comparer = comparer
@annotated_image_path = annotated_image_path || comparer.annotated_image_path
@annotated_base_image_path = annotated_base_image_path || comparer.annotated_base_image_path
end

def generate(difference)
return nil unless difference.different?

if difference.failed? && difference.failed_by[:different_dimensions]
return build_error_for_different_dimensions(difference.failed_by[:different_dimensions])
end

annotate_and_save_images(difference)
build_error_message(difference)
end


def clean_tmp_files
annotated_base_image_path.unlink if annotated_base_image_path.exist?
annotated_image_path.unlink if annotated_image_path.exist?
end

def build_error_for_different_dimensions(failed_by)
comparison, new_file_name = failed_by[:comparison], failed_by[:new_file_name]
change_msg = [comparison.base_image, comparison.new_image]
.map { |i| driver.dimension(i).join("x") }
.join(" => ")

"Screenshot dimension has been changed for #{new_file_name}: #{change_msg}"
end

def annotate_and_save_images(difference)
annotate_and_save_image(difference, difference.comparison.new_image, annotated_image_path)
annotate_and_save_image(difference, difference.comparison.base_image, annotated_base_image_path)
end

def annotate_and_save_image(difference, image, image_path)
image = annotate_difference(image, difference.region)
image = annotate_skip_areas(image, difference.skip_area) if difference.skip_area

save(image, image_path.to_path)
end

DIFF_COLOR = [255, 0, 0, 255].freeze

def annotate_difference(image, region)
driver.draw_rectangles([image], region, DIFF_COLOR, offset: 1).first
end

SKIP_COLOR = [255, 192, 0, 255].freeze

def annotate_skip_areas(image, skip_areas)
skip_areas.reduce(image) do |memo, region|
driver.draw_rectangles([memo], region, SKIP_COLOR).first
end
end

def save(image, image_path)
driver.save_image_to(image, image_path.to_s)
end

NEW_LINE = "\n".freeze

def build_error_message(difference)
[
"(#{difference.inspect})",
new_file_name,
annotated_base_image_path.to_path,
annotated_image_path.to_path
].join(NEW_LINE)
end

private

def reporter
self
end

def driver
@comparer.driver
end

def new_file_name
@comparer.new_file_name
end
end
end
end
2 changes: 1 addition & 1 deletion sig/capybara/screenshot/diff/image_compare.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ module Capybara

private

def _different?: -> String?
def find_difference: -> Difference

def different: (Difference images) -> String

Expand Down
22 changes: 22 additions & 0 deletions test/capybara/screenshot/diff/difference_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

require "test_helper"
require "capybara/screenshot/diff/difference"

module Capybara::Screenshot::Diff
class DifferenceTest < ActiveSupport::TestCase
class WithFailedByTest < DifferenceTest
setup do
@difference = Difference.new(nil, {}, nil, { different_dimensions: [] })
end

test 'it is different' do
assert_predicate @difference, :different?
end

test 'it is failed' do
assert_predicate @difference, :failed?
end
end
end
end

0 comments on commit 97e10ad

Please sign in to comment.