looks_good 1.0.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.
@@ -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