capybara-screenshot-diff 0.1.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3c7078265d4d0fc01429989f9b8d67a60773ccab
4
- data.tar.gz: 0bee455268a6e5ecf65549a22ff35c85c5b56327
3
+ metadata.gz: d8c517212dfc9af8af735a354862dcaba9adc96a
4
+ data.tar.gz: 7828ae0bfa1c9aea2e8814288989288c43c8f64e
5
5
  SHA512:
6
- metadata.gz: 9003b9fb66fa3e2206ee771d288963d26a85a2bb26b0d643dc357b5647e5b5915083b44e547daf6e2cafa4aba5791853b9496c8dce3a79372214da1a50a13343
7
- data.tar.gz: 8fcfca1b48a99fa3b14b8b1270d48af12ecd1dc9f30ffc002c0fdaaff79fdfb728cb3e6516fb2724aec7ca921ede6dc00a9165607c2d4f7e024776f446423aec
6
+ metadata.gz: 27179f167cc8d6b77850033dd0e5291ae89e7dd4182586e22269a66619fca6e02d891e257c6c7041e51adb13a4b7097e8017e7c6e543ef7f11a6cf02fefef2e9
7
+ data.tar.gz: be58b147f1948e3136975f1320caa8cbfeeca7d5e5f27651bd8736fe31da35384d950165e8b560c0fdc4b2fe1975e382511ac565cc9f8314a2145982c11d3de0
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ *~
1
2
  /.bundle/
2
3
  /.yardoc
3
4
  /Gemfile.lock
@@ -1,8 +1,28 @@
1
1
  inherit_from: .rubocop_todo.yml
2
2
 
3
+ AllCops:
4
+ DisplayCopNames: true
5
+ DisplayStyleGuide: true
6
+
7
+ Lint/Debugger:
8
+ Enabled: false
9
+
10
+ Metrics/ClassLength:
11
+ Max: 101
12
+
13
+ Metrics/LineLength:
14
+ Max: 110
15
+
3
16
  Style/MultilineMethodCallIndentation:
4
17
  EnforcedStyle: indented
5
18
  IndentationWidth: 4
6
19
 
20
+ Style/NumericPredicate:
21
+ Enabled: false
22
+
7
23
  Style/SignalException:
8
24
  EnforcedStyle: semantic
25
+
26
+ Style/AlignParameters:
27
+ EnforcedStyle: with_fixed_indentation
28
+ IndentationWidth: 4
@@ -0,0 +1,79 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2016-04-22 14:35:36 +0200 using RuboCop version 0.39.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ Style/TrivialAccessors:
10
+ Enabled: false
11
+
12
+ # Offense count: 2
13
+ Lint/AmbiguousRegexpLiteral:
14
+ Exclude:
15
+ - 'lib/capybara/screenshot/diff/capybara_setup.rb'
16
+
17
+ # Offense count: 3
18
+ Metrics/AbcSize:
19
+ Max: 55
20
+
21
+ # Offense count: 1
22
+ Metrics/CyclomaticComplexity:
23
+ Max: 15
24
+
25
+ # Offense count: 3
26
+ # Configuration parameters: CountComments.
27
+ Metrics/MethodLength:
28
+ Max: 42
29
+
30
+ # Offense count: 1
31
+ # Configuration parameters: CountKeywordArgs.
32
+ Metrics/ParameterLists:
33
+ Max: 6
34
+
35
+ # Offense count: 1
36
+ Metrics/PerceivedComplexity:
37
+ Max: 17
38
+
39
+ # Offense count: 1
40
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
41
+ # SupportedStyles: nested, compact
42
+ Style/ClassAndModuleChildren:
43
+ Exclude:
44
+ - 'lib/capybara/screenshot/diff/capybara_setup.rb'
45
+
46
+ # Offense count: 2
47
+ Style/Documentation:
48
+ Exclude:
49
+ - 'spec/**/*'
50
+ - 'test/**/*'
51
+ - 'lib/capybara/screenshot/diff.rb'
52
+ - 'lib/capybara/screenshot/diff/image_compare.rb'
53
+
54
+ # Offense count: 1
55
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
56
+ # SupportedStyles: format, sprintf, percent
57
+ Style/FormatString:
58
+ Exclude:
59
+ - 'lib/capybara/screenshot/diff/capybara_setup.rb'
60
+
61
+ # Offense count: 1
62
+ # Configuration parameters: MinBodyLength.
63
+ Style/GuardClause:
64
+ Exclude:
65
+ - 'capybara-screenshot-diff.gemspec'
66
+
67
+ # Offense count: 1
68
+ # Cop supports --auto-correct.
69
+ # Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
70
+ # SupportedStyles: aligned, indented
71
+ Style/MultilineMethodCallIndentation:
72
+ Enabled: false
73
+
74
+ # Offense count: 1
75
+ # Cop supports --auto-correct.
76
+ # Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
77
+ # SupportedStyles: aligned, indented
78
+ Style/MultilineOperationIndentation:
79
+ Enabled: false
@@ -1,10 +1,16 @@
1
1
  language: ruby
2
2
  rvm:
3
- - jruby-9.0.4.0
4
- - jruby-9.0.5.0
5
3
  - jruby-head
4
+ - jruby-9.1.2.0
5
+ - jruby-9.1.5.0
6
+ - 2.3.1
7
+ - 2.2.5
6
8
  - 2.1.8
7
- - 2.2.4
8
- - 2.3.0
9
9
  - ruby-head
10
- before_install: gem install bundler -v 1.11.2
10
+ before_install: gem query -i -n ^bundler$ >/dev/null || gem install bundler
11
+
12
+ env:
13
+ - JRUBY_OPTS="--dev --debug"
14
+
15
+ jdk:
16
+ - oraclejdk8
data/README.md CHANGED
@@ -1,11 +1,13 @@
1
+ [![Build Status](https://travis-ci.org/donv/capybara-screenshot-diff.svg?branch=master)](https://travis-ci.org/donv/capybara-screenshot-diff)
2
+
1
3
  # Capybara::Screenshot::Diff
2
4
 
3
5
  Ever wondered what your project looked like two years ago? To answer that, you
4
6
  start taking screen shots during your tests. Capybara provides the
5
7
  `save_screenshot` method for this. Very good.
6
8
 
7
- Ever introduced a graphical chnage unintended? Never want it to happen again?
8
- Then this gem is gfor you! Use this gem to detect changes in your pages by
9
+ Ever introduced a graphical change unintended? Never want it to happen again?
10
+ Then this gem is for you! Use this gem to detect changes in your pages by
9
11
  taking screen shots and comparing them to the previous revision.
10
12
 
11
13
  ## Installation
@@ -84,6 +86,44 @@ doc
84
86
  02-action_performed
85
87
  ```
86
88
 
89
+ **All files in the screenshot group directory will be deleted when
90
+ `screenshot_group` is called.**
91
+
92
+
93
+ #### Screenshot sections
94
+
95
+ You can introduce another level above the screenshot group called a
96
+ `screenshot_section`. The section name is inserted just before the group name
97
+ in the save path. If called in the setup of the test, all screenshots in
98
+ that test will get the same prefix:
99
+
100
+ ```ruby
101
+ setup do
102
+ screenshot_section 'my_feature'
103
+ end
104
+ test 'my subfeature' do
105
+ screenshot_group 'subfeature'
106
+ visit '/feature'
107
+ click_button 'Interresting button'
108
+ screenshot 'subfeature_index'
109
+ click_button 'Perform action'
110
+ screenshot 'action_performed'
111
+ end
112
+ ```
113
+
114
+ This will produce a sequence of images like this
115
+
116
+ ```
117
+ doc
118
+ screenshots
119
+ my_feature
120
+ subfeature
121
+ 00-subfeature_index
122
+ 01-action_performed
123
+ ```
124
+
125
+
126
+
87
127
  ### Multiple Capybara drivers
88
128
 
89
129
  Often it is useful to test your app using different browsers. To avoid the
@@ -189,12 +229,25 @@ If you would like the screen shots to be saved in a different location set
189
229
  Capybara::Screenshot.save_path = "#{Rails.root}/doc/gui"
190
230
  ```
191
231
 
232
+ ### Screen shot stability
233
+
234
+ To ensure that animations are finished before saving a screen shot, you can add
235
+ a stability time limit. If the stability time limit is set, a second screen
236
+ shot will be taken and compared to the first. This is repeated until two
237
+ subsequent screen shots are identical.
238
+
239
+ ```ruby
240
+ Capybara::Screenshot.stability_time_limit = 0.5
241
+ ```
242
+
192
243
 
193
244
  ## Development
194
245
 
195
246
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
196
247
 
197
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
248
+ To install this gem onto your local machine, run `bundle exec rake install`.
249
+
250
+ To release a new version, update the version number in `lib/capybara/screenshot/diff/version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
198
251
 
199
252
  ## Contributing
200
253
 
data/Rakefile CHANGED
@@ -12,4 +12,4 @@ end
12
12
 
13
13
  RuboCop::RakeTask.new
14
14
 
15
- Rake::Task[:test].enhance [:rubocop]
15
+ Rake::Task[:test].enhance [:'rubocop:auto_correct']
@@ -8,31 +8,24 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Capybara::Screenshot::Diff::VERSION
9
9
  spec.authors = ['Uwe Kubosch']
10
10
  spec.email = ['uwe@kubosch.no']
11
-
12
11
  spec.summary = 'Track your GUI changes with diff assertions'
13
12
  spec.description = 'Save screen shots and track changes with graphical diff'
14
13
  spec.homepage = 'https://github.com/donv/capybara-screenshot-diff'
15
14
  spec.license = 'MIT'
16
-
17
- # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
18
- # delete this section to allow pushing this gem to any host.
19
- if spec.respond_to?(:metadata)
20
- spec.metadata['allowed_push_host'] = 'https://rubygems.org/'
21
- else
22
- fail 'RubyGems 2.0 or newer is required to protect against public gem push.'
23
- end
24
-
25
- spec.files = `git ls-files -z`.split("\x0")
26
- .reject { |f| f.match(%r{^(test|spec|features)/}) }
15
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org/'
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
27
17
  spec.bindir = 'exe'
28
18
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
29
19
  spec.require_paths = ['lib']
30
20
 
21
+ spec.add_runtime_dependency 'actionpack', '~> 4.1'
31
22
  spec.add_runtime_dependency 'capybara', '~> 2.0'
23
+ spec.add_runtime_dependency 'chunky_png', '~> 1.3'
32
24
 
33
25
  spec.add_development_dependency 'bundler', '~> 1.11'
34
- spec.add_development_dependency 'rake', '~> 10.0'
35
26
  spec.add_development_dependency 'minitest', '~> 5.0'
36
27
  spec.add_development_dependency 'minitest-reporters'
28
+ spec.add_development_dependency 'rake', '~> 10.0'
37
29
  spec.add_development_dependency 'rubocop', '~> 0.39'
30
+ spec.add_development_dependency 'simplecov', '~> 0.11'
38
31
  end
@@ -4,10 +4,16 @@ require 'capybara/screenshot/diff/capybara_setup'
4
4
 
5
5
  module Capybara
6
6
  module Screenshot
7
- mattr_accessor :enabled
8
- mattr_accessor :window_size
9
7
  mattr_accessor :add_driver_path
10
8
  mattr_accessor :add_os_path
9
+ mattr_accessor :enabled
10
+ mattr_accessor :screenshot_root
11
+ mattr_accessor :stability_time_limit
12
+ mattr_accessor :window_size
13
+
14
+ def self.active?
15
+ enabled || (enabled.nil? && Diff.enabled)
16
+ end
11
17
 
12
18
  # Module to track screen shot changes
13
19
  module Diff
@@ -1,7 +1,12 @@
1
1
  require 'capybara'
2
2
  require 'capybara/screenshot/diff/image_compare'
3
+ require 'action_controller'
4
+ require 'action_dispatch'
3
5
 
4
- # Add the `screenshot`method to ActionDispatch::IntegrationTest
6
+ # TODO(uwe): Move this code to module Capybara::Screenshot::Diff::TestMethods,
7
+ # and use Module#prepend/include to insert.
8
+ # Add the `screenshot` method to ActionDispatch::IntegrationTest
9
+ # rubocop:disable Metrics/ClassLength
5
10
  class ActionDispatch::IntegrationTest
6
11
  ON_WINDOWS = RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
7
12
  SILENCE_ERRORS = ON_WINDOWS ? '2>nul' : '2>/dev/null'
@@ -19,22 +24,51 @@ class ActionDispatch::IntegrationTest
19
24
  end
20
25
  end
21
26
 
22
- def self.screenshot_dir
27
+ def self.screenshot_root
28
+ Capybara::Screenshot.screenshot_root ||
29
+ (defined?(Rails.root) && Rails.root) || File.expand_path('.')
30
+ end
31
+
32
+ def self.screenshot_area
23
33
  parts = ['doc/screenshots']
24
34
  parts << Capybara.default_driver.to_s if Capybara::Screenshot.add_driver_path
25
35
  parts << os_name if Capybara::Screenshot.add_os_path
26
36
  File.join parts
27
37
  end
28
38
 
29
- def self.screenshot_dir_abs
30
- "#{Rails.root}/#{screenshot_dir}".freeze
39
+ def self.screenshot_area_abs
40
+ "#{screenshot_root}/#{screenshot_area}".freeze
41
+ end
42
+
43
+ def initialize(*)
44
+ super
45
+ @screenshot_counter = nil
46
+ @screenshot_group = nil
47
+ @screenshot_section = nil
48
+ @test_screenshot_errors = nil
49
+ @test_screenshots = nil
50
+ end
51
+
52
+ def group_parts
53
+ parts = []
54
+ parts << @screenshot_section if @screenshot_section.present?
55
+ parts << @screenshot_group if @screenshot_group.present?
56
+ parts
57
+ end
58
+
59
+ def full_name(name)
60
+ File.join group_parts.<<(name).map(&:to_s)
61
+ end
62
+
63
+ def screenshot_dir
64
+ File.join [self.class.screenshot_area] + group_parts
31
65
  end
32
66
 
33
67
  setup do
34
68
  if Capybara::Screenshot.window_size
35
69
  if Capybara.default_driver == :selenium
36
70
  page.driver.browser.manage.window.resize_to(*Capybara::Screenshot.window_size)
37
- else
71
+ elsif Capybara.default_driver == :poltergeist
38
72
  page.driver.resize(*Capybara::Screenshot.window_size)
39
73
  end
40
74
  end
@@ -47,14 +81,19 @@ class ActionDispatch::IntegrationTest
47
81
  fail(@test_screenshot_errors.join("\n\n")) if @test_screenshot_errors
48
82
  end
49
83
 
84
+ def screenshot_section(name)
85
+ @screenshot_section = name.to_s
86
+ end
87
+
50
88
  def screenshot_group(name)
51
- @screenshot_group = name
89
+ @screenshot_group = name.to_s
52
90
  @screenshot_counter = 0
53
- FileUtils.rm_rf "#{self.class.screenshot_dir_abs}/#{name}" if name.present?
91
+ return unless Capybara::Screenshot.active? && name.present?
92
+ FileUtils.rm_rf screenshot_dir
54
93
  end
55
94
 
56
95
  def screenshot(name)
57
- return unless Capybara::Screenshot.enabled || (Capybara::Screenshot.enabled.nil? && Capybara::Screenshot::Diff.enabled)
96
+ return unless Capybara::Screenshot.active?
58
97
  if Capybara.default_driver == :selenium && Capybara::Screenshot.window_size
59
98
  return unless page.driver.browser.manage.window
60
99
  .size == Selenium::WebDriver::Dimension.new(*Capybara::Screenshot.window_size)
@@ -63,46 +102,79 @@ class ActionDispatch::IntegrationTest
63
102
  name = "#{'%02i' % @screenshot_counter}_#{name}"
64
103
  @screenshot_counter += 1
65
104
  end
66
- name = "#{@screenshot_group}/#{name}" if @screenshot_group.present?
67
- file_name = "#{self.class.screenshot_dir_abs}/#{name}.png"
68
- org_name = "#{self.class.screenshot_dir_abs}/#{name}_0.png~"
69
- new_name = "#{self.class.screenshot_dir_abs}/#{name}_1.png~"
105
+ name = full_name(name)
106
+ file_name = "#{self.class.screenshot_area_abs}/#{name}.png"
107
+ org_name = "#{self.class.screenshot_area_abs}/#{name}_0.png~"
108
+ new_name = "#{self.class.screenshot_area_abs}/#{name}_1.png~"
70
109
 
71
110
  FileUtils.mkdir_p File.dirname(file_name)
72
- svn_file_name = "#{self.class.screenshot_dir_abs}/.svn/text-base/#{name}.png.svn-base"
111
+ svn_file_name = "#{self.class.screenshot_area_abs}/.svn/text-base/#{name}.png.svn-base"
73
112
  if File.exist?(svn_file_name)
74
113
  committed_file_name = svn_file_name
75
114
  else
76
115
  svn_info = `svn info #{file_name} #{SILENCE_ERRORS}`
77
116
  if svn_info.present?
78
- wc_root = svn_info.slice /(?<=Working Copy Root Path: ).*$/
79
- checksum = svn_info.slice /(?<=Checksum: ).*$/
117
+ wc_root = svn_info.slice(/(?<=Working Copy Root Path: ).*$/)
118
+ checksum = svn_info.slice(/(?<=Checksum: ).*$/)
80
119
  if checksum
81
120
  committed_file_name = "#{wc_root}/.svn/pristine/#{checksum[0..1]}/#{checksum}.svn-base"
82
121
  end
83
122
  else
84
123
  committed_file_name = org_name
85
- `git show HEAD~0:#{self.class.screenshot_dir}/#{name}.png > #{committed_file_name} #{SILENCE_ERRORS}`
124
+ `git show HEAD~0:#{self.class.screenshot_area}/#{name}.png > #{committed_file_name} #{SILENCE_ERRORS}`
86
125
  if File.size(committed_file_name) == 0
87
126
  FileUtils.rm_f committed_file_name
88
127
  end
89
128
  end
90
129
  end
130
+ take_stable_screenshot(file_name)
131
+ return unless committed_file_name && File.exist?(committed_file_name)
132
+ (@test_screenshots ||= []) << [caller[0], name, file_name, committed_file_name, new_name, org_name]
133
+ end
134
+
135
+ IMAGE_WAIT_SCRIPT = <<EOF.freeze
136
+ function pending_image() {
137
+ var images = document.images;
138
+ for (var i = 0; i < images.length; i++) {
139
+ if (!images[i].complete) {
140
+ return images[i].src;
141
+ }
142
+ }
143
+ return false;
144
+ }()
145
+ EOF
146
+
147
+ def assert_images_loaded(timeout: Capybara.default_max_wait_time)
148
+ return unless respond_to? :evaluate_script
149
+ start = Time.now
150
+ loop do
151
+ pending_image = evaluate_script IMAGE_WAIT_SCRIPT
152
+ break unless pending_image
153
+ assert (Time.now - start) < timeout,
154
+ "Image not loaded after #{timeout}s: #{pending_image.inspect}"
155
+ sleep 0.1
156
+ end
157
+ end
158
+
159
+ def take_stable_screenshot(file_name)
160
+ assert_images_loaded
91
161
  old_file_size = nil
92
162
  loop do
93
- page.save_screenshot(file_name)
94
- break if old_file_size == File.size(file_name)
95
- old_file_size = File.size(file_name)
96
- sleep 0.5
163
+ save_screenshot(file_name)
164
+ break unless Capybara::Screenshot.stability_time_limit
165
+ new_file_size = File.size(file_name)
166
+ break if new_file_size == old_file_size
167
+ old_file_size = new_file_size
168
+ sleep Capybara::Screenshot.stability_time_limit
97
169
  end
98
- return unless File.exist?(committed_file_name)
99
- (@test_screenshots ||= []) << [caller[0], name, file_name, committed_file_name, new_name, org_name]
100
170
  end
101
171
 
102
172
  def assert_image_not_changed(caller, name, file_name, committed_file_name, new_name, org_name)
103
- if Capybara::Screenshot::Diff::ImageCompare.compare(file_name, committed_file_name, Capybara::Screenshot.window_size)
173
+ if Capybara::Screenshot::Diff::ImageCompare.compare(committed_file_name, file_name,
174
+ Capybara::Screenshot.window_size)
104
175
  (@test_screenshot_errors ||= []) <<
105
- "Screenshot does not match for #{name.inspect}\n#{file_name}\n#{org_name}\n#{new_name}\nat #{caller}"
176
+ "Screenshot does not match for '#{name}'\n#{file_name}\n#{org_name}\n#{new_name}\nat #{caller}"
106
177
  end
107
178
  end
108
179
  end
180
+ # rubocop:enable Metrics/ClassLength
@@ -6,21 +6,31 @@ module Capybara
6
6
  class ImageCompare
7
7
  include ChunkyPNG::Color
8
8
 
9
- def self.compare(file_name, old_file_name, dimensions = nil)
10
- name = file_name.chomp('.png')
9
+ def self.compare(*args)
10
+ new(*args).compare
11
+ end
12
+
13
+ def initialize(old_file_name, new_file_name, dimensions = nil)
14
+ @old_file_name = old_file_name
15
+ @file_name = new_file_name
16
+ @dimensions = dimensions
17
+ end
18
+
19
+ def compare
20
+ name = @file_name.chomp('.png')
11
21
  org_file_name = "#{name}_0.png~"
12
22
  new_file_name = "#{name}_1.png~"
13
23
 
14
- return nil unless File.exist? old_file_name
24
+ return nil unless File.exist? @old_file_name
15
25
 
16
- images = load_images(old_file_name, file_name)
26
+ images = load_images(@old_file_name, @file_name)
17
27
 
18
28
  unless images
19
29
  clean_tmp_files(new_file_name, org_file_name)
20
30
  return false
21
31
  end
22
32
 
23
- crop_images(images, dimensions) if dimensions
33
+ crop_images(images, @dimensions) if @dimensions
24
34
  org_img = images.first
25
35
  new_img = images.last
26
36
  if sizes_changed?(org_img, new_img, name)
@@ -33,41 +43,45 @@ module Capybara
33
43
  return false
34
44
  end
35
45
 
36
- bottom, left, right, top = find_diff_rectangle(org_img, new_img)
37
- draw_rectangles(images, bottom, left, right, top)
46
+ @left, @top, @right, @bottom = find_diff_rectangle(org_img, new_img)
47
+ draw_rectangles(images, @bottom, @left, @right, @top)
38
48
  save_images(new_file_name, new_img, org_file_name, org_img)
39
49
  true
40
50
  end
41
51
 
42
- def self.save_images(new_file_name, new_img, org_file_name, org_img)
52
+ def dimensions
53
+ [@left, @top, @right, @bottom]
54
+ end
55
+
56
+ private
57
+
58
+ def save_images(new_file_name, new_img, org_file_name, org_img)
43
59
  org_img.save(org_file_name)
44
60
  new_img.save(new_file_name)
45
61
  end
46
62
 
47
- def self.clean_tmp_files(new_file_name, org_file_name)
48
- File.delete(org_file_name) if File.exists?(org_file_name)
49
- File.delete(new_file_name) if File.exists?(new_file_name)
63
+ def clean_tmp_files(new_file_name, org_file_name)
64
+ File.delete(org_file_name) if File.exist?(org_file_name)
65
+ File.delete(new_file_name) if File.exist?(new_file_name)
50
66
  end
51
67
 
52
- private
53
-
54
- def self.load_images(old_file_name, file_name)
55
- old_file = File.read(old_file_name)
56
- new_file = File.read(file_name)
68
+ def load_images(old_file_name, file_name)
69
+ old_file = File.binread(old_file_name)
70
+ new_file = File.binread(file_name)
57
71
 
58
72
  return false if old_file == new_file
59
73
 
60
74
  [ChunkyPNG::Image.from_blob(old_file), ChunkyPNG::Image.from_blob(new_file)]
61
75
  end
62
76
 
63
- def self.sizes_changed?(org_image, new_image, name)
64
- if org_image.dimension != new_image.dimension
65
- puts "Image size has changed for #{name}: #{[org_image, new_image].map { |i| "#{i.width}x#{i.height}" }.join(' => ')}"
66
- return true
67
- end
77
+ def sizes_changed?(org_image, new_image, name)
78
+ return unless org_image.dimension != new_image.dimension
79
+ change_msg = [org_image, new_image].map { |i| "#{i.width}x#{i.height}" }.join(' => ')
80
+ puts "Image size has changed for #{name}: #{change_msg}"
81
+ true
68
82
  end
69
83
 
70
- def self.crop_images(images, dimensions)
84
+ def crop_images(images, dimensions)
71
85
  images.map! do |i|
72
86
  if i.dimension.to_a == dimensions || i.width < dimensions[0] || i.height < dimensions[1]
73
87
  i
@@ -77,26 +91,24 @@ module Capybara
77
91
  end
78
92
  end
79
93
 
80
- def self.draw_rectangles(images, bottom, left, right, top)
81
- (1..2).each do |i|
82
- images.each do |image|
83
- image.rect(left - 1, top - 1, right + 1, bottom + 1, ChunkyPNG::Color.rgb(255, 0, 0))
84
- end
94
+ def draw_rectangles(images, bottom, left, right, top)
95
+ images.each do |image|
96
+ image.rect(left - 1, top - 1, right + 1, bottom + 1, ChunkyPNG::Color.rgb(255, 0, 0))
85
97
  end
86
98
  end
87
99
 
88
- def self.find_diff_rectangle(org_img, new_img)
100
+ def find_diff_rectangle(org_img, new_img)
89
101
  top = bottom = nil
90
102
  left = org_img.width
91
103
  right = -1
92
104
  org_img.height.times do |y|
93
105
  (0...left).find do |x|
94
- if org_img[x, y] != new_img[x, y]
95
- top ||= y
96
- bottom = y
97
- left = x
98
- right = x if x > right
99
- end
106
+ next if org_img[x, y] == new_img[x, y]
107
+ top ||= y
108
+ bottom = y
109
+ left = x
110
+ right = x if x > right
111
+ x
100
112
  end
101
113
  (org_img.width - 1).step(right + 1, -1).find do |x|
102
114
  if org_img[x, y] != new_img[x, y]
@@ -107,12 +119,10 @@ module Capybara
107
119
  end
108
120
  (org_img.height - 1).step(bottom + 1, -1).find do |y|
109
121
  ((left + 1)..(right - 1)).find do |x|
110
- if org_img[x, y] != new_img[x, y]
111
- bottom = y
112
- end
122
+ bottom = y if org_img[x, y] != new_img[x, y]
113
123
  end
114
124
  end
115
- return bottom, left, right, top
125
+ [left, top, right, bottom]
116
126
  end
117
127
  end
118
128
  end
@@ -2,7 +2,7 @@
2
2
  module Capybara
3
3
  module Screenshot
4
4
  module Diff
5
- VERSION = '0.1.0'.freeze
5
+ VERSION = '0.2.1'.freeze
6
6
  end
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capybara-screenshot-diff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Uwe Kubosch
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-04-20 00:00:00.000000000 Z
11
+ date: 2016-12-20 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: actionpack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.1'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: capybara
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -25,33 +39,33 @@ dependencies:
25
39
  - !ruby/object:Gem::Version
26
40
  version: '2.0'
27
41
  - !ruby/object:Gem::Dependency
28
- name: bundler
42
+ name: chunky_png
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '1.11'
34
- type: :development
47
+ version: '1.3'
48
+ type: :runtime
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '1.11'
54
+ version: '1.3'
41
55
  - !ruby/object:Gem::Dependency
42
- name: rake
56
+ name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: '10.0'
61
+ version: '1.11'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '10.0'
68
+ version: '1.11'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: minitest
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +94,20 @@ dependencies:
80
94
  - - ">="
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '10.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '10.0'
83
111
  - !ruby/object:Gem::Dependency
84
112
  name: rubocop
85
113
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +122,20 @@ dependencies:
94
122
  - - "~>"
95
123
  - !ruby/object:Gem::Version
96
124
  version: '0.39'
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.11'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.11'
97
139
  description: Save screen shots and track changes with graphical diff
98
140
  email:
99
141
  - uwe@kubosch.no