green_onion 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +17 -3
- data/lib/green_onion/cli.rb +4 -4
- data/lib/green_onion/compare.rb +16 -16
- data/lib/green_onion/errors.rb +10 -0
- data/lib/green_onion/generators/skinner.erb +1 -1
- data/lib/green_onion/screenshot.rb +10 -1
- data/lib/green_onion/version.rb +1 -1
- data/lib/green_onion.rb +16 -16
- data/spec/unit/cli_spec.rb +13 -9
- data/spec/unit/green_onion_spec.rb +24 -6
- data/spec/unit/screenshot_spec.rb +0 -4
- metadata +3 -2
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
[<img src="https://secure.travis-ci.org/tomeara/green_onion.png" />](http://travis-ci.org/#!/tomeara/green_onion)
|
2
|
+
[<img src="https://secure.travis-ci.org/tomeara/green_onion.png" />](http://travis-ci.org/#!/tomeara/green_onion) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/tomeara/green_onion)
|
3
3
|
|
4
4
|
# GreenOnion
|
5
5
|
|
@@ -7,6 +7,10 @@ Regression issues in the view make you cry.
|
|
7
7
|
|
8
8
|
GreenOnion is a testing library for the UI only. It alerts you when the appearance of a view has changed, let's you know the percentage of total change, and allows you to visualize the areas that have been changed. It fits right into your test suite, and is dependent on familiar tools like Capybara.
|
9
9
|
|
10
|
+
## Documentation
|
11
|
+
|
12
|
+
[RDoc](http://rdoc.info/gems/green_onion/frames)
|
13
|
+
|
10
14
|
## Installation
|
11
15
|
|
12
16
|
You'll need to get Qt built in your testing environment. [Follow these steps](https://github.com/thoughtbot/capybara-webkit/wiki/Installing-Qt-and-compiling-capybara-webkit) to get it up and running.
|
@@ -45,7 +49,7 @@ Options
|
|
45
49
|
|
46
50
|
To generate a "skinner" file, which will test a Rails application with the routes without params included (this is an area that could be worked on a lot more :) ); use the command below:
|
47
51
|
|
48
|
-
|
52
|
+
green_onion generate [options]
|
49
53
|
|
50
54
|
* `--url=URL` - the domain that you will be testing your Rails app. The default is "http://localhost:3000".
|
51
55
|
* `--dir=DIR` - the directory in which you would like to generate the skinner. The default is "spec/skinner.rb"
|
@@ -101,6 +105,7 @@ The best way to run the specs is with...
|
|
101
105
|
* Screenshots can either be viewed as a visual diff, or overlayed newest over oldest and viewed as an onion-skin with sliding transparency.
|
102
106
|
* Allow for flexibility in picking browsers
|
103
107
|
* Skinner generator needs love <3
|
108
|
+
** Should allow for testing using fixtures/factories
|
104
109
|
* More robust tests, especially around the visual diffs themselves
|
105
110
|
* More documentation
|
106
111
|
* More configuration/customizable settings
|
@@ -116,4 +121,13 @@ This is the post that got the wheels in motion: http://jeffkreeftmeijer.com/2011
|
|
116
121
|
Carol Nichols saw the same post, and worked on an excellent gem for cross-browser testing. That gem greatly influenced design decisions with GreenOnion.
|
117
122
|
|
118
123
|
### Capybara, ChunkyPNG, Thor, and OilyPNG
|
119
|
-
The land on which we sow our bulbs.
|
124
|
+
The land on which we sow our bulbs.
|
125
|
+
|
126
|
+
## Contributor
|
127
|
+
[Ted O'Meara](http://www.intridea.com/about/team/ted-o-meara)
|
128
|
+
|
129
|
+
## License
|
130
|
+
MIT License. See LICENSE for details.
|
131
|
+
|
132
|
+
## Copyright
|
133
|
+
Copyright (c) 2012 Intridea, Inc.
|
data/lib/green_onion/cli.rb
CHANGED
@@ -5,7 +5,7 @@ module GreenOnion
|
|
5
5
|
class CLI < Thor
|
6
6
|
include Thor::Actions
|
7
7
|
|
8
|
-
|
8
|
+
source_root File.expand_path('../generators', __FILE__)
|
9
9
|
|
10
10
|
class_option :dir, :aliases => "-d", :type => :string
|
11
11
|
|
@@ -30,12 +30,12 @@ module GreenOnion
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
desc "generate", "Generates a 'skinner' file to test
|
33
|
+
desc "generate", "Generates a 'skinner' file to test only Rails routes without params"
|
34
34
|
method_option :url, :aliases => "-u", :type => :string
|
35
35
|
def generate_skinner
|
36
36
|
options[:dir] ? dir = options[:dir] : dir = "spec"
|
37
|
-
options[:url] ?
|
38
|
-
template('skinner.erb', "#{dir}/skinner.rb")
|
37
|
+
options[:url] ? config = { :url => options[:url] } : config = { :url => "http://localhost:3000" }
|
38
|
+
template('skinner.erb', "#{dir}/skinner.rb", config)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
data/lib/green_onion/compare.rb
CHANGED
@@ -19,7 +19,7 @@ module GreenOnion
|
|
19
19
|
begin
|
20
20
|
diff_iterator
|
21
21
|
rescue ChunkyPNG::OutOfBounds
|
22
|
-
|
22
|
+
warn "Skins are different sizes. Please delete #{org} and/or #{fresh}.".color(:yellow)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -28,16 +28,24 @@ module GreenOnion
|
|
28
28
|
@images.first.row(y).each_with_index do |pixel, x|
|
29
29
|
unless pixel == @images.last[x,y]
|
30
30
|
@diff_index << [x,y]
|
31
|
-
|
32
|
-
ChunkyPNG::Color.r(pixel) + ChunkyPNG::Color.r(@images.last[x,y]) - 2 * [ChunkyPNG::Color.r(pixel), ChunkyPNG::Color.r(@images.last[x,y])].min,
|
33
|
-
ChunkyPNG::Color.g(pixel) + ChunkyPNG::Color.g(@images.last[x,y]) - 2 * [ChunkyPNG::Color.g(pixel), ChunkyPNG::Color.g(@images.last[x,y])].min,
|
34
|
-
ChunkyPNG::Color.b(pixel) + ChunkyPNG::Color.b(@images.last[x,y]) - 2 * [ChunkyPNG::Color.b(pixel), ChunkyPNG::Color.b(@images.last[x,y])].min
|
35
|
-
)
|
31
|
+
pixel_difference_filter(pixel, x, y)
|
36
32
|
end
|
37
33
|
end
|
38
34
|
end
|
39
35
|
end
|
40
36
|
|
37
|
+
def pixel_difference_filter(pixel, x, y)
|
38
|
+
chans = []
|
39
|
+
[:r, :b, :g].each do |chan|
|
40
|
+
chans << channel_difference(chan, pixel, x, y)
|
41
|
+
end
|
42
|
+
@images.last[x,y] = ChunkyPNG::Color.rgb(chans[0], chans[1], chans[2])
|
43
|
+
end
|
44
|
+
|
45
|
+
def channel_difference(chan, pixel, x, y)
|
46
|
+
ChunkyPNG::Color.send(chan, pixel) + ChunkyPNG::Color.send(chan, @images.last[x,y]) - 2 * [ChunkyPNG::Color.send(chan, pixel), ChunkyPNG::Color.send(chan, @images.last[x,y])].min
|
47
|
+
end
|
48
|
+
|
41
49
|
def percentage_diff(org, fresh)
|
42
50
|
diff_images(org, fresh)
|
43
51
|
@total_px = @images.first.pixels.length
|
@@ -47,19 +55,11 @@ module GreenOnion
|
|
47
55
|
|
48
56
|
def visual_diff(org, fresh)
|
49
57
|
diff_images(org, fresh)
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
|
-
def percentage_and_visual_diff(org, fresh)
|
54
|
-
diff_images(org, fresh)
|
55
|
-
@total_px = @images.first.pixels.length
|
56
|
-
@changed_px = @diff_index.length
|
57
|
-
@percentage_changed = ( (@diff_index.length.to_f / @images.first.pixels.length) * 100 ).round(2)
|
58
|
+
save_visual_diff(org, fresh)
|
58
59
|
end
|
59
60
|
|
60
|
-
def
|
61
|
+
def save_visual_diff(org, fresh)
|
61
62
|
x, y = @diff_index.map{ |xy| xy[0] }, @diff_index.map{ |xy| xy[1] }
|
62
|
-
|
63
63
|
@diffed_image = org.insert(-5, '_diff')
|
64
64
|
|
65
65
|
begin
|
@@ -17,5 +17,5 @@ all_routes = Rails.application.routes.routes
|
|
17
17
|
routes = all_routes.collect { |r| r.path.spec.to_s.gsub(/\/*(\(\.)*:(\w*)(\))*\/*/, "") }.delete_if(&:empty?)
|
18
18
|
|
19
19
|
routes.each do |route|
|
20
|
-
GreenOnion.
|
20
|
+
GreenOnion.skin_visual_and_percentage("<%= config[:url] %>" + route)
|
21
21
|
end
|
@@ -36,8 +36,17 @@ module GreenOnion
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
def url_matcher(url)
|
40
|
+
url_match = url.match(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/).to_a.compact
|
41
|
+
if url_match.length >= 5
|
42
|
+
@filename = url_match[5]
|
43
|
+
else
|
44
|
+
raise Errors::IllformattedURL.new "Your URL is incorrectly formatted. Please make sure to use http://"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
39
48
|
def get_path(url)
|
40
|
-
|
49
|
+
url_matcher(url)
|
41
50
|
if @filename.empty? || @filename == '/'
|
42
51
|
@paths_hash[:original] = "#{@dir}/root.png"
|
43
52
|
else
|
data/lib/green_onion/version.rb
CHANGED
data/lib/green_onion.rb
CHANGED
@@ -2,6 +2,7 @@ require "green_onion/version"
|
|
2
2
|
require "green_onion/screenshot"
|
3
3
|
require "green_onion/compare"
|
4
4
|
require "green_onion/configuration"
|
5
|
+
require "green_onion/errors"
|
5
6
|
require "rainbow"
|
6
7
|
|
7
8
|
module GreenOnion
|
@@ -32,35 +33,34 @@ module GreenOnion
|
|
32
33
|
# Finds the percentage of change between skins
|
33
34
|
# Threshold can be set in configuration, or as an argument itself, and can be specific to an instance
|
34
35
|
def skin_percentage(url, threshold=@configuration.threshold)
|
36
|
+
raise Errors::ThresholdOutOfRange.new "The threshold need to be a number between 1 and 100" if threshold > 100
|
35
37
|
skin(url)
|
36
|
-
|
37
|
-
puts "\n" + url.color(:cyan)
|
38
|
-
@compare.percentage_diff(@screenshot.paths_hash[:original], @screenshot.paths_hash[:fresh])
|
39
|
-
threshold_alert(@compare.percentage_changed, threshold)
|
40
|
-
else
|
41
|
-
puts "\n#{url}".color(:cyan) + " has been saved to #{@screenshot.paths_hash[:original]}".color(:yellow)
|
42
|
-
end
|
38
|
+
skin_picker(url, { :percentage => true }, threshold)
|
43
39
|
end
|
44
40
|
|
45
41
|
# Creates a diffed screenshot between skins
|
46
42
|
def skin_visual(url)
|
47
43
|
skin(url)
|
48
|
-
|
49
|
-
puts "\n" + url.color(:cyan)
|
50
|
-
@compare.visual_diff(@screenshot.paths_hash[:original], @screenshot.paths_hash[:fresh])
|
51
|
-
else
|
52
|
-
puts "\n#{url}".color(:cyan) + " has been saved to #{@screenshot.paths_hash[:original]}".color(:yellow)
|
53
|
-
end
|
44
|
+
skin_picker(url, { :visual => true })
|
54
45
|
end
|
55
46
|
|
56
47
|
# Creates a diffed screenshot between skins AND prints percentage changed
|
57
48
|
def skin_visual_and_percentage(url, threshold=@configuration.threshold)
|
49
|
+
raise Errors::ThresholdOutOfRange.new "The threshold need to be a number between 1 and 100" if threshold > 100
|
58
50
|
skin(url)
|
51
|
+
skin_picker(url, { :percentage => true, :visual => true }, threshold)
|
52
|
+
end
|
53
|
+
|
54
|
+
def skin_picker(url, type, threshold=100)
|
59
55
|
if(@screenshot.paths_hash.length > 1)
|
60
56
|
puts "\n" + url.color(:cyan)
|
61
|
-
|
62
|
-
|
63
|
-
|
57
|
+
if type[:percentage]
|
58
|
+
@compare.percentage_diff(@screenshot.paths_hash[:original], @screenshot.paths_hash[:fresh])
|
59
|
+
threshold_alert(@compare.percentage_changed, threshold)
|
60
|
+
end
|
61
|
+
if type[:visual]
|
62
|
+
@compare.visual_diff(@screenshot.paths_hash[:original], @screenshot.paths_hash[:fresh])
|
63
|
+
end
|
64
64
|
else
|
65
65
|
puts "\n#{url}".color(:cyan) + " has been saved to #{@screenshot.paths_hash[:original]}".color(:yellow)
|
66
66
|
end
|
data/spec/unit/cli_spec.rb
CHANGED
@@ -11,10 +11,6 @@ describe "bin/green_onion" do
|
|
11
11
|
|
12
12
|
describe "Skin Utility" do
|
13
13
|
|
14
|
-
before(:each) do
|
15
|
-
FileUtils.mkdir(@tmp_path)
|
16
|
-
end
|
17
|
-
|
18
14
|
after(:each) do
|
19
15
|
FileUtils.rm_r(@tmp_path, :force => true)
|
20
16
|
end
|
@@ -24,22 +20,30 @@ describe "bin/green_onion" do
|
|
24
20
|
File.exist?(@file1).should be_true
|
25
21
|
end
|
26
22
|
|
23
|
+
it "should run the skin task w/ --method=p flag to run only percentage diff" do
|
24
|
+
stdin, stdout, stderr = Open3.popen3("bin/green_onion skin #{@url} --dir=#{@tmp_path} --method=p --threshold=1 &&
|
25
|
+
bin/green_onion skin #{@url} --dir=#{@tmp_path} --method=p --threshold=1")
|
26
|
+
stderr.readlines.to_s.should include("above threshold set @")
|
27
|
+
end
|
28
|
+
|
27
29
|
end
|
28
30
|
|
29
31
|
describe "Generator" do
|
30
32
|
|
31
|
-
before(:each) do
|
32
|
-
FileUtils.mkdir(@tmp_path)
|
33
|
-
end
|
34
|
-
|
35
33
|
after(:each) do
|
36
34
|
FileUtils.rm_r(@tmp_path, :force => true)
|
37
35
|
end
|
38
36
|
|
39
37
|
it "should build the skinner file" do
|
40
|
-
`bin/green_onion generate --
|
38
|
+
`bin/green_onion generate --dir=#{@tmp_path}`
|
41
39
|
File.exist?(@skinner_file).should be_true
|
42
40
|
end
|
41
|
+
|
42
|
+
it "should build the skinner file with the url included correctly" do
|
43
|
+
`bin/green_onion generate --url=#{@url} --dir=#{@tmp_path}`
|
44
|
+
skinner = IO.read(@skinner_file)
|
45
|
+
skinner.should include("GreenOnion.skin_visual_and_percentage(\"http://localhost:8070\" + route)")
|
46
|
+
end
|
43
47
|
|
44
48
|
end
|
45
49
|
end
|
@@ -10,8 +10,6 @@ describe GreenOnion do
|
|
10
10
|
|
11
11
|
describe "Skins" do
|
12
12
|
before(:each) do
|
13
|
-
FileUtils.mkdir(@tmp_path)
|
14
|
-
|
15
13
|
GreenOnion.configure do |c|
|
16
14
|
c.skins_dir = @tmp_path
|
17
15
|
end
|
@@ -84,8 +82,6 @@ describe GreenOnion do
|
|
84
82
|
|
85
83
|
describe "Skins with custom dimensions" do
|
86
84
|
before(:each) do
|
87
|
-
FileUtils.mkdir(@tmp_path)
|
88
|
-
|
89
85
|
GreenOnion.configure do |c|
|
90
86
|
c.skins_dir = @tmp_path
|
91
87
|
c.dimensions = { :width => 1440, :height => 900 }
|
@@ -104,8 +100,6 @@ describe GreenOnion do
|
|
104
100
|
|
105
101
|
describe "Skins with custom threshold" do
|
106
102
|
before(:each) do
|
107
|
-
FileUtils.mkdir(@tmp_path)
|
108
|
-
|
109
103
|
GreenOnion.configure do |c|
|
110
104
|
c.skins_dir = @tmp_path
|
111
105
|
c.threshold = 1
|
@@ -123,4 +117,28 @@ describe GreenOnion do
|
|
123
117
|
end
|
124
118
|
end
|
125
119
|
end
|
120
|
+
|
121
|
+
describe "Errors" do
|
122
|
+
before(:each) do
|
123
|
+
GreenOnion.configure do |c|
|
124
|
+
c.skins_dir = @tmp_path
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
after(:each) do
|
129
|
+
FileUtils.rm_r(@tmp_path, :force => true)
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should raise error for when ill-formatted URL is used" do
|
133
|
+
expect { GreenOnion.skin_percentage("localhost") }.to raise_error(GreenOnion::Errors::IllformattedURL)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should raise error for when threshold is out of range for skin_percentage" do
|
137
|
+
expect { GreenOnion.skin_percentage(@url, 101) }.to raise_error(GreenOnion::Errors::ThresholdOutOfRange)
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should raise error for when threshold is out of range for skin_visual_and_percentage" do
|
141
|
+
expect { GreenOnion.skin_visual_and_percentage(@url, 101) }.to raise_error(GreenOnion::Errors::ThresholdOutOfRange)
|
142
|
+
end
|
143
|
+
end
|
126
144
|
end
|
@@ -12,8 +12,6 @@ describe GreenOnion::Screenshot do
|
|
12
12
|
describe 'Snap single screenshot' do
|
13
13
|
|
14
14
|
before(:each) do
|
15
|
-
FileUtils.mkdir(@tmp_path)
|
16
|
-
|
17
15
|
@screenshot = GreenOnion::Screenshot.new(
|
18
16
|
:dir => @tmp_path,
|
19
17
|
:dimensions => @dimensions
|
@@ -51,8 +49,6 @@ describe GreenOnion::Screenshot do
|
|
51
49
|
describe 'Snap two screenshots' do
|
52
50
|
|
53
51
|
before(:each) do
|
54
|
-
FileUtils.mkdir(@tmp_path)
|
55
|
-
|
56
52
|
@screenshot = GreenOnion::Screenshot.new(
|
57
53
|
:dir => @tmp_path,
|
58
54
|
:dimensions => @dimensions
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: green_onion
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.1.
|
5
|
+
version: 0.1.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Ted O'Meara
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-08-
|
13
|
+
date: 2012-08-06 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake
|
@@ -157,6 +157,7 @@ files:
|
|
157
157
|
- lib/green_onion/cli.rb
|
158
158
|
- lib/green_onion/compare.rb
|
159
159
|
- lib/green_onion/configuration.rb
|
160
|
+
- lib/green_onion/errors.rb
|
160
161
|
- lib/green_onion/generators/skinner.erb
|
161
162
|
- lib/green_onion/screenshot.rb
|
162
163
|
- lib/green_onion/version.rb
|