kontrast 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +262 -0
- data/Rakefile +2 -0
- data/bin/kontrast +111 -0
- data/lib/kontrast.rb +97 -0
- data/lib/kontrast/config/template.rb +27 -0
- data/lib/kontrast/configuration.rb +124 -0
- data/lib/kontrast/exceptions.rb +5 -0
- data/lib/kontrast/gallery/template.erb +76 -0
- data/lib/kontrast/gallery_creator.rb +164 -0
- data/lib/kontrast/image_handler.rb +119 -0
- data/lib/kontrast/runner.rb +141 -0
- data/lib/kontrast/selenium_handler.rb +84 -0
- data/lib/kontrast/test_builder.rb +25 -0
- data/lib/kontrast/version.rb +3 -0
- data/spec/configuration_spec.rb +53 -0
- data/spec/gallery_creator_spec.rb +105 -0
- data/spec/image_handler_spec.rb +52 -0
- data/spec/runner_spec.rb +37 -0
- data/spec/spec_helper.rb +44 -0
- data/spec/test_builder_spec.rb +52 -0
- metadata +202 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ccae0e8fea2906d0f534b11feee35bd3690fc4d2
|
4
|
+
data.tar.gz: 0d94b6a934294b8ffb3e480abceb09f5263e637d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b36e5e0f5d4edf9945f7fe6183b3a8accb2ddcbf1bbe29ded50ce0f236c7a9735e4e34e72ba0addfeaec46e3ec807f38753920401bcfaaa3be53f660133e8d35
|
7
|
+
data.tar.gz: a011155d29e1817de408fb029941856721be1fc05f2e02e1f0afdffe7b25def4b7bff43d92687f5c8952044d18a7fa4f67272037c399540f9b6def91d99c892a
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Ilya Rubnich
|
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,262 @@
|
|
1
|
+
# Kontrast
|
2
|
+
|
3
|
+
An automated testing tool for comparing visual differences between two versions of a website.
|
4
|
+
|
5
|
+
Kontrast lets you build a test suite to run against your test and production websites. It uses [Selenium](http://www.seleniumhq.org/) to take screenshots and [ImageMagick](http://www.imagemagick.org/) to compare them. Kontrast then produces a detailed gallery of its test results.
|
6
|
+
|
7
|
+
## Prerequisites
|
8
|
+
|
9
|
+
1. Install ImageMagick. You can do this on OS X via brew with:
|
10
|
+
|
11
|
+
$ brew install imagemagick
|
12
|
+
|
13
|
+
2. Make sure you have Firefox or a different Selenium-compatible browser installed. By default, Firefox is used.
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
Add this line to your application's Gemfile:
|
18
|
+
|
19
|
+
gem 'kontrast'
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
$ bundle
|
24
|
+
|
25
|
+
Or install it yourself as:
|
26
|
+
|
27
|
+
$ gem install kontrast
|
28
|
+
|
29
|
+
Lastly, generate the config file:
|
30
|
+
|
31
|
+
$ kontrast generate_config
|
32
|
+
|
33
|
+
If you're in Rails, the config file will be generated in `config/initializers/kontrast.rb`.
|
34
|
+
Otherwise, the config file will be generated in your current directory.
|
35
|
+
|
36
|
+
## Basic Configuration
|
37
|
+
|
38
|
+
Here's all the config you need to get started:
|
39
|
+
|
40
|
+
Kontrast.configure do |config|
|
41
|
+
# Set your test and production domains
|
42
|
+
config.test_domain = "http://localhost:3000"
|
43
|
+
config.production_domain = "http://www.example.com"
|
44
|
+
|
45
|
+
# Build your test suite
|
46
|
+
# These pages will open in a 1280px-wide browser
|
47
|
+
config.pages(1280) do |page|
|
48
|
+
page.home "/"
|
49
|
+
page.about "/about"
|
50
|
+
end
|
51
|
+
|
52
|
+
# These pages will open in a 320px-wide browser
|
53
|
+
config.pages(320) do |page|
|
54
|
+
page.home "/"
|
55
|
+
page.about "/about"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
## Basic Usage
|
60
|
+
Run Kontrast (use `bundle exec` and omit the --config flag if you're within a Rails app):
|
61
|
+
|
62
|
+
$ kontrast local_run --config ./kontrast_config.rb
|
63
|
+
...
|
64
|
+
...
|
65
|
+
...
|
66
|
+
Kontrast is all done!
|
67
|
+
You can find the gallery at: /tmp/shots/1410309651/gallery/gallery.html
|
68
|
+
|
69
|
+
Review the gallery in your Favorite Browser:
|
70
|
+
|
71
|
+
$ open /tmp/shots/1410309651/gallery/gallery.html
|
72
|
+
|
73
|
+
## Parallelized Usage
|
74
|
+
We designed Kontrast from the very beginning to work with multiple nodes. At Harry's, we use CircleCI for testing and Kontrast works perfectly with CircleCI's multi-container features.
|
75
|
+
|
76
|
+
### Method of Action
|
77
|
+
|
78
|
+
Because we ultimately need to generate a gallery with all test results from all given nodes, Kontrast uploads the test images it creates plus a per-node manifest file to S3. After all the tests have run, a single node downloads the manifest files and parses them to create a single gallery.
|
79
|
+
|
80
|
+
Here's how to get set up:
|
81
|
+
|
82
|
+
### 1. Enable Parallelization
|
83
|
+
|
84
|
+
config.run_parallel = true
|
85
|
+
|
86
|
+
### 2. Configure Nodes
|
87
|
+
Set how many nodes you have in total and the zero-based index of the current node. Kontrast will automatically split up tests among these nodes.
|
88
|
+
|
89
|
+
config.total_nodes = 6
|
90
|
+
config.current_node = 2
|
91
|
+
|
92
|
+
### 3. Configure Remote Options
|
93
|
+
Set your S3 details:
|
94
|
+
|
95
|
+
config.aws_bucket = "kontrast-test-results"
|
96
|
+
config.aws_key = ENV['AWS_KEY']
|
97
|
+
config.aws_secret = ENV['AWS_SECRET']
|
98
|
+
|
99
|
+
Set the **local** path where output images will be stored before they are uploaded to S3. This is also where the gallery will be saved on the node that runs the `make_gallery` command. This path will be created if it doesn't already exist.
|
100
|
+
|
101
|
+
config.local_path = "tmp/kontrast"
|
102
|
+
|
103
|
+
Set the **remote** path relative to your S3 bucket's root where Kontrast's output files will be uploaded to. It should be unique to every test.
|
104
|
+
|
105
|
+
config.remote_path = "artifacts.#{ENV['BUILD_NUMBER']}"
|
106
|
+
|
107
|
+
### 4. Run the Tests
|
108
|
+
This command should run in parallel on every node. Use `bundle exec` and omit the --config flag if your app is `bundle`'d along with Rails.
|
109
|
+
|
110
|
+
$ kontrast run_tests --config /path/to/config.rb
|
111
|
+
|
112
|
+
### 5. Create the Gallery
|
113
|
+
This command should only run on one node after all the other nodes have completed the previous command. Use `bundle exec` and omit the --config flag if your app is `bundle`'d along with Rails.
|
114
|
+
|
115
|
+
$ kontrast make_gallery --config /path/to/config.rb
|
116
|
+
|
117
|
+
### 6. Review Your Results
|
118
|
+
At this point, the gallery should be saved to `config.local_path` and uploaded to `config.remote_path`. Check it out in your Favorite Browser.
|
119
|
+
|
120
|
+
### Sample circle.yml
|
121
|
+
Here's an example of how to run Kontrast within a Rails app using CircleCI:
|
122
|
+
|
123
|
+
test:
|
124
|
+
post:
|
125
|
+
- bundle exec rails server:
|
126
|
+
background: true
|
127
|
+
parallel: true
|
128
|
+
- bundle exec kontrast run_tests:
|
129
|
+
parallel: true
|
130
|
+
- bundle exec kontrast make_gallery
|
131
|
+
|
132
|
+
## Advanced Configuration
|
133
|
+
|
134
|
+
### Test Suite
|
135
|
+
|
136
|
+
#### fail_build
|
137
|
+
If you want Kontrast to exit with an error code if it finds any diffs, use this option:
|
138
|
+
|
139
|
+
config.fail_build = true
|
140
|
+
|
141
|
+
### Selenium Driver
|
142
|
+
#### browser_driver
|
143
|
+
Choose which Selenium driver you'd like to use. Kontrast has only been tested on the default Firefox driver but we would love feedback and/or pull requests for other drivers.
|
144
|
+
|
145
|
+
config.browser_driver = "firefox"
|
146
|
+
|
147
|
+
#### browser_profile
|
148
|
+
You may set a driver's profile options in this hash.
|
149
|
+
|
150
|
+
config.browser_profile = {
|
151
|
+
"general.useragent.override" => "Some Cool Kontrast User Agent",
|
152
|
+
"image.animation_mode" => "none"
|
153
|
+
}
|
154
|
+
|
155
|
+
### Image Comparisons
|
156
|
+
#### distortion_metric
|
157
|
+
See [http://www.imagemagick.org/RMagick/doc/constants.html#MetricType]() for available values.
|
158
|
+
|
159
|
+
config.distortion_metric = "MeanAbsoluteErrorMetric"
|
160
|
+
|
161
|
+
#### highlight_color
|
162
|
+
The ImageMagick comparison tool emphasizes differences with this color.
|
163
|
+
Valid options are an RMagick color name or pixel.
|
164
|
+
|
165
|
+
config.highlight_color = "blue"
|
166
|
+
|
167
|
+
#### lowlight_color
|
168
|
+
The ImageMagick comparison tool deemphasizes differences with this color.
|
169
|
+
Valid options are an RMagick color name or pixel.
|
170
|
+
|
171
|
+
config.lowlight_color = "rgba(255, 255, 255, 0.3)"
|
172
|
+
|
173
|
+
### Hooks
|
174
|
+
To make Kontrast even more powerful, we provided a set of hooks that you can use in your configuration.
|
175
|
+
|
176
|
+
#### before_run
|
177
|
+
Runs before the entire suite.
|
178
|
+
|
179
|
+
config.before_run do
|
180
|
+
WebMock.disable!
|
181
|
+
end
|
182
|
+
|
183
|
+
#### after_run
|
184
|
+
Runs after the entire suite.
|
185
|
+
|
186
|
+
config.after_run do
|
187
|
+
WebMock.enable!
|
188
|
+
end
|
189
|
+
|
190
|
+
#### before_gallery
|
191
|
+
Runs before the gallery creation step.
|
192
|
+
|
193
|
+
config.before_gallery do
|
194
|
+
WebMock.disable!
|
195
|
+
end
|
196
|
+
|
197
|
+
#### after_gallery
|
198
|
+
Runs after the gallery creation step.
|
199
|
+
|
200
|
+
config.after_gallery do |diffs, gallery_path|
|
201
|
+
# diffs is a hash containing all the differences that Kontrast found in your test suite
|
202
|
+
# gallery_path is where Kontrast saved the gallery
|
203
|
+
end
|
204
|
+
|
205
|
+
#### before_screenshot
|
206
|
+
Runs on every test before Selenium takes a screenshot.
|
207
|
+
|
208
|
+
config.before_screenshot do |test_driver, production_driver, test_info|
|
209
|
+
# test_driver and production_driver are instances of Selenium::WebDriver that you can control
|
210
|
+
# test_info is a hash with the current test's name and width
|
211
|
+
end
|
212
|
+
|
213
|
+
#### after_screenshot
|
214
|
+
Runs on every test after Selenium takes a screenshot.
|
215
|
+
|
216
|
+
config.after_screenshot do |test_driver, production_driver, test_info|
|
217
|
+
# same variables are available as with before_screenshot
|
218
|
+
end
|
219
|
+
|
220
|
+
## Customizing Kontrast
|
221
|
+
Kontrast's hooks allow you to insert custom functionality into many parts of the test suite. Here are some examples of how we use hooks at Harry's:
|
222
|
+
|
223
|
+
### Integrating with HipChat
|
224
|
+
Once a build finishes, we let HipChat know if Kontrast found any diffs using the `hipchat` gem:
|
225
|
+
|
226
|
+
config.after_gallery do |diffs, gallery_path|
|
227
|
+
hipchat_room = "Kontrast Results"
|
228
|
+
hipchat_user = "KontrastBot"
|
229
|
+
|
230
|
+
if !diffs.empty?
|
231
|
+
msg = "Kontrast Diffs: #{diffs.keys.join(', ')}. Don't push to production without reviewing these. You can find the gallery at #{gallery_path}."
|
232
|
+
client = HipChat::Client.new(ENV["HIPCHAT_TOKEN"])
|
233
|
+
client[hipchat_room].send(hipchat_user, msg, :color => "red")
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
### Setting Cookies
|
238
|
+
Testing our cart page required a bit more setup before we could take a screenshot of it:
|
239
|
+
|
240
|
+
config.before_screenshot do |test_driver, production_driver, test|
|
241
|
+
if test[:name] == "cart"
|
242
|
+
# prepare our cookie value
|
243
|
+
cookie_value = super_secret_magic_cart_cookie
|
244
|
+
|
245
|
+
# write cookies using Mootools
|
246
|
+
# http://mootools.net/docs/core/Utilities/Cookie
|
247
|
+
test_driver.execute_script("Cookie.write('cart', '#{cookie_value}');")
|
248
|
+
production_driver.execute_script("Cookie.write('cart', '#{cookie_value}');")
|
249
|
+
|
250
|
+
# refresh the page
|
251
|
+
test_driver.navigate.refresh
|
252
|
+
production_driver.navigate.refresh
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
## Contributing
|
257
|
+
|
258
|
+
1. Fork it
|
259
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
260
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
261
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
262
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bin/kontrast
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#######################################
|
4
|
+
# This is the entry point to Kontrast #
|
5
|
+
#######################################
|
6
|
+
|
7
|
+
begin
|
8
|
+
require "rubygems"
|
9
|
+
require "kontrast"
|
10
|
+
rescue LoadError => e
|
11
|
+
puts "Could not load Kontrast."
|
12
|
+
raise e
|
13
|
+
end
|
14
|
+
require "thor"
|
15
|
+
|
16
|
+
module Kontrast
|
17
|
+
class CLI < Thor
|
18
|
+
class_option :config
|
19
|
+
|
20
|
+
desc "run_tests", "Run Kontrast test suite"
|
21
|
+
def run_tests
|
22
|
+
load_config(options[:config])
|
23
|
+
Kontrast.run
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "make_gallery --result-path PATH", "Create gallery given an optional local path of test results"
|
27
|
+
option :result_path
|
28
|
+
def make_gallery
|
29
|
+
load_config(options[:config])
|
30
|
+
|
31
|
+
# We're only allowed to give no path in the remote case
|
32
|
+
if options[:result_path].nil? && !Kontrast.configuration.run_parallel
|
33
|
+
raise GalleryException.new("You can't omit --result-path when running in local mode")
|
34
|
+
end
|
35
|
+
|
36
|
+
result = Kontrast.make_gallery(options[:result_path])
|
37
|
+
abort if !result && Kontrast.configuration.fail_build
|
38
|
+
end
|
39
|
+
|
40
|
+
# todo: option to specify an output path
|
41
|
+
desc "local_run", "Run Kontrast locally"
|
42
|
+
def local_run
|
43
|
+
load_config(options[:config])
|
44
|
+
|
45
|
+
# Make sure config run_parallel is set to false
|
46
|
+
if Kontrast.configuration.run_parallel
|
47
|
+
raise ConfigurationException.new("You can't run in parallel locally")
|
48
|
+
end
|
49
|
+
|
50
|
+
# Run Kontrast
|
51
|
+
Kontrast.run
|
52
|
+
result = Kontrast.make_gallery(Kontrast.path)
|
53
|
+
|
54
|
+
# Print the gallery path
|
55
|
+
puts "Kontrast is all done!"
|
56
|
+
puts "You can find the gallery at: #{Kontrast.path}/gallery/gallery.html"
|
57
|
+
|
58
|
+
# Quit with an error code if appropriate
|
59
|
+
abort if !result && Kontrast.configuration.fail_build
|
60
|
+
end
|
61
|
+
|
62
|
+
desc "generate_config", "Generate a Kontrast configuration file"
|
63
|
+
def generate_config
|
64
|
+
template = File.read(Kontrast.root + '/lib/kontrast/config/template.rb')
|
65
|
+
|
66
|
+
if Kontrast.in_rails?
|
67
|
+
target_file = './config/initializers/kontrast.rb'
|
68
|
+
else
|
69
|
+
target_file = './kontrast_config.rb'
|
70
|
+
end
|
71
|
+
|
72
|
+
File.open(target_file, 'w') do |f|
|
73
|
+
f.write(template)
|
74
|
+
end
|
75
|
+
|
76
|
+
puts "Created a Kontrast config file at: #{target_file}"
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
def load_config(config)
|
81
|
+
# Let's check if we're within Rails.
|
82
|
+
if !Kontrast.in_rails?
|
83
|
+
begin
|
84
|
+
require config
|
85
|
+
rescue TypeError => e
|
86
|
+
raise ConfigurationException.new("Error parsing the config flag '#{config}'")
|
87
|
+
rescue LoadError => e
|
88
|
+
raise ConfigurationException.new("Could not load '#{config}'")
|
89
|
+
rescue Exception => e
|
90
|
+
raise ConfigurationException.new("An unexpected error occurred while trying to load the given config file: #{e.inspect}")
|
91
|
+
end
|
92
|
+
else
|
93
|
+
# Load Rails environment
|
94
|
+
# We will assume the config was loaded from an initializer
|
95
|
+
require './config/environment'
|
96
|
+
end
|
97
|
+
|
98
|
+
# Check that we actually got a configuration block
|
99
|
+
if !Kontrast.configuration
|
100
|
+
raise ConfigurationException.new("No configuration has been loaded")
|
101
|
+
end
|
102
|
+
|
103
|
+
# Make sure we have the bare minimum configuration to continue
|
104
|
+
Kontrast.configuration.validate
|
105
|
+
|
106
|
+
return true
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
Kontrast::CLI.start(ARGV)
|
data/lib/kontrast.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
# Dependencies
|
2
|
+
require "fog"
|
3
|
+
require "bundler"
|
4
|
+
|
5
|
+
# Load classes
|
6
|
+
require "kontrast/exceptions"
|
7
|
+
require "kontrast/configuration"
|
8
|
+
require "kontrast/test_builder"
|
9
|
+
require "kontrast/selenium_handler"
|
10
|
+
require "kontrast/image_handler"
|
11
|
+
require "kontrast/gallery_creator"
|
12
|
+
require "kontrast/runner"
|
13
|
+
|
14
|
+
module Kontrast
|
15
|
+
class << self
|
16
|
+
@@path = nil
|
17
|
+
|
18
|
+
def root
|
19
|
+
File.expand_path('../..', __FILE__)
|
20
|
+
end
|
21
|
+
|
22
|
+
def in_rails?
|
23
|
+
# Logic: Rails uses Bundler, so if the Bundler environment contains Rails, return true.
|
24
|
+
# If there's any error whatsoever, return false.
|
25
|
+
begin
|
26
|
+
Bundler.environment.current_dependencies.each do |dep|
|
27
|
+
return true if dep.name == "rails"
|
28
|
+
end
|
29
|
+
rescue Exception => e
|
30
|
+
# Quietly ignore any exceptions
|
31
|
+
end
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
|
35
|
+
def path
|
36
|
+
return @@path if @@path
|
37
|
+
|
38
|
+
if Kontrast.configuration.run_parallel
|
39
|
+
@@path = FileUtils.mkdir_p(Kontrast.configuration.local_path).join('')
|
40
|
+
elsif Kontrast.in_rails?
|
41
|
+
@@path = FileUtils.mkdir_p(Rails.root + "tmp/shots/#{Time.now.to_i}").join('')
|
42
|
+
else
|
43
|
+
@@path = FileUtils.mkdir_p("/tmp/shots/#{Time.now.to_i}").join('')
|
44
|
+
end
|
45
|
+
|
46
|
+
return @@path
|
47
|
+
end
|
48
|
+
|
49
|
+
def fog
|
50
|
+
return Fog::Storage.new({
|
51
|
+
:provider => 'AWS',
|
52
|
+
:aws_access_key_id => Kontrast.configuration.aws_key,
|
53
|
+
:aws_secret_access_key => Kontrast.configuration.aws_secret
|
54
|
+
})
|
55
|
+
end
|
56
|
+
|
57
|
+
def run
|
58
|
+
beginning_time = Time.now
|
59
|
+
|
60
|
+
begin
|
61
|
+
# Call "before" hook
|
62
|
+
Kontrast.configuration.before_run
|
63
|
+
|
64
|
+
runner = Runner.new
|
65
|
+
runner.run
|
66
|
+
ensure
|
67
|
+
# Call "after" hook
|
68
|
+
Kontrast.configuration.after_run
|
69
|
+
end
|
70
|
+
|
71
|
+
end_time = Time.now
|
72
|
+
puts "Time elapsed: #{(end_time - beginning_time)} seconds"
|
73
|
+
end
|
74
|
+
|
75
|
+
def make_gallery(result_path = nil)
|
76
|
+
puts "Creating gallery..."
|
77
|
+
gallery_info = {}
|
78
|
+
begin
|
79
|
+
# Call "before" hook
|
80
|
+
Kontrast.configuration.before_gallery
|
81
|
+
|
82
|
+
gallery_creator = GalleryCreator.new(result_path)
|
83
|
+
if Kontrast.configuration.run_parallel
|
84
|
+
gallery_info = gallery_creator.create_gallery(Kontrast.configuration.local_path)
|
85
|
+
else
|
86
|
+
gallery_info = gallery_creator.create_gallery(result_path)
|
87
|
+
end
|
88
|
+
ensure
|
89
|
+
# Call "after" hook
|
90
|
+
Kontrast.configuration.after_gallery(gallery_info[:diffs], gallery_info[:path])
|
91
|
+
end
|
92
|
+
|
93
|
+
# Return based on if we have diffs or not
|
94
|
+
return gallery_info[:diffs].empty?
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|