screenpress 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.ruby-version +1 -0
- data/README.md +2 -1
- data/lib/screenpress.rb +1 -0
- data/lib/screenpress/compare.rb +115 -0
- data/lib/screenpress/config.rb +24 -4
- data/lib/screenpress/saver.rb +22 -1
- data/lib/screenpress/version.rb +1 -1
- data/screenpress.gemspec +1 -0
- metadata +46 -15
- checksums.yaml +0 -7
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.9.3-p194
|
data/README.md
CHANGED
@@ -67,10 +67,11 @@ end
|
|
67
67
|
* Maybe be more deliberate like Huxley and set modes (ENV variables?) for recording
|
68
68
|
* Enable mode that fails test if image changes
|
69
69
|
* Enable tools to easily compare without Github (locally)
|
70
|
-
|
70
|
+
* Is there a good way to automatically take screenshots or when example is tagged?
|
71
71
|
|
72
72
|
### Inspiration
|
73
73
|
|
74
74
|
* [Huxley](https://github.com/facebook/huxley)
|
75
75
|
* [Wraith](https://github.com/BBC-News/wraith)
|
76
|
+
* [Green Onion](https://github.com/intridea/green_onion)
|
76
77
|
* [Capybara Screenshot](https://github.com/mattheworiordan/capybara-screenshot)
|
data/lib/screenpress.rb
CHANGED
@@ -0,0 +1,115 @@
|
|
1
|
+
# based on: https://github.com/intridea/green_onion/blob/master/lib/green_onion/compare.rb
|
2
|
+
|
3
|
+
require "oily_png"
|
4
|
+
|
5
|
+
module Screenpress
|
6
|
+
class Compare
|
7
|
+
include ChunkyPNG::Color
|
8
|
+
|
9
|
+
attr_reader :orig_image, :fresh_image, :threshold
|
10
|
+
def initialize(orig_path, fresh_path, threshold)
|
11
|
+
@orig_path = orig_path
|
12
|
+
@fresh_path = fresh_path
|
13
|
+
@threshold ||= threshold
|
14
|
+
end
|
15
|
+
|
16
|
+
def same?
|
17
|
+
return !File.exists?(@fresh_path) if !File.exists?(@orig_path)
|
18
|
+
setup
|
19
|
+
|
20
|
+
return false unless diff_iterator
|
21
|
+
|
22
|
+
|
23
|
+
if percentage_diff > 0
|
24
|
+
puts "Image Percentage Different #{@orig_path}: #{percentage_diff}"
|
25
|
+
if percentage_diff > self.threshold
|
26
|
+
puts " Image different!"
|
27
|
+
return false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def setup
|
37
|
+
return if @diff_index
|
38
|
+
@orig_image = ChunkyPNG::Image.from_file(@orig_path)
|
39
|
+
@fresh_image = ChunkyPNG::Image.from_file(@fresh_path)
|
40
|
+
@diff_index = []
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
# Pulled from Jeff Kreeftmeijer's post here: http://jeffkreeftmeijer.com/2011/comparing-images-and-creating-image-diffs/
|
45
|
+
# Run through all of the pixels on both org image, and fresh image. Change the pixel color accordingly.
|
46
|
+
def update_diff_index(x, y, pixel)
|
47
|
+
lowest_score = 1
|
48
|
+
return if pixel == fresh_image[x,y]
|
49
|
+
|
50
|
+
# try a bit in each direction to account for differences
|
51
|
+
[-2, -1, 0, 1, 2].each do |yd|
|
52
|
+
[-1, 0, 1].each do |xd|
|
53
|
+
begin
|
54
|
+
# to do based on more nuanced score
|
55
|
+
#score = Math.sqrt(
|
56
|
+
# (r(fresh_image[x+xd,y+yd]) - r(pixel)) ** 2 +
|
57
|
+
# (g(fresh_image[x+xd,y+yd]) - g(pixel)) ** 2 +
|
58
|
+
# (b(fresh_image[x+xd,y+yd]) - b(pixel)) ** 2
|
59
|
+
# ) / Math.sqrt(MAX ** 2 * 3)
|
60
|
+
|
61
|
+
return if pixel == fresh_image[x+xd,y+yd]
|
62
|
+
|
63
|
+
score = 1
|
64
|
+
|
65
|
+
lowest_score = score if score < lowest_score
|
66
|
+
rescue ChunkyPNG::OutOfBounds
|
67
|
+
# off the edge!
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
@diff_index << [x,y,lowest_score] if lowest_score > 0
|
73
|
+
end
|
74
|
+
|
75
|
+
def diff_iterator
|
76
|
+
orig_image.height.times do |y|
|
77
|
+
orig_image.row(y).each_with_index do |pixel, x|
|
78
|
+
update_diff_index(x, y, pixel)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
return true
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns the numeric results of the diff of 2 images
|
86
|
+
def percentage_diff
|
87
|
+
return @percentage_changed if @percentage_changed
|
88
|
+
total_px = orig_image.pixels.length
|
89
|
+
changed_px = @diff_index.length
|
90
|
+
|
91
|
+
# to do based on more nuanced score
|
92
|
+
#changed_px = 0.0
|
93
|
+
#@diff_index.each do |x,y,score|
|
94
|
+
# could use the actual score
|
95
|
+
# changed_px += score
|
96
|
+
#end
|
97
|
+
@percentage_changed = ((changed_px.to_f*100) / total_px)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Saves the visual diff as a separate file
|
101
|
+
def save_visual_diff
|
102
|
+
x, y = @diff_index.map{ |xy| xy[0] }, @diff_index.map{ |xy| xy[1] }
|
103
|
+
diff_path = @orig_path.insert(-5, '_diff')
|
104
|
+
|
105
|
+
begin
|
106
|
+
fresh_image.rect(x.min, y.min, x.max, y.max, ChunkyPNG::Color.rgb(0,255,0))
|
107
|
+
rescue NoMethodError
|
108
|
+
puts "Both images are the same."
|
109
|
+
end
|
110
|
+
|
111
|
+
fresh_image.save(diff_path)
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
data/lib/screenpress/config.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module Screenpress
|
2
2
|
class Config
|
3
|
+
attr_accessor :enabled
|
4
|
+
|
3
5
|
def path=val
|
4
6
|
self.full_path = root.join(val)
|
5
7
|
end
|
@@ -13,13 +15,31 @@ module Screenpress
|
|
13
15
|
@full_path
|
14
16
|
end
|
15
17
|
|
16
|
-
def
|
17
|
-
|
18
|
+
def tmp_path=val
|
19
|
+
self.full_tmp_path=root.join(val)
|
20
|
+
end
|
21
|
+
|
22
|
+
def full_tmp_path=val
|
23
|
+
@full_tmp_path = Pathname.new(val).expand_path
|
24
|
+
end
|
25
|
+
|
26
|
+
def full_tmp_path
|
27
|
+
self.tmp_path = "tmp" unless @full_tmp_path
|
28
|
+
@full_tmp_path
|
18
29
|
end
|
19
30
|
|
20
31
|
def enabled?
|
21
|
-
return !!@
|
22
|
-
@
|
32
|
+
return !!@calc_enabled if defined?(@calc_enabled)
|
33
|
+
@calc_enabled = calc_enabled
|
34
|
+
end
|
35
|
+
|
36
|
+
def threshold=val
|
37
|
+
# number between 0.0 and 100.0 for percentage of image that can change
|
38
|
+
@threshold = val.to_f
|
39
|
+
end
|
40
|
+
|
41
|
+
def threshold
|
42
|
+
@threshold ||= 0.1
|
23
43
|
end
|
24
44
|
|
25
45
|
protected
|
data/lib/screenpress/saver.rb
CHANGED
@@ -17,13 +17,28 @@ module Screenpress
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def save_screenshot
|
20
|
+
tmp_file = self.tmp_filename
|
21
|
+
|
20
22
|
# settings to nil because of issues in some version of capybara
|
21
23
|
old_path = Capybara.save_and_open_page_path
|
22
24
|
Capybara.save_and_open_page_path = nil
|
23
25
|
|
24
26
|
ensure_directory
|
25
27
|
|
26
|
-
Screenpress::Saver::Proxy.save!(capybara.current_driver, page.driver,
|
28
|
+
return false unless Screenpress::Saver::Proxy.save!(capybara.current_driver, page.driver, tmp_file)
|
29
|
+
|
30
|
+
# is it different?
|
31
|
+
compare = Screenpress::Compare.new(filename, tmp_file, Screenpress.config.threshold)
|
32
|
+
if compare.same?
|
33
|
+
File.delete(tmp_file)
|
34
|
+
else
|
35
|
+
FileUtils.mv(tmp_file, filename)
|
36
|
+
end
|
37
|
+
return true
|
38
|
+
|
39
|
+
rescue Exception => e
|
40
|
+
File.delete(tmp_file) if tmp_file && File.exists?(tmp_file)
|
41
|
+
raise e
|
27
42
|
end
|
28
43
|
|
29
44
|
def ensure_directory
|
@@ -32,6 +47,12 @@ module Screenpress
|
|
32
47
|
FileUtils.mkdir_p(folder)
|
33
48
|
end
|
34
49
|
|
50
|
+
def tmp_filename
|
51
|
+
tmp_dir = Screenpress.config.full_tmp_path.to_s
|
52
|
+
tmp_file = "#{tmp_dir}/screenpress_#{File.basename(filename)}"
|
53
|
+
tmp_file
|
54
|
+
end
|
55
|
+
|
35
56
|
class Proxy
|
36
57
|
class << self
|
37
58
|
def save!(name, driver, filename)
|
data/lib/screenpress/version.rb
CHANGED
data/screenpress.gemspec
CHANGED
metadata
CHANGED
@@ -1,32 +1,52 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: screenpress
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Brian Leonard
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2013-12-
|
12
|
+
date: 2013-12-09 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: capybara
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
|
-
- - '>='
|
19
|
+
- - ! '>='
|
18
20
|
- !ruby/object:Gem::Version
|
19
21
|
version: '0'
|
20
22
|
type: :runtime
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
|
-
- - '>='
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: oily_png
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
25
44
|
- !ruby/object:Gem::Version
|
26
45
|
version: '0'
|
27
46
|
- !ruby/object:Gem::Dependency
|
28
47
|
name: bundler
|
29
48
|
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
30
50
|
requirements:
|
31
51
|
- - ~>
|
32
52
|
- !ruby/object:Gem::Version
|
@@ -34,6 +54,7 @@ dependencies:
|
|
34
54
|
type: :development
|
35
55
|
prerelease: false
|
36
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
37
58
|
requirements:
|
38
59
|
- - ~>
|
39
60
|
- !ruby/object:Gem::Version
|
@@ -41,43 +62,49 @@ dependencies:
|
|
41
62
|
- !ruby/object:Gem::Dependency
|
42
63
|
name: rake
|
43
64
|
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
44
66
|
requirements:
|
45
|
-
- - '>='
|
67
|
+
- - ! '>='
|
46
68
|
- !ruby/object:Gem::Version
|
47
69
|
version: '0'
|
48
70
|
type: :development
|
49
71
|
prerelease: false
|
50
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
51
74
|
requirements:
|
52
|
-
- - '>='
|
75
|
+
- - ! '>='
|
53
76
|
- !ruby/object:Gem::Version
|
54
77
|
version: '0'
|
55
78
|
- !ruby/object:Gem::Dependency
|
56
79
|
name: rspec
|
57
80
|
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
58
82
|
requirements:
|
59
|
-
- - '>='
|
83
|
+
- - ! '>='
|
60
84
|
- !ruby/object:Gem::Version
|
61
85
|
version: '0'
|
62
86
|
type: :development
|
63
87
|
prerelease: false
|
64
88
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
65
90
|
requirements:
|
66
|
-
- - '>='
|
91
|
+
- - ! '>='
|
67
92
|
- !ruby/object:Gem::Version
|
68
93
|
version: '0'
|
69
94
|
- !ruby/object:Gem::Dependency
|
70
95
|
name: debugger
|
71
96
|
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
72
98
|
requirements:
|
73
|
-
- - '>='
|
99
|
+
- - ! '>='
|
74
100
|
- !ruby/object:Gem::Version
|
75
101
|
version: '0'
|
76
102
|
type: :development
|
77
103
|
prerelease: false
|
78
104
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
79
106
|
requirements:
|
80
|
-
- - '>='
|
107
|
+
- - ! '>='
|
81
108
|
- !ruby/object:Gem::Version
|
82
109
|
version: '0'
|
83
110
|
description: Workflow and Capybara extension that takes screenshots of your tests
|
@@ -90,11 +117,13 @@ extra_rdoc_files: []
|
|
90
117
|
files:
|
91
118
|
- .gitignore
|
92
119
|
- .rspec
|
120
|
+
- .ruby-version
|
93
121
|
- Gemfile
|
94
122
|
- LICENSE.txt
|
95
123
|
- README.md
|
96
124
|
- Rakefile
|
97
125
|
- lib/screenpress.rb
|
126
|
+
- lib/screenpress/compare.rb
|
98
127
|
- lib/screenpress/config.rb
|
99
128
|
- lib/screenpress/dsl.rb
|
100
129
|
- lib/screenpress/saver.rb
|
@@ -107,29 +136,31 @@ files:
|
|
107
136
|
homepage: https://github.com/taskrabbit/screenpress
|
108
137
|
licenses:
|
109
138
|
- MIT
|
110
|
-
metadata: {}
|
111
139
|
post_install_message:
|
112
140
|
rdoc_options: []
|
113
141
|
require_paths:
|
114
142
|
- lib
|
115
143
|
required_ruby_version: !ruby/object:Gem::Requirement
|
144
|
+
none: false
|
116
145
|
requirements:
|
117
|
-
- - '>='
|
146
|
+
- - ! '>='
|
118
147
|
- !ruby/object:Gem::Version
|
119
148
|
version: '0'
|
120
149
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
150
|
+
none: false
|
121
151
|
requirements:
|
122
|
-
- - '>='
|
152
|
+
- - ! '>='
|
123
153
|
- !ruby/object:Gem::Version
|
124
154
|
version: '0'
|
125
155
|
requirements: []
|
126
156
|
rubyforge_project:
|
127
|
-
rubygems_version:
|
157
|
+
rubygems_version: 1.8.23
|
128
158
|
signing_key:
|
129
|
-
specification_version:
|
159
|
+
specification_version: 3
|
130
160
|
summary: Prevent visual regressions
|
131
161
|
test_files:
|
132
162
|
- spec/config_spec.rb
|
133
163
|
- spec/dsl_spec.rb
|
134
164
|
- spec/saver_spec.rb
|
135
165
|
- spec/spec_helper.rb
|
166
|
+
has_rdoc:
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 0e788d87ac38505a9a4a0a18c763ed7b90090510
|
4
|
-
data.tar.gz: 700ac9fd342eb0a9f471813840eaf65b6b5c87a0
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: cafa83682004a4c115dbaa6417d5628cb7c69396a154f68bb6af49e4e584cba612d54560393bbec33e00f301e4bc769da1c978ab7a1a398a1618e4f9b74bda33
|
7
|
-
data.tar.gz: 1bfeca9e8bcdc5b4b72f3144fc3c98bc59ae6edad94874795ffbca383643783ff8dd4df240255b949cfa0233db33808baf518b337ddaf19151246d53dff67bb3
|