Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: specs for transparency support #31

Merged
merged 3 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,18 @@ AllCops:

Metrics/BlockLength:
CountAsOne: ['array', 'hash', 'heredoc', 'method_call']
AllowedMethods:
- describe
- context
- shared_examples
- RSpec::Matchers.define

Naming/MethodParameterName:
AllowedNames:
- x
- y
- cr
- x1
- y1
- x2
- y2
19 changes: 0 additions & 19 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,6 @@ Gemspec/RequiredRubyVersion:
Metrics/AbcSize:
Max: 94

# Offense count: 3
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
# IgnoredMethods: refine
Metrics/BlockLength:
AllowedMethods:
- describe
- context
- shared_examples

# Offense count: 1
# Configuration parameters: CountComments, CountAsOne.
Metrics/ClassLength:
Expand All @@ -52,16 +43,6 @@ Metrics/ParameterLists:
Metrics/PerceivedComplexity:
Max: 17

Naming/MethodParameterName:
AllowedNames:
- x
- y
- cr
- x1
- y1
- x2
- y2

# Offense count: 1
Naming/AccessorMethodName:
Exclude:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Support for visual image comparison in specs
- Automated visual comparison of images in specs, also serving as a record of exact rendering behaviour
- Development scripts for performing benchmarks
- Basic test coverage for transparency support

### Changed
- Extracted image operations to separate files within a dedicated module
Expand Down
Binary file added spec/fixtures/match-with-transparency.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 32 additions & 0 deletions spec/morandi_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,38 @@
expect(created_file_sizes.sort).to eq(files_in_increasing_quality_order)
end
end

context 'with transparent png input' do
let(:file_in) { 'spec/fixtures/match-with-transparency.png' }
let(:options) do
{
'gamma' => 1.1,
'fx' => 'sepia',
'crop' => [10, 2, 600, 840]
}
end

it 'applies transformations' do
process_image

expect(File).to exist(file_out)
expect(processed_image_type).to eq('jpeg')
expect(file_out).to match_reference_image('match-multiple-operations')
end

context 'with straighten option' do
# Tested explicitly, because morandi happens to handle transparency differently when using straighten
let(:options) { super().merge('straighten' => 2) }

it 'applies transformations' do
process_image

expect(File).to exist(file_out)
expect(processed_image_type).to eq('jpeg')
expect(file_out).to match_reference_image('match-multiple-operations-and-straighten')
end
end
end
end

context 'pixbuf processor' do
Expand Down
85 changes: 59 additions & 26 deletions spec/support/match_reference_image.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,31 @@ class ImageDebugData

attr_reader :exposed_reference_path, :exposed_tested_path, :exposed_diff_path

def initialize(name, file_type)
sanitised_name = name.gsub(/[^a-zA-Z0-9_-]+/, '-')
@output_dir = File.join(OUTPUT_ROOT, sanitised_name)
@exposed_reference_path = File.join(@output_dir, "reference.#{file_type}")
@exposed_tested_path = File.join(@output_dir, "tested.#{file_type}")
@exposed_diff_path = File.join(@output_dir, 'diff.png')
def initialize(name)
@name = name
end

def expose_from(reference_path:, tested_path:, diff_path:)
FileUtils.mkdir_p(@output_dir)
FileUtils.cp(tested_path, @exposed_tested_path)
FileUtils.cp(reference_path, @exposed_reference_path)
FileUtils.cp(diff_path, @exposed_diff_path)
def expose_from(file_type:, tested_path: nil, reference_path: nil, diff_path: nil)
sanitised_name = @name.gsub(/[^a-zA-Z0-9_-]+/, '-')
output_dir = File.join(OUTPUT_ROOT, sanitised_name)
FileUtils.mkdir_p(output_dir)

if reference_path
@exposed_reference_path = File.join(output_dir, "reference.#{file_type}")
FileUtils.cp(reference_path, @exposed_reference_path)
end

if tested_path
@exposed_tested_path = File.join(output_dir, "tested.#{file_type}")
FileUtils.cp(tested_path, @exposed_tested_path)
end

if diff_path
@exposed_diff_path = File.join(output_dir, 'diff.png')
FileUtils.cp(diff_path, @exposed_diff_path)
end

true
end
end
end
Expand All @@ -63,7 +75,18 @@ def expose_from(reference_path:, tested_path:, diff_path:)
RSpec::Matchers.define :match_reference_image do |reference_name, file_type: 'jpg', tolerance: 0|
reference_path = File.join('spec/fixtures/reference_images', "#{reference_name}.#{file_type}")

def debug_data
metadata = RSpec.current_example.metadata
spec_name = "#{metadata[:absolute_file_path].split('/spec/').last}:#{metadata[:scoped_id]}"
@debug_data ||= Morandi::SpecSupport::ImageDebugData.new(spec_name)
end

match do |tested_path|
if File.file?(tested_path) && !File.file?(reference_path)
debug_data.expose_from(tested_path: tested_path, file_type: file_type)
return false
end

tmp_diff = Tempfile.new('test-diff')
comparison = Morandi::SpecSupport::ImageComparison.new(reference_path: reference_path,
tested_path: tested_path,
Expand All @@ -72,25 +95,35 @@ def expose_from(reference_path:, tested_path:, diff_path:)
@normalized_mean_error = comparison.normalized_mean_error
return true if @normalized_mean_error <= tolerance

metadata = RSpec.current_example.metadata
spec_name = "#{metadata[:absolute_file_path].split('/spec/').last}:#{metadata[:scoped_id]}"
@debug_data = Morandi::SpecSupport::ImageDebugData.new(spec_name, file_type)

@debug_data.expose_from(reference_path: reference_path, tested_path: tested_path, diff_path: tmp_diff.path)
debug_data.expose_from(reference_path: reference_path,
tested_path: tested_path,
diff_path: tmp_diff.path,
file_type: file_type)
false
ensure
tmp_diff.close!
tmp_diff&.close!
end

failure_message do
<<~TXT
The provided image and reference image do not match (error: #{@normalized_mean_error}, tolerance: #{tolerance})
EXPECTED: #{@debug_data.exposed_reference_path}
ACTUAL: #{@debug_data.exposed_tested_path}
DIFF: #{@debug_data.exposed_diff_path}

After manually confirming that the difference is expected, run:
cp #{@debug_data.exposed_tested_path} #{reference_path}
TXT
if debug_data.exposed_reference_path
<<~TXT
The provided image and reference image do not match (error: #{@normalized_mean_error}, tolerance: #{tolerance})
EXPECTED: #{debug_data.exposed_reference_path}
ACTUAL: #{debug_data.exposed_tested_path}
DIFF: #{debug_data.exposed_diff_path}

After manually confirming that the difference is expected, run:
cp #{debug_data.exposed_tested_path} #{reference_path}

TXT
else
<<~TXT
The provided reference image does not exist.

If there is no typo and tested image is valid, reference can be created with:
cp #{debug_data.exposed_tested_path} #{reference_path}

TXT
end
end
end