cezanne 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3b042161b943e9c613765446eb96de02c932c1ed
4
+ data.tar.gz: ea2b8b6803ed4cb416da7dc9d031265f8ce368f4
5
+ SHA512:
6
+ metadata.gz: f839e12234ddb4d54248264aa6d974191d129c705652eb01f98d860463e6a9e47d1f68e9bf77c981e7e41253aecd4546fceb3f86002d3fe6a290a8643a372b3f
7
+ data.tar.gz: 42f2832a17ce4a8cc10bed8ae5bedaca3c334ef953da157a8e30751e90597b26605a53cc2b9eb9ef3966290a0fef77533b01c2e8e7ef0d7e05fbbc4e2ee875e5
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ artifacts
19
+ *.swp
20
+ .DS_Store
21
+ .env
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cezanne.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Andrea Pigato
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Cezanne
2
+
3
+ Visual regression testing tool
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'cezanne'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install cezanne
18
+
19
+ ## Usage
20
+
21
+ coming soon
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it ( http://github.com/<my-github-username>/cezanne/fork )
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/cezanne.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cezanne/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "cezanne"
8
+ spec.version = Cezanne::VERSION
9
+ spec.authors = ["Sky Haiku"]
10
+ spec.email = ["skyhaikuteam@gmail.com"]
11
+ spec.summary = %q{Visual regression testing tool}
12
+ spec.description = %q{Let Cezanne help you make sure your views look alright}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "pry"
25
+ spec.add_development_dependency "capybara"
26
+ spec.add_development_dependency "selenium-webdriver"
27
+
28
+ spec.add_dependency "rmagick"
29
+ spec.add_dependency "dropscreen"
30
+ end
@@ -0,0 +1,14 @@
1
+ require 'RMagick'
2
+
3
+ module Cezanne
4
+
5
+ SIMILARITY_THRESHOLD = 42
6
+
7
+ def spot_differences_between this, that
8
+ width = [this.width, that.width].min
9
+ height = [this.height, that.height].min
10
+ [this, that].each { |img| img.crop!(width, height) }
11
+ this.picture.compare_channel(that.picture, Magick::PeakSignalToNoiseRatioMetric)[1] < SIMILARITY_THRESHOLD
12
+ end
13
+
14
+ end
@@ -0,0 +1,27 @@
1
+ require 'RMagick'
2
+
3
+ module Cezanne
4
+
5
+ class Image
6
+ attr_reader :path, :picture
7
+
8
+ def initialize path
9
+ @path = path
10
+ @picture = Magick::Image.read(@path).first
11
+ end
12
+
13
+ def crop! *coords
14
+ if coords.length == 2 then coords = [0, 0, *coords] end # treat them as widht and height
15
+ @picture.crop!(*coords)
16
+ end
17
+
18
+ def width
19
+ @picture.columns
20
+ end
21
+
22
+ def height
23
+ @picture.rows
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,36 @@
1
+ module Cezanne
2
+
3
+ class LocalFiles
4
+
5
+ def initialize uid, base_path
6
+
7
+ @folders = {
8
+ ref: File.join(base_path, 'reference_screenshots'),
9
+ diff: File.join(base_path, uid, 'different_screenshots'),
10
+ new: File.join(base_path, uid, 'new_screenshots'),
11
+ tmp: File.join(base_path, uid, 'tmp_screenshots')
12
+ }
13
+
14
+ @folders.each { |key, path| setup_directory_for key }
15
+
16
+ end
17
+
18
+ def path_for key
19
+ @folders[key]
20
+ end
21
+
22
+ def clean
23
+ path = File.dirname( path_for(:ref) )
24
+ FileUtils.rm_rf path
25
+ end
26
+
27
+ private
28
+
29
+ def setup_directory_for key
30
+ FileUtils.rm_rf path_for(key)
31
+ FileUtils.mkdir_p path_for(key)
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,27 @@
1
+ require 'dropscreen'
2
+
3
+ module Cezanne
4
+
5
+ class RemoteFiles
6
+
7
+ def initialize uid, base_path
8
+ @remote_folders = {
9
+ ref: File.join('reference_screenshots'),
10
+ diff: File.join(uid, 'different_screenshots'),
11
+ new: File.join(uid, 'new_screenshots')
12
+ }
13
+
14
+ @adapter = Dropscreen::Client.new( remote_base_dir: base_path, local_base_dir: './' )
15
+ end
16
+
17
+ def pull key, path
18
+ @adapter.pull @remote_folders[key], path
19
+ end
20
+
21
+ def push path, key
22
+ @adapter.push path, @remote_folders[key]
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,43 @@
1
+ require 'cezanne'
2
+ require 'rspec/core'
3
+
4
+ RSpec.configure do |config|
5
+
6
+ config.add_setting :cezanne
7
+
8
+ config.before(:all, screenshots: true) do
9
+ if self.class.include?(Cezanne)
10
+ uid = config.cezanne[:uid]
11
+ project_name = config.cezanne[:project_name]
12
+ config.cezanne[:local_files] = Cezanne::LocalFiles.new(uid, 'artifacts')
13
+ config.cezanne[:remote_files] = Cezanne::RemoteFiles.new(uid, project_name)
14
+ begin
15
+ config.cezanne[:remote_files].pull(:ref, config.cezanne[:local_files].path_for(:ref))
16
+ rescue
17
+ puts "no reference screenshot exist for project #{project_name}"
18
+ end
19
+ end
20
+ end
21
+
22
+ config.after(:all, screenshots: true) do
23
+ if self.class.include?(Cezanne)
24
+ [:new, :diff].each do |key|
25
+ config.cezanne[:remote_files].push(config.cezanne[:local_files].path_for(key), key)
26
+ end
27
+ config.cezanne[:local_files].clean
28
+ end
29
+ end
30
+
31
+ end
32
+
33
+ module Cezanne
34
+
35
+ def local_files
36
+ RSpec.configuration.cezanne[:local_files]
37
+ end
38
+
39
+ def remote_files
40
+ RSpec.configuration.cezanne[:remote_files]
41
+ end
42
+
43
+ end
@@ -0,0 +1,3 @@
1
+ module Cezanne
2
+ VERSION = "0.0.1"
3
+ end
data/lib/cezanne.rb ADDED
@@ -0,0 +1,56 @@
1
+ require "cezanne/version"
2
+ require "cezanne/local_files"
3
+ require "cezanne/remote_files"
4
+ require "cezanne/image"
5
+ require "cezanne/comparison"
6
+
7
+ module Cezanne
8
+
9
+ def check_visual_regression_for page_name
10
+ screenshot = take_screenshot page_name
11
+ reference_screenshot = get_reference_screenshot_for page_name
12
+
13
+ unless reference_screenshot
14
+ mark_as_new screenshot
15
+ raise "new screenshot for #{page_name}"
16
+ end
17
+
18
+ if spot_differences_between screenshot, reference_screenshot
19
+ mark_for_review screenshot
20
+ raise "screenshot for #{page_name} didn't match"
21
+ end
22
+
23
+ return true
24
+ end
25
+
26
+ private
27
+
28
+ def take_screenshot page_name
29
+ path = File.join( local_files.path_for(:tmp), file_name_for(page_name) )
30
+ page.driver.browser.save_screenshot(path)
31
+ image(path)
32
+ end
33
+
34
+
35
+ def get_reference_screenshot_for page_name
36
+ path = File.join( local_files.path_for(:ref), file_name_for(page_name) )
37
+ return false unless File.exists? path
38
+ image(path)
39
+ end
40
+
41
+ def file_name_for page_name
42
+ "#{page_name}_#{page.driver.browser.browser.to_s}.gif"
43
+ end
44
+
45
+ def mark_as_new screenshot
46
+ FileUtils.mv(screenshot.path, local_files.path_for(:new))
47
+ end
48
+
49
+ def mark_for_review screenshot
50
+ FileUtils.mv(screenshot.path, local_files.path_for(:diff))
51
+ end
52
+
53
+ def image path
54
+ Cezanne::Image.new(path)
55
+ end
56
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cezanne::LocalFiles do
4
+
5
+ before(:each) do
6
+ @local_files = Cezanne::LocalFiles.new 'test', 'spec/artifacts'
7
+ end
8
+
9
+ describe '#initialize' do
10
+
11
+ it 'create local folders for the screenshots' do
12
+ expect(File.exists?('spec/artifacts/reference_screenshots')).to be true
13
+ expect(File.exists?('spec/artifacts/test/different_screenshots')).to be true
14
+ expect(File.exists?('spec/artifacts/test/new_screenshots')).to be true
15
+ end
16
+
17
+ end
18
+
19
+ describe '#path_for' do
20
+
21
+ it 'is a path helper' do
22
+ [:ref, :diff, :new, :tmp].each do |key|
23
+ expect(@local_files.path_for(key)).to eq(@local_files.instance_variable_get(:@folders)[key])
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ describe '#clean' do
30
+
31
+ it 'remove all local folders' do
32
+ @local_files.clean
33
+ expect(File.exists?('spec/artifacts/local_files_test')).to be false
34
+ end
35
+
36
+ end
37
+
38
+ after(:each) do
39
+ FileUtils.rm_rf 'spec/artifacts'
40
+ end
41
+
42
+ end
43
+
44
+ describe Cezanne::RemoteFiles do
45
+
46
+ let(:dropscreen_client) { double('Dropscreen::Client') }
47
+
48
+ before(:each) do
49
+ allow(Dropscreen::Client).to receive('new').and_return(dropscreen_client)
50
+ @remote_files = Cezanne::RemoteFiles.new 'test_uid', 'cezanne'
51
+ end
52
+
53
+ describe '#pull' do
54
+
55
+ it 'is a proxy to Dropscreen::Client#pull' do
56
+ expect(dropscreen_client).to receive(:pull).at_least(1).times.with(kind_of(String), 'local_path')
57
+ [:ref, :diff, :new].each do |key|
58
+ @remote_files.pull key, 'local_path'
59
+ end
60
+ end
61
+
62
+ end
63
+
64
+ describe '#push' do
65
+
66
+ it 'is a proxy to Dropscreen::Client#push' do
67
+ expect(dropscreen_client).to receive(:push).at_least(1).times.with('local_path', kind_of(String))
68
+ [:ref, :diff, :new].each do |key|
69
+ @remote_files.push 'local_path', key
70
+ end
71
+ end
72
+ end
73
+
74
+ end
75
+
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cezanne::Image do
4
+
5
+ let(:image) { Cezanne::Image.new('spec/images/page_name_browser.gif') }
6
+
7
+ describe '#initialize' do
8
+
9
+ it 'wraps Magick::Image' do
10
+ expect(image.picture).to be_instance_of(Magick::Image)
11
+ end
12
+
13
+ it 'return an error if there is no file at path' do
14
+ expect { Cezanne::Image.new('unexistent_file_path') }.to raise_error
15
+ end
16
+ end
17
+
18
+ describe '#width' do
19
+
20
+ it 'has a width' do
21
+ expect(image.width).to be 763
22
+ end
23
+
24
+ end
25
+
26
+ describe '#height' do
27
+
28
+ it 'has a height' do
29
+ expect(image.height).to be 599
30
+ end
31
+
32
+ end
33
+
34
+ describe '#crop!' do
35
+
36
+ it 'accepts 4 parameters x, y, width, height' do
37
+ x = 1
38
+ y = 2
39
+ width = 5
40
+ height = 10
41
+ image.crop!(x,y,width,height)
42
+ expect(image.width).to be 5
43
+ expect(image.height).to be 10
44
+ end
45
+
46
+ it 'accepts width and height alone' do
47
+ width = 10
48
+ height = 5
49
+ image.crop!(width, height)
50
+ expect(image.width).to be 10
51
+ expect(image.height).to be 5
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,100 @@
1
+ require 'cezanne/rspec'
2
+ require 'capybara/rspec'
3
+ require 'selenium-webdriver'
4
+ require 'pry'
5
+
6
+
7
+ Capybara.app = Rack::Directory.new('spec/images')
8
+ Capybara.default_driver = :selenium
9
+
10
+ RSpec.configure do |config|
11
+ config.include Cezanne
12
+ config.cezanne = { uid: 'test', project_name: 'cezanne' }
13
+ end
14
+
15
+ describe 'Cezanne RSpec integration', type: :feature, screenshots: true do
16
+
17
+ # wrap each test with before(:all) and after(:all)
18
+
19
+ after(:all) do |example|
20
+ RSpec.configuration.after(:all, screenshots: true).last.instance_variable_set(:@block, Proc.new {}) # disable the after(:all) hook
21
+ end
22
+
23
+ before(:each) do |example|
24
+ RSpec.configuration.before(:all, screenshots: true).first.run(example)
25
+ end
26
+
27
+ after(:each) do |example|
28
+ RSpec.configuration.after(:all, screenshots: true).last.run(example) unless example.metadata[:after_hook_test]
29
+ end
30
+
31
+
32
+
33
+
34
+
35
+
36
+ describe 'initialization' do
37
+
38
+ it 'create local folders' do
39
+ expect(File.exist?('artifacts/reference_screenshots')).to be true
40
+ expect(File.exist?('artifacts/test/tmp_screenshots')).to be true
41
+ expect(File.exist?('artifacts/test/different_screenshots')).to be true
42
+ expect(File.exist?('artifacts/test/new_screenshots')).to be true
43
+ end
44
+
45
+
46
+ it 'pull reference_screenshots' do
47
+ expect(File.exist?('artifacts/reference_screenshots/similar_firefox.gif')).to be true
48
+ expect(File.exist?('artifacts/reference_screenshots/different_firefox.gif')).to be true
49
+ end
50
+
51
+ end
52
+
53
+ describe 'take screenshots' do
54
+
55
+ context 'similar' do
56
+
57
+ it 'pass the test' do
58
+ visit '/similar.html'
59
+ expect { check_visual_regression_for 'similar' }.not_to raise_error
60
+ end
61
+
62
+ end
63
+
64
+ context 'different' do
65
+
66
+ it 'fail the test' do
67
+ visit '/different.html'
68
+ expect { check_visual_regression_for 'different' }.to raise_error
69
+ end
70
+
71
+ end
72
+
73
+
74
+ context 'new' do
75
+
76
+ it 'fail the test' do
77
+ visit '/new.html'
78
+ expect { check_visual_regression_for 'new' }.to raise_error
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+
85
+ describe 'finalization', after_hook_test: true do
86
+
87
+ it 'push new, diff screenshots to remote' do |example|
88
+ expect(RSpec.configuration.cezanne[:remote_files]).to receive('push').with(kind_of(String), :diff).and_call_original
89
+ expect(RSpec.configuration.cezanne[:remote_files]).to receive('push').with(kind_of(String), :new).and_call_original
90
+ RSpec.configuration.after(:all, screenshots: true).last.run(example)
91
+ end
92
+
93
+ it 'clean local folders' do |example|
94
+ RSpec.configuration.after(:all, screenshots: true).last.run(example)
95
+ expect(File.exists?('artifacts')).to be false
96
+ end
97
+
98
+ end
99
+
100
+ end
@@ -0,0 +1,215 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cezanne do
4
+
5
+ let(:class_with_cezanne) { Class.include(Cezanne).new }
6
+ # Capybara mocks
7
+ let(:page) { double('page') }
8
+ let(:driver) { double('driver') }
9
+ let(:browser) { double('browser') }
10
+ # RMagick mocks
11
+ let(:picture) { double('Magick::Image') }
12
+ # Cezanne classes mocks
13
+ let(:local_files) { double('local_files') }
14
+ let(:image) { double('Cezanne::Image') }
15
+
16
+ before(:each) do
17
+ allow(browser).to receive('browser').and_return(:browser)
18
+ allow(browser).to receive('save_screenshot')
19
+ allow(driver).to receive('browser').and_return(browser)
20
+ allow(page).to receive('driver').and_return(driver)
21
+ allow(local_files).to receive('path_for').and_return('spec/images')
22
+ allow(class_with_cezanne).to receive('page').and_return(page)
23
+ allow(class_with_cezanne).to receive('local_files').and_return(local_files)
24
+ allow(class_with_cezanne).to receive('image').and_return(image)
25
+ end
26
+
27
+ describe '#take_screenshot' do
28
+
29
+ it 'take a screenshot using the browser driver' do
30
+ expect(page.driver.browser).to receive('save_screenshot')
31
+ class_with_cezanne.send(:take_screenshot, 'page_name')
32
+ end
33
+
34
+ it 'return a Cezanne::Image' do
35
+ expect(class_with_cezanne.send(:take_screenshot, 'page_name')).to be image
36
+ end
37
+
38
+ end
39
+
40
+ describe '#get_reference_screenshot_for' do
41
+
42
+ it 'return the reference Cezanne::Image' do
43
+ expect(class_with_cezanne.send(:get_reference_screenshot_for, 'page_name')).to be image
44
+ end
45
+
46
+ it 'return false if the reference image does not exist' do
47
+ expect(class_with_cezanne.send(:get_reference_screenshot_for, 'page_name_with_no_reference')).to be false
48
+ end
49
+
50
+ end
51
+
52
+ describe '#spot_differences_between' do
53
+
54
+ let(:this) { image }
55
+ let(:that) { this.clone }
56
+
57
+ before(:each) do
58
+ allow(image).to receive('picture').and_return(picture)
59
+ allow(image).to receive('crop!')
60
+ allow(picture).to receive('compare_channel').with(picture, Magick::PeakSignalToNoiseRatioMetric).and_return([nil, 1])
61
+ allow(this).to receive('width').and_return(1)
62
+ allow(this).to receive('height').and_return(2)
63
+ allow(that).to receive('width').and_return(2)
64
+ allow(that).to receive('height').and_return(1)
65
+ end
66
+
67
+ it 'crop images to min width and height' do
68
+ expect(this).to receive('crop!').with(1,1)
69
+ expect(that).to receive('crop!').with(1,1)
70
+ class_with_cezanne.send(:spot_differences_between, this, that)
71
+ end
72
+
73
+ context 'similar images' do
74
+
75
+ it 'return false' do
76
+ expect(this.picture).to receive('compare_channel').and_return([nil, Cezanne::SIMILARITY_THRESHOLD + 1])
77
+ expect(class_with_cezanne.send(:spot_differences_between, this, that)).to be false
78
+ end
79
+
80
+ end
81
+
82
+ context 'different images' do
83
+
84
+ it 'return true' do
85
+ expect(this.picture).to receive('compare_channel').and_return([nil, Cezanne::SIMILARITY_THRESHOLD - 1])
86
+ expect(class_with_cezanne.send(:spot_differences_between, this, that)).to be true
87
+ end
88
+
89
+ end
90
+ end
91
+
92
+ describe '#file_name_for' do
93
+
94
+ it 'contains page_name and browser' do
95
+ expect(class_with_cezanne.send(:file_name_for, 'fancy_page_name')).to eq('fancy_page_name_browser.gif')
96
+ end
97
+
98
+ end
99
+
100
+ describe '#mark_for_review' do
101
+
102
+ let(:screenshot) { image }
103
+
104
+ before(:each) do
105
+ allow(image).to receive('path').and_return('spec/images/page_name_browser.gif')
106
+ end
107
+
108
+ it 'moves screenshot to the diff folder' do
109
+ expect(local_files).to receive('path_for').with(:diff).and_return('spec/images/different.gif')
110
+ class_with_cezanne.send(:mark_for_review, screenshot)
111
+ expect(File.exists?('spec/images/different.gif')).to be true
112
+ end
113
+
114
+ after(:each) do
115
+ FileUtils.mv('spec/images/different.gif', 'spec/images/page_name_browser.gif')
116
+ end
117
+
118
+ end
119
+
120
+
121
+ describe '#mark_as_new' do
122
+
123
+ let(:screenshot) { image }
124
+
125
+ before(:each) do
126
+ allow(image).to receive('path').and_return('spec/images/page_name_browser.gif')
127
+ end
128
+
129
+ it 'moves screenshot to the new folder' do
130
+ expect(local_files).to receive('path_for').with(:new).and_return('spec/images/new.gif')
131
+ class_with_cezanne.send(:mark_as_new, screenshot)
132
+ expect(File.exists?('spec/images/new.gif')).to be true
133
+ end
134
+
135
+ after(:each) do
136
+ FileUtils.mv('spec/images/new.gif', 'spec/images/page_name_browser.gif')
137
+ end
138
+
139
+ end
140
+
141
+ describe '#image' do
142
+
143
+ before(:each) do
144
+ allow(class_with_cezanne).to receive('image').and_call_original
145
+ end
146
+
147
+ it 'return a Cezanne::Image' do
148
+ path = 'spec/images/page_name_browser.gif'
149
+ expect(class_with_cezanne.send(:image, path)).to be_instance_of(Cezanne::Image)
150
+ end
151
+
152
+ end
153
+
154
+ describe '#check_visual_regression_for' do
155
+
156
+ before(:each) do
157
+ allow(class_with_cezanne).to receive('get_reference_screenshot_for').and_return(Cezanne::Image.new('spec/images/page_name_browser.gif'))
158
+ end
159
+
160
+ context 'succesful match' do
161
+
162
+ it 'does not raise an error' do
163
+ allow(class_with_cezanne).to receive('take_screenshot').and_return(Cezanne::Image.new('spec/images/page_name_browser.gif'))
164
+ expect { class_with_cezanne.check_visual_regression_for 'page_name' }.not_to raise_error
165
+ end
166
+
167
+ end
168
+
169
+ context 'failed match' do
170
+
171
+ let(:screenshot) { Cezanne::Image.new('spec/images/page_name_2_browser.gif') }
172
+
173
+ before(:each) do
174
+ allow(class_with_cezanne).to receive('take_screenshot').and_return(screenshot)
175
+ allow(class_with_cezanne).to receive('mark_for_review')
176
+ end
177
+
178
+ it 'raise a <did not match> error' do
179
+ expect { class_with_cezanne.check_visual_regression_for('page_name') }.to raise_error(/didn't match/)
180
+ end
181
+
182
+ it 'mark the screenshot for review' do
183
+ expect(class_with_cezanne).to receive('mark_for_review').with(screenshot)
184
+ begin
185
+ class_with_cezanne.check_visual_regression_for('page_name')
186
+ rescue
187
+ end
188
+ end
189
+ end
190
+
191
+ context 'new screenshot' do
192
+
193
+ let(:screenshot) { Cezanne::Image.new('spec/images/page_name_browser.gif') }
194
+
195
+ before(:each) do
196
+ allow(class_with_cezanne).to receive('get_reference_screenshot_for').and_return(false)
197
+ allow(class_with_cezanne).to receive('take_screenshot').and_return(screenshot)
198
+ allow(class_with_cezanne).to receive('mark_as_new')
199
+ end
200
+
201
+ it 'raise a <new> error' do
202
+ expect { class_with_cezanne.check_visual_regression_for('page_name') }.to raise_error(/new screenshot/)
203
+ end
204
+
205
+ it 'mark the screenshot as new' do
206
+ expect(class_with_cezanne).to receive('mark_as_new').with(screenshot)
207
+ begin
208
+ class_with_cezanne.check_visual_regression_for('page_name')
209
+ rescue
210
+ end
211
+ end
212
+
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,9 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>DIFFERENT</title>
5
+ </head>
6
+ <body>
7
+ <img src="page_name_browser.gif" />
8
+ </body>
9
+ </html>
@@ -0,0 +1,9 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>NEW</title>
5
+ </head>
6
+ <body>
7
+ <img src="page_name_2_browser.gif" />
8
+ </body>
9
+ </html>
Binary file
Binary file
@@ -0,0 +1,9 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>SIMILAR</title>
5
+ </head>
6
+ <body>
7
+ <img src="page_name_browser.gif" />
8
+ </body>
9
+ </html>
@@ -0,0 +1,6 @@
1
+ require 'cezanne'
2
+
3
+ RSpec.configure do |config|
4
+ end
5
+
6
+
metadata ADDED
@@ -0,0 +1,189 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cezanne
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Sky Haiku
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
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'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: capybara
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: selenium-webdriver
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rmagick
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: dropscreen
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Let Cezanne help you make sure your views look alright
126
+ email:
127
+ - skyhaikuteam@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".gitignore"
133
+ - Gemfile
134
+ - LICENSE.txt
135
+ - README.md
136
+ - Rakefile
137
+ - cezanne.gemspec
138
+ - lib/cezanne.rb
139
+ - lib/cezanne/comparison.rb
140
+ - lib/cezanne/image.rb
141
+ - lib/cezanne/local_files.rb
142
+ - lib/cezanne/remote_files.rb
143
+ - lib/cezanne/rspec.rb
144
+ - lib/cezanne/version.rb
145
+ - spec/cezanne_filesystem_spec.rb
146
+ - spec/cezanne_image_spec.rb
147
+ - spec/cezanne_rspec_spec.rb
148
+ - spec/cezanne_spec.rb
149
+ - spec/images/different.html
150
+ - spec/images/new.html
151
+ - spec/images/page_name_2_browser.gif
152
+ - spec/images/page_name_browser.gif
153
+ - spec/images/similar.html
154
+ - spec/spec_helper.rb
155
+ homepage: ''
156
+ licenses:
157
+ - MIT
158
+ metadata: {}
159
+ post_install_message:
160
+ rdoc_options: []
161
+ require_paths:
162
+ - lib
163
+ required_ruby_version: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ required_rubygems_version: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ requirements: []
174
+ rubyforge_project:
175
+ rubygems_version: 2.2.2
176
+ signing_key:
177
+ specification_version: 4
178
+ summary: Visual regression testing tool
179
+ test_files:
180
+ - spec/cezanne_filesystem_spec.rb
181
+ - spec/cezanne_image_spec.rb
182
+ - spec/cezanne_rspec_spec.rb
183
+ - spec/cezanne_spec.rb
184
+ - spec/images/different.html
185
+ - spec/images/new.html
186
+ - spec/images/page_name_2_browser.gif
187
+ - spec/images/page_name_browser.gif
188
+ - spec/images/similar.html
189
+ - spec/spec_helper.rb