looks_good 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,180 @@
1
+ require 'spec_helper'
2
+
3
+ describe LooksGood::Configuration do
4
+
5
+
6
+ describe "#reference_image_path" do
7
+
8
+ after :each do
9
+ config_clean_up
10
+ end
11
+
12
+ describe "without Rails" do
13
+ it "should default to './spec/reference_images' when not in a rails environment" do
14
+ LooksGood::Configuration.reference_image_path.should eql("spec/reference_images")
15
+ end
16
+ end
17
+
18
+ describe "with rails" do
19
+
20
+ before do
21
+ begin
22
+ # Check that rails exists, otherwise fake it for the test
23
+ Module.const_get("Rails")
24
+ rescue NameError
25
+ module Rails
26
+ def self.root
27
+ "fake_rails_root"
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ it "should default to <Rails.root>/spec/reference_images in a rails environment" do
34
+ subject.reference_image_path.should == "fake_rails_root/spec/reference_images"
35
+ end
36
+
37
+ it "should be overrideable in a rails environment" do
38
+ subject.reference_image_path = "my custom path"
39
+ subject.reference_image_path.should == "my custom path"
40
+ end
41
+
42
+ it 'should return the directory for a type of image' do
43
+ subject.reference_image_path = "a_path"
44
+ subject.path(:temp).should == 'a_path/temp'
45
+ end
46
+
47
+ end
48
+
49
+ describe "creating custom reference folders" do
50
+
51
+ before :each do
52
+ subject.reference_image_path = '/some/ref/path'
53
+ end
54
+
55
+ it "should default to custom folders off" do
56
+ subject.browser_folders.should == false
57
+ end
58
+
59
+ it "should allow setting custom folders on" do
60
+ subject.browser_folders = true
61
+ subject.browser_folders.should == true
62
+ end
63
+
64
+
65
+ it "should set reference_image_path to default when browser can\'t be found" do
66
+ subject.browser_folders = true
67
+ Capybara.page.driver.browser.should_receive(:browser).at_least(:once).and_raise(StandardError.new)
68
+ subject.reference_image_path.should == '/some/ref/path'
69
+ end
70
+
71
+ it "should create custom folder for each browser according to ENV" do
72
+ pending
73
+ end
74
+
75
+ it "should set the image reference path for each browser according to selenium driver if no ENV is set" do
76
+ subject.browser_folders = true
77
+ subject.stub!(:browser).and_return('chrome')
78
+ subject.reference_image_path.should == '/some/ref/path/chrome'
79
+ subject.browser_folders = false
80
+ end
81
+
82
+
83
+ end
84
+ end
85
+
86
+ describe "#max_no_tries" do
87
+
88
+ it "should default to 5" do
89
+ subject.max_no_tries.should == 5
90
+ end
91
+
92
+ it "should be settable" do
93
+ LooksGood::Configuration.max_no_tries = 1
94
+ subject.max_no_tries.should == 1
95
+ end
96
+ end
97
+
98
+ describe "#sleep_between_tries" do
99
+
100
+ it "should default to 0.5" do
101
+ subject.sleep_between_tries.should == 0.5
102
+ end
103
+
104
+ it "should be settable" do
105
+ subject.sleep_between_tries = 55
106
+ subject.sleep_between_tries.should == 55
107
+ end
108
+ end
109
+
110
+ describe "settings" do
111
+
112
+ describe "should accept a block of settings and parse them correctly" do
113
+
114
+ it "for reference_image_path" do
115
+ LooksGood.config do |c|
116
+ c.reference_image_path = 'custom_path'
117
+ end
118
+ subject.reference_image_path.should == 'custom_path'
119
+ end
120
+
121
+ it "for max_no_tries" do
122
+ LooksGood.config do |c|
123
+ c.max_no_tries = 3
124
+ end
125
+
126
+ subject.max_no_tries.should == 3
127
+ end
128
+
129
+ it "sleep_between_tries" do
130
+ LooksGood.config do |c|
131
+ c.sleep_between_tries = 0.7
132
+ end
133
+ subject.sleep_between_tries.should == 0.7
134
+ end
135
+
136
+ it "for browser_folders" do
137
+ LooksGood.config do |c|
138
+ c.browser_folders = true
139
+ end
140
+
141
+ subject.browser_folders.should == true
142
+ end
143
+
144
+ end
145
+ end
146
+
147
+ describe "config block" do
148
+
149
+ it 'should be able to set a config block' do
150
+ LooksGood.config do |c|
151
+ c.reference_image_path = 'some/path'
152
+ c.max_no_tries = 4
153
+ c.sleep_between_tries = 5
154
+ c.browser_folders = false
155
+ end
156
+
157
+ subject.reference_image_path.should == 'some/path'
158
+ subject.max_no_tries.should == 4
159
+ subject.sleep_between_tries.should == 5
160
+ subject.browser_folders.should == false
161
+ end
162
+
163
+ it 'should raise depreciation alert when calling old block' do
164
+ expect {
165
+ LooksGood.config do |c|
166
+ LooksGood.reference_image_path = 'some/path'
167
+ LooksGood.max_no_tries = 4
168
+ LooksGood.sleep_between_tries = 5
169
+ LooksGood.browser_folders = false
170
+ end
171
+ }.to raise_error "Config block has changed. Example: LooksGood.config {|c| c.reference_image_path = 'some/path'}. Please see README"
172
+ end
173
+
174
+
175
+ end
176
+
177
+
178
+
179
+
180
+ end
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+ include Capybara::DSL
3
+
4
+ describe LooksGood do
5
+
6
+ after :all do
7
+ config_clean_up
8
+ end
9
+
10
+ let(:actual_image) { mock("LooksGood::Image") }
11
+ let(:expected_image) { mock("LooksGood::Image") }
12
+ let(:comparison) { mock("LooksGood::Comparison") }
13
+ let(:element) { mock("LooksGood::CaptureElement") }
14
+
15
+
16
+ describe 'comparison' do
17
+ before :each do
18
+ LooksGood::ImageFromFile.stub!(:new).and_return(expected_image)
19
+ LooksGood::ImageFromElement.stub!(:new).and_return(actual_image)
20
+ LooksGood::Comparison.stub!(:new).and_return(comparison)
21
+ expected_image.should_receive(:file_name).and_return('expected_image.png')
22
+ end
23
+
24
+ it 'will return true if the images are identical' do
25
+ comparison.stub!(:matches?).and_return(true)
26
+ File.stub!(:exists?).and_return(true)
27
+
28
+ subject.matches?("expected_image.png", @element).should be_true
29
+ end
30
+ end
31
+
32
+
33
+ describe 'saving images' do
34
+ before :each do
35
+ @image_class_mock = mock(LooksGood::Image)
36
+ end
37
+
38
+
39
+ it "#save_image_as_diff" do
40
+ @image_class_mock.should_receive(:save).with(:diff).and_return(@ref_path)
41
+ @image_class_mock.should_receive(:file_name).at_least(:once).and_return("some_name")
42
+
43
+ expect {subject.save_image_as_diff(@image_class_mock)}.to raise_error
44
+ end
45
+
46
+ it "#save_image_as_candidate" do
47
+ @image_class_mock.should_receive(:save).with(:candidate).and_return(@ref_path)
48
+ @image_class_mock.should_receive(:file_name).at_least(:once).and_return("some_name")
49
+ @image_class_mock.should_receive(:path).and_return(@path)
50
+ expect {subject.save_image_as_candidate(@image_class_mock)}.to raise_error
51
+ end
52
+
53
+ describe "#save_image_as_reference" do
54
+
55
+ let(:image) {mock('image.png')}
56
+ let(:reference_image) {LooksGood::ImageFromElement.stub(:new).and_return(image)}
57
+ let(:comparison) {mock("comparison")}
58
+
59
+ before :each do
60
+ LooksGood.stub!(:compare_until_match).and_return(comparison)
61
+ end
62
+
63
+ end
64
+ end
65
+
66
+ describe "#compare_until_match" do
67
+
68
+ before :each do
69
+ LooksGood::ImageFromElement.stub!(:new).and_return(actual_image)
70
+ LooksGood::ImageFromFile.stub!(:new).and_return(expected_image)
71
+ LooksGood::Comparison.stub!(:new).and_return(comparison)
72
+
73
+ expected_image.should_receive(:file_name).at_least(:once).and_return('expected_image.png')
74
+ end
75
+
76
+ it "should try match for a specified amount of times" do
77
+ comparison.should_receive(:matches?).exactly(3).times.and_return(false)
78
+ LooksGood.compare_until_match(@element, expected_image, 3, 0.1)
79
+ end
80
+
81
+ it "should pass after a few tries if match is found" do
82
+ comparison.should_receive(:matches?).exactly(1).times.and_return(true)
83
+ LooksGood.compare_until_match(@element, expected_image, 3, 0.1)
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+
3
+ describe LooksGood::Image do
4
+
5
+ let(:example_image) { Magick::Image.new(1,1) }
6
+ let(:ref_path) { 'spec/reference_images/image.png' }
7
+
8
+ before :each do
9
+ LooksGood::Configuration.reference_image_path = 'spec/reference_images'
10
+ end
11
+
12
+ after :each do
13
+ config_clean_up
14
+ end
15
+
16
+ describe 'should initialize from' do
17
+ it 'ImageFromFile - IO file read' do
18
+ File.stub(:exists?).and_return(true)
19
+ Magick::Image.should_receive(:read).with(ref_path).and_return([example_image])
20
+
21
+ subject = LooksGood::ImageFromFile.new("image.png")
22
+ subject.image.should == example_image
23
+ subject.file_name.should == 'image.png'
24
+ end
25
+
26
+
27
+ end
28
+
29
+ describe "save" do
30
+ it 'will save an image' do
31
+ example_image.should_receive(:write).with(ref_path).and_return()
32
+
33
+ File.should_receive(:exists?).with(ref_path).and_return(true)
34
+ FileUtils.should_not_receive(:mkdir_p)
35
+ subject = LooksGood::Image.new(example_image, "image.png")
36
+
37
+ subject.save
38
+ subject.path.should == ref_path
39
+ end
40
+ end
41
+
42
+ describe "it creates a path from path types" do
43
+
44
+ before :each do
45
+ LooksGood::Configuration.should_receive(:reference_image_path).any_number_of_times.and_return('/some/path')
46
+ mock_image = mock(Magick::Image)
47
+ @subject = LooksGood::Image.new(mock_image, 'image.png')
48
+ end
49
+
50
+ it "from reference" do
51
+ # expected_path = '/some/path/reference'
52
+ @subject.path.should == '/some/path/image.png'
53
+ end
54
+
55
+ it "from diff" do
56
+ @subject.path(:diff).should == '/some/path/diff/image.png'
57
+ end
58
+
59
+ it "from candidate" do
60
+ @subject.path(:candidate).should == '/some/path/candidate/image.png'
61
+ end
62
+
63
+ end
64
+
65
+ describe "ImageFromElement" do
66
+
67
+ let(:mock_element) { mock(Capybara::Node::Element) }
68
+ let(:comparison) { mock('comparison') }
69
+
70
+ it 'should initialize from a web element' do
71
+ LooksGood::CaptureElement.should_receive(:capture).with(mock_element).and_return(example_image)
72
+
73
+ subject = LooksGood::ImageFromElement.new(mock_element, "image.png")
74
+ subject.image.class.should == example_image.class
75
+ subject.file_name.should == 'image.png'
76
+ end
77
+
78
+ describe '.save_and_verify' do
79
+
80
+ it 'should verify the element and then save' do
81
+ LooksGood::Comparison.should_receive(:new).exactly(2).times.and_return(comparison)
82
+ comparison.should_receive(:matches?).exactly(2).times.and_return(false,true)
83
+
84
+ LooksGood::CaptureElement.should_receive(:capture).exactly(3).times.with(mock_element).and_return(example_image)
85
+
86
+ subject = LooksGood::ImageFromElement.new(mock_element, "image.png")
87
+ subject.should_receive(:save)
88
+
89
+ LooksGood::Configuration.max_no_tries = 3
90
+
91
+ subject.verify_and_save
92
+ end
93
+
94
+ it 'should raise an exception if can\'t create a stable image' do
95
+ LooksGood::Configuration.max_no_tries = 1
96
+ LooksGood::CaptureElement.stub!(:capture).and_return(mock_element)
97
+ LooksGood::Comparison.stub!(:matches?).and_return(false)
98
+
99
+ subject = LooksGood::ImageFromElement.new(mock_element, "image.png")
100
+
101
+ expect {subject.verify_and_save}.to raise_error
102
+ end
103
+ end
104
+
105
+
106
+ end
107
+
108
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+ include Capybara::DSL
3
+
4
+ describe 'LooksGood' do
5
+
6
+ before(:all) do
7
+ @spec_support_root = spec_support_root
8
+ @black_box = 'black.png'
9
+ @red_box = 'red.png'
10
+ end
11
+
12
+ before(:each) do
13
+ @ref_path = LooksGood::Configuration.reference_image_path = File.join(spec_support_root, 'ref_path')
14
+ end
15
+
16
+ after(:each) do
17
+ remove_refs(@ref_path)
18
+ end
19
+
20
+ describe 'LooksGood, when no reference image exists' do
21
+
22
+ it "will notify that no reference image exists and create a candidate image" do
23
+ pending
24
+ mock_element = mock
25
+ mock_element.stub(:native).and_return(mock_element)
26
+
27
+ expected_error = "The design reference #{@black_box} does not exist, #{@ref_path}/candidate/#{@black_box} " +
28
+ "is now available to be used as a reference. " +
29
+ "Copy candidate to root reference_image_path to use as reference"
30
+
31
+ expect {LooksGood.matches?(@black_box, mock_element)}.to raise_error(RuntimeError, expected_error)
32
+
33
+ File.exists?(File.join(@ref_path, 'candidate', @black_box)).should be_true
34
+ end
35
+ end
36
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require rubygems
3
+ --require rspec/instafail
@@ -0,0 +1,59 @@
1
+ require 'rubygems'
2
+ require 'capybara'
3
+ require 'capybara/dsl'
4
+ require 'capybara/rspec'
5
+ require 'looks_good'
6
+ require 'looks_good/matchers/look_like_matcher'
7
+ require 'fileutils'
8
+ require 'pry'
9
+
10
+ #todo: spec folders clean up method
11
+ RSpec.configure do |config|
12
+ config.color_enabled = true
13
+ config.formatter = 'documentation'
14
+ end
15
+
16
+ Capybara.app_host = "file://#{File.expand_path(File.dirname(__FILE__))}/support/assets"
17
+ Capybara.default_driver = :selenium
18
+ Capybara.run_server = false
19
+
20
+ def config_clean_up
21
+ LooksGood::Configuration.reference_image_path = nil
22
+ LooksGood::Configuration.browser_folders = false
23
+ LooksGood::Configuration.max_no_tries = nil
24
+ end
25
+
26
+ def remove_refs(dir)
27
+ Dir.glob("#{dir}/**/*.png").each {|image| FileUtils.rm image}
28
+ end
29
+
30
+ def element_for_spec(css = '#black')
31
+ visit('/fruit_app.html')
32
+ @element = page.find(:css, css)
33
+ end
34
+
35
+ def spec_support_root
36
+ File.join(File.dirname(__FILE__), 'support')
37
+ end
38
+
39
+ def create_images_for_web_page
40
+ asset_reference_path = File.join(spec_support_root, 'assets')
41
+ create_square_image(asset_reference_path, 'black')
42
+ create_square_image(asset_reference_path, 'red')
43
+ end
44
+
45
+ def create_square_image(path, color)
46
+ # We make the images, rather then check them in because otherwise the comparison tests
47
+ # become very flakey depending on the graphics set up on the computer running them
48
+ FileUtils::mkdir_p(path)
49
+
50
+ reference_file = Magick::Image.new(100,100) { self.background_color = 'white' }
51
+ square = Magick::Draw.new
52
+ square.fill_opacity(100)
53
+ square.fill_color(color)
54
+ square.rectangle(10,10, 90,90)
55
+ square.draw(reference_file)
56
+
57
+ reference_file.write(File.join(path, "#{color}.png"))
58
+ reference_file
59
+ end
@@ -0,0 +1,23 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2
+ "http://www.w3.org/TR/html4/loose.dtd">
3
+ <html>
4
+ <head>
5
+ <style type="text/css">
6
+ div.ex
7
+ {
8
+ width:220px;
9
+ padding:10px;
10
+ border:5px solid gray;
11
+ margin:0px;
12
+ }
13
+ </style>
14
+ <title>The Smiley Site</title>
15
+ </head>
16
+ <body>
17
+ <div class='ex' id="box">
18
+ <img src='./black.png' id="black"/>
19
+ <img src='./red.png' id="red"/>
20
+ </div>
21
+ <img src='./black.png' id="different-size" width="15px" height="180px"/>
22
+ </body>
23
+ </html>
data/temp-1032.rdb ADDED
File without changes
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: looks_good
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Russell Jennings
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-08-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rmagick
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 2.15.4
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 2.15.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: capybara
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.6.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 2.6.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.9.2
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.9.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 0.10.2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 0.10.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: selenium-webdriver
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 2.53.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 2.53.0
83
+ description: Rspec visual testing with percent matching tolerance
84
+ email:
85
+ - violentpurr@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".DS_Store"
91
+ - ".gitignore"
92
+ - Gemfile
93
+ - Gemfile.lock
94
+ - LICENSE.txt
95
+ - README.md
96
+ - lib/looks_good.rb
97
+ - lib/looks_good/capture_element.rb
98
+ - lib/looks_good/comparison.rb
99
+ - lib/looks_good/configuration.rb
100
+ - lib/looks_good/image.rb
101
+ - lib/looks_good/matchers/look_like_matcher.rb
102
+ - lib/looks_good/rspec_config.rb
103
+ - lib/looks_good/version.rb
104
+ - looks_good.gemspec
105
+ - reports/rspec_unit_test_output.html
106
+ - spec/acceptance/gatling_acceptance_spec.rb
107
+ - spec/acceptance/rspec_matcher_spec.rb
108
+ - spec/capture_spec.rb
109
+ - spec/comparison_spec.rb
110
+ - spec/configuration_spec.rb
111
+ - spec/gatling_spec.rb
112
+ - spec/image_spec.rb
113
+ - spec/integration/gatling_integration_spec.rb
114
+ - spec/spec.opts
115
+ - spec/spec_helper.rb
116
+ - spec/support/assets/fruit_app.html
117
+ - temp-1032.rdb
118
+ homepage: http://github.com/meesterdude/looks_good
119
+ licenses: []
120
+ metadata: {}
121
+ post_install_message:
122
+ rdoc_options: []
123
+ require_paths:
124
+ - lib
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ requirements: []
136
+ rubygems_version: 3.3.19
137
+ signing_key:
138
+ specification_version: 4
139
+ summary: Rspec visual testing
140
+ test_files:
141
+ - spec/acceptance/gatling_acceptance_spec.rb
142
+ - spec/acceptance/rspec_matcher_spec.rb
143
+ - spec/capture_spec.rb
144
+ - spec/comparison_spec.rb
145
+ - spec/configuration_spec.rb
146
+ - spec/gatling_spec.rb
147
+ - spec/image_spec.rb
148
+ - spec/integration/gatling_integration_spec.rb
149
+ - spec/spec.opts
150
+ - spec/spec_helper.rb
151
+ - spec/support/assets/fruit_app.html