kontrast 0.2.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +135 -96
- data/bin/kontrast +9 -5
- data/lib/kontrast.rb +17 -5
- data/lib/kontrast/api_client.rb +56 -0
- data/lib/kontrast/api_endpoint_comparator.rb +126 -0
- data/lib/kontrast/api_endpoint_runner.rb +99 -0
- data/lib/kontrast/api_endpoint_test.rb +8 -0
- data/lib/kontrast/configuration.rb +36 -7
- data/lib/kontrast/exceptions.rb +2 -1
- data/lib/kontrast/gallery/template.erb +152 -21
- data/lib/kontrast/gallery_creator.rb +105 -47
- data/lib/kontrast/global_runner.rb +121 -0
- data/lib/kontrast/image_helper.rb +63 -0
- data/lib/kontrast/image_uploader.rb +18 -0
- data/lib/kontrast/page_comparator.rb +46 -0
- data/lib/kontrast/page_runner.rb +95 -0
- data/lib/kontrast/page_test.rb +32 -0
- data/lib/kontrast/selenium_handler.rb +18 -7
- data/lib/kontrast/spec.rb +21 -0
- data/lib/kontrast/spec_builder.rb +54 -0
- data/lib/kontrast/test.rb +27 -0
- data/lib/kontrast/test_builder.rb +25 -9
- data/lib/kontrast/test_suite.rb +42 -0
- data/lib/kontrast/thumbnail_creator.rb +18 -0
- data/lib/kontrast/version.rb +1 -1
- data/spec/api_endpoint_comparator_spec.rb +125 -0
- data/spec/configuration_spec.rb +19 -0
- data/spec/gallery_creator_spec.rb +26 -20
- data/spec/{image_handler_spec.rb → global_runner_spec.rb} +17 -12
- data/spec/page_comparator_spec.rb +31 -0
- data/spec/page_runner_spec.rb +45 -0
- data/spec/spec_builder_spec.rb +32 -0
- data/spec/support/fixtures/image.jpg +0 -0
- data/spec/support/fixtures/image_clone.jpg +0 -0
- data/spec/support/fixtures/img1.jpg +0 -0
- data/spec/support/fixtures/img2.jpg +0 -0
- data/spec/support/fixtures/other_image.jpg +0 -0
- data/spec/test_builder_spec.rb +6 -3
- data/spec/test_spec.rb +53 -0
- data/spec/test_suite_spec.rb +56 -0
- metadata +91 -30
- data/lib/kontrast/image_handler.rb +0 -119
- data/lib/kontrast/runner.rb +0 -141
- data/spec/runner_spec.rb +0 -37
@@ -12,7 +12,7 @@ module Kontrast
|
|
12
12
|
def create_gallery(output_dir)
|
13
13
|
begin
|
14
14
|
@gallery_dir = FileUtils.mkdir_p("#{output_dir}/gallery").join('')
|
15
|
-
rescue
|
15
|
+
rescue StandardError => e
|
16
16
|
raise GalleryException.new("An unexpected error occurred while trying to create the gallery's output directory: #{e.inspect}")
|
17
17
|
end
|
18
18
|
|
@@ -46,7 +46,7 @@ module Kontrast
|
|
46
46
|
|
47
47
|
def generate_html(files, diffs)
|
48
48
|
# Template variables
|
49
|
-
|
49
|
+
groups, without_diffs, with_diffs = parse_directories(files, diffs)
|
50
50
|
|
51
51
|
# HTML
|
52
52
|
template = File.read(Kontrast.root + '/lib/kontrast/gallery/template.erb')
|
@@ -83,66 +83,124 @@ module Kontrast
|
|
83
83
|
}
|
84
84
|
end
|
85
85
|
|
86
|
+
def test_name_from_dir(dir)
|
87
|
+
# dir is a string prefixed with a group name:
|
88
|
+
# '1280_home' or '2x_home_screen'
|
89
|
+
return dir.split('_')[1..-1].join('_')
|
90
|
+
end
|
91
|
+
|
92
|
+
def base_path
|
93
|
+
# This determines where to display images from in the gallery
|
94
|
+
if Kontrast.configuration.run_parallel
|
95
|
+
# Build the remote path to S3
|
96
|
+
return "https://#{Kontrast.configuration.aws_bucket}.s3.amazonaws.com/#{Kontrast.configuration.remote_path}"
|
97
|
+
else
|
98
|
+
return ".."
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def variants_for_page(directory, diffs)
|
103
|
+
# Return a hash that will be used in the erb template to show the
|
104
|
+
# diffs for a given test.
|
105
|
+
variants = []
|
106
|
+
['test', 'production', 'diff'].each do |type|
|
107
|
+
variant = {
|
108
|
+
image: "#{base_path}/#{directory}/" + type + ".png",
|
109
|
+
thumb: "#{base_path}/#{directory}/" + type + "_thumb.png",
|
110
|
+
domain: type,
|
111
|
+
type: 'page',
|
112
|
+
}
|
113
|
+
if type == 'diff' && diffs[directory]
|
114
|
+
variant[:diff_amt] = diffs[directory]["diff"]
|
115
|
+
end
|
116
|
+
variants << variant
|
117
|
+
end
|
118
|
+
|
119
|
+
return variants
|
120
|
+
end
|
121
|
+
|
122
|
+
def variants_for_api_endpoint(directory, diffs, files)
|
123
|
+
# Return a hash that will be used in the erb template to show the
|
124
|
+
# diffs for a given test.
|
125
|
+
variants = []
|
126
|
+
['test', 'production', 'diff'].each do |type|
|
127
|
+
variant = {
|
128
|
+
file: "#{base_path}/#{directory}/#{type}.json",
|
129
|
+
domain: type,
|
130
|
+
type: 'api_endpoint',
|
131
|
+
diff_amt: 0,
|
132
|
+
}
|
133
|
+
if diffs[directory]
|
134
|
+
variant[:diff_amt] = 1
|
135
|
+
end
|
136
|
+
|
137
|
+
# Get all images
|
138
|
+
image_files = files.select { |file_name|
|
139
|
+
file_name.match /#{directory}\/#{type}_\d+.(jpg|png)/
|
140
|
+
}.map { |file_name|
|
141
|
+
name_without_extension = file_name.split('.')[0..-2].join('.')
|
142
|
+
{
|
143
|
+
image: "#{base_path}/#{file_name}",
|
144
|
+
thumb: "#{base_path}/#{name_without_extension}_thumb.png",
|
145
|
+
}
|
146
|
+
}
|
147
|
+
variant[:images] = image_files
|
148
|
+
variants << variant
|
149
|
+
end
|
150
|
+
|
151
|
+
return variants
|
152
|
+
end
|
153
|
+
|
86
154
|
# This function just turns the list of files and diffs into a hash that the gallery
|
87
155
|
# creator can insert into a template. See an example of the created hash below.
|
88
156
|
def parse_directories(files, diffs)
|
89
157
|
files.sort!
|
90
158
|
|
91
|
-
|
92
|
-
|
159
|
+
# Initialize those hashes, where each key will map to hash, in wich
|
160
|
+
# each key maps to an array:
|
161
|
+
# {
|
162
|
+
# key1: {
|
163
|
+
# },
|
164
|
+
# key2: {
|
165
|
+
# },
|
166
|
+
# }
|
167
|
+
#
|
168
|
+
without_diffs = Hash.new { |h,k| h[k] = {} }
|
169
|
+
with_diffs = Hash.new { |h,k| h[k] = {} }
|
93
170
|
|
94
|
-
|
95
|
-
|
96
|
-
sizes.each { |size|
|
97
|
-
dirs[size] = {}
|
98
|
-
|
99
|
-
# Get all directories for this size
|
100
|
-
tests_for_size = directories.select { |d| d.index(size + "_") == 0 }
|
101
|
-
tests_for_size.each do |dir|
|
102
|
-
array = dir.split('_')
|
103
|
-
array.delete_at(0)
|
104
|
-
test_name = array.join('_')
|
105
|
-
dirs[size][test_name] = {
|
106
|
-
variants: []
|
107
|
-
}
|
108
|
-
end
|
109
|
-
}
|
171
|
+
directories = files.map { |f| f.split('/').first }.uniq
|
172
|
+
groups = directories.map { |dir| dir.split('_').first }.uniq
|
110
173
|
|
111
|
-
# This determines where to display images from in the gallery
|
112
|
-
if Kontrast.configuration.run_parallel
|
113
|
-
# Build the remote path to S3
|
114
|
-
base_path = "https://#{Kontrast.configuration.aws_bucket}.s3.amazonaws.com/#{Kontrast.configuration.remote_path}"
|
115
|
-
else
|
116
|
-
base_path = ".."
|
117
|
-
end
|
118
174
|
|
119
175
|
# Fill in the files as variants
|
120
176
|
directories.each do |directory|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
#
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
177
|
+
group = directory.split('_')[0]
|
178
|
+
test_name = test_name_from_dir(directory)
|
179
|
+
|
180
|
+
# Determines the type of test by the presence of the diff.png
|
181
|
+
# file in the folder.
|
182
|
+
# Ideally the manifest file format would be different and
|
183
|
+
# include the test type with
|
184
|
+
if files.select { |file_name| file_name.start_with?(directory) }.any? { |file_name| file_name.include?('diff.png') }
|
185
|
+
variants = variants_for_page(directory, diffs)
|
186
|
+
else
|
187
|
+
variants = variants_for_api_endpoint(directory, diffs, files)
|
188
|
+
end
|
189
|
+
|
190
|
+
if diffs[directory]
|
191
|
+
with_diffs[group][test_name] = variants
|
192
|
+
else
|
193
|
+
without_diffs[group][test_name] = variants
|
136
194
|
end
|
137
195
|
end
|
138
196
|
|
139
|
-
return
|
197
|
+
return groups, without_diffs, with_diffs
|
140
198
|
|
141
199
|
# For reference
|
142
200
|
# gallery_format = {
|
143
201
|
# "1080" => {
|
144
|
-
# "name" =>
|
145
|
-
#
|
202
|
+
# "name" => [
|
203
|
+
# {
|
146
204
|
# image: "full_img_src",
|
147
205
|
# thumb: "thumb_src",
|
148
206
|
# domain: "production"
|
@@ -154,8 +212,8 @@ module Kontrast
|
|
154
212
|
# image: "diff_src",
|
155
213
|
# thumb: "diff_thumb_src",
|
156
214
|
# domain: "diff",
|
157
|
-
#
|
158
|
-
# }
|
215
|
+
# diff_amt: 0.1
|
216
|
+
# }
|
159
217
|
# }
|
160
218
|
# }
|
161
219
|
# }
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require "net/http"
|
3
|
+
|
4
|
+
module Kontrast
|
5
|
+
class GlobalRunner
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@page_runner = PageRunner.new
|
9
|
+
@api_endpont_runner = ApiEndpointRunner.new
|
10
|
+
@path = Kontrast.path
|
11
|
+
@current_node = 0
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
# Make sure the local server is running
|
16
|
+
wait_for_server
|
17
|
+
|
18
|
+
# Assign nodes
|
19
|
+
if Kontrast.configuration.run_parallel
|
20
|
+
total_nodes = Kontrast.configuration.total_nodes
|
21
|
+
@current_node = Kontrast.configuration.current_node
|
22
|
+
else
|
23
|
+
# Override the config for local use
|
24
|
+
total_nodes = 1
|
25
|
+
end
|
26
|
+
|
27
|
+
# Run both runners
|
28
|
+
@page_runner.run(total_nodes, @current_node)
|
29
|
+
@api_endpont_runner.run(total_nodes, @current_node)
|
30
|
+
|
31
|
+
# Create manifest
|
32
|
+
create_manifest
|
33
|
+
end
|
34
|
+
|
35
|
+
# The manifest is a per-node .json file that is used to create the gallery
|
36
|
+
# without having to download all assets from S3 to the test environment
|
37
|
+
def create_manifest
|
38
|
+
# Create manifest
|
39
|
+
puts "Creating manifest..."
|
40
|
+
if Kontrast.configuration.run_parallel
|
41
|
+
build = Kontrast.configuration.remote_path
|
42
|
+
else
|
43
|
+
build = nil
|
44
|
+
end
|
45
|
+
|
46
|
+
diffs = {}
|
47
|
+
diffs.merge!(@page_runner.diffs)
|
48
|
+
diffs.merge!(@api_endpont_runner.diffs)
|
49
|
+
|
50
|
+
# Set up structure
|
51
|
+
manifest = {
|
52
|
+
diffs: diffs,
|
53
|
+
files: []
|
54
|
+
}
|
55
|
+
|
56
|
+
# Dump directories
|
57
|
+
Dir.foreach(@path) do |subdir|
|
58
|
+
next if ['.', '..'].include?(subdir)
|
59
|
+
next if subdir.index('manifest_')
|
60
|
+
Dir.foreach("#{@path}/#{subdir}") do |img|
|
61
|
+
next if ['.', '..'].include?(img)
|
62
|
+
manifest[:files] << "#{subdir}/#{img}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
if Kontrast.configuration.run_parallel
|
67
|
+
# Upload manifest
|
68
|
+
Kontrast.fog.directories.get(Kontrast.configuration.aws_bucket).files.create(
|
69
|
+
key: "#{build}/manifest_#{@current_node}.json",
|
70
|
+
body: manifest.to_json
|
71
|
+
)
|
72
|
+
else
|
73
|
+
# Write manifest
|
74
|
+
File.open("#{@path}/manifest_#{@current_node}.json", 'w') do |outf|
|
75
|
+
outf.write(manifest.to_json)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
return manifest
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
def wait_for_server
|
84
|
+
# Test server
|
85
|
+
tries = 30
|
86
|
+
uri = URI(Kontrast.configuration.test_domain)
|
87
|
+
begin
|
88
|
+
Net::HTTP.get(uri)
|
89
|
+
rescue Errno::ECONNREFUSED => e
|
90
|
+
tries -= 1
|
91
|
+
if tries > 0
|
92
|
+
puts "Waiting for test server..."
|
93
|
+
sleep 2
|
94
|
+
retry
|
95
|
+
else
|
96
|
+
raise RunnerException.new("Could not reach the test server at '#{uri}'.")
|
97
|
+
end
|
98
|
+
rescue StandardError => e
|
99
|
+
raise RunnerException.new("An unexpected error occured while trying to reach the test server at '#{uri}': #{e.inspect}")
|
100
|
+
end
|
101
|
+
|
102
|
+
# Production server
|
103
|
+
tries = 30
|
104
|
+
uri = URI(Kontrast.configuration.production_domain)
|
105
|
+
begin
|
106
|
+
Net::HTTP.get(uri)
|
107
|
+
rescue Errno::ECONNREFUSED => e
|
108
|
+
tries -= 1
|
109
|
+
if tries > 0
|
110
|
+
puts "Waiting for production server..."
|
111
|
+
sleep 2
|
112
|
+
retry
|
113
|
+
else
|
114
|
+
raise RunnerException.new("Could not reach the production server at '#{uri}'.")
|
115
|
+
end
|
116
|
+
rescue StandardError => e
|
117
|
+
raise RunnerException.new("An unexpected error occured while trying to reach the production server at '#{uri}': #{e.inspect}")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "RMagick"
|
2
|
+
require "workers"
|
3
|
+
|
4
|
+
module Kontrast
|
5
|
+
|
6
|
+
class ImageHelper
|
7
|
+
def initialize(img1_path, img2_path)
|
8
|
+
@img1_path, @img2_path = img1_path, img2_path
|
9
|
+
@img1 = load_image(@img1_path)
|
10
|
+
@img2 = load_image(@img2_path)
|
11
|
+
@path = Kontrast.path
|
12
|
+
end
|
13
|
+
|
14
|
+
def reload_images
|
15
|
+
@img1 = load_image(@img1_path)
|
16
|
+
@img2 = load_image(@img2_path)
|
17
|
+
end
|
18
|
+
|
19
|
+
def load_image(path)
|
20
|
+
return Magick::Image.read(path).first
|
21
|
+
end
|
22
|
+
|
23
|
+
def crop(width)
|
24
|
+
# Let's not do anything if the images are already the same size
|
25
|
+
return if @img1.rows == @img2.rows
|
26
|
+
|
27
|
+
# Get max height of both images
|
28
|
+
max_height = [@img1.rows, @img2.rows].max
|
29
|
+
|
30
|
+
# Crop
|
31
|
+
Workers.map([@img1, @img2]) do |image|
|
32
|
+
image.extent(width, max_height).write(image.filename)
|
33
|
+
end
|
34
|
+
reload_images
|
35
|
+
end
|
36
|
+
|
37
|
+
# Uses the compare_channel function to highlight the differences between
|
38
|
+
# two images Docs:
|
39
|
+
# http://www.rubydoc.info/github/gemhome/rmagick/Magick%2FImage%3Acompare_channel
|
40
|
+
def compare(output_dir, output_file_name)
|
41
|
+
begin
|
42
|
+
distortion_metric = Magick.const_get(Kontrast.configuration.distortion_metric)
|
43
|
+
diff = @img1.compare_channel(@img2, distortion_metric) do |options|
|
44
|
+
options.highlight_color = Kontrast.configuration.highlight_color
|
45
|
+
options.lowlight_color = Kontrast.configuration.lowlight_color
|
46
|
+
end
|
47
|
+
|
48
|
+
output_path = "#{Kontrast.path}/#{output_dir}"
|
49
|
+
FileUtils.mkdir_p(output_path) # Just in case
|
50
|
+
diff.first.write(File.join(output_path, output_file_name))
|
51
|
+
|
52
|
+
# diff is an array, the last (second) value is the diff value,
|
53
|
+
# a float between 0 and 1, 0 being the same image, 1 being an
|
54
|
+
# entirely different image
|
55
|
+
return diff.last
|
56
|
+
rescue Magick::ImageMagickError => e
|
57
|
+
puts "Error comparing images: #{e.message}"
|
58
|
+
# 1 means that both images are different
|
59
|
+
return 1
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Kontrast
|
2
|
+
module ImageUploader
|
3
|
+
def upload_images(test)
|
4
|
+
worker_pool = Workers::Pool.new
|
5
|
+
worker_pool.resize(Kontrast.configuration.workers_pool_size)
|
6
|
+
|
7
|
+
Workers.map(Dir.entries("#{Kontrast.path}/#{test}"), pool: worker_pool) do |file|
|
8
|
+
next if ['.', '..'].include?(file)
|
9
|
+
Kontrast.fog.directories.get(Kontrast.configuration.aws_bucket).files.create(
|
10
|
+
key: "#{Kontrast.configuration.remote_path}/#{test}/#{file}",
|
11
|
+
body: File.open("#{Kontrast.path}/#{test}/#{file}"),
|
12
|
+
public: true
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
|
2
|
+
module Kontrast
|
3
|
+
class PageComparator
|
4
|
+
include Magick
|
5
|
+
attr_reader :diffs, :path
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@path = Kontrast.path
|
9
|
+
|
10
|
+
# This is where failed diffs will be stored
|
11
|
+
@diffs = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_image_path(test)
|
15
|
+
return "#{@path}/#{test}/test.png"
|
16
|
+
end
|
17
|
+
|
18
|
+
def production_image_path(test)
|
19
|
+
return "#{@path}/#{test}/production.png"
|
20
|
+
end
|
21
|
+
|
22
|
+
def diff(test)
|
23
|
+
|
24
|
+
image_helper = Kontrast::ImageHelper.new(
|
25
|
+
test_image_path(test),
|
26
|
+
production_image_path(test),
|
27
|
+
)
|
28
|
+
|
29
|
+
# In order for images to be diff'ed, they need to have the same dimensions
|
30
|
+
print "Cropping... "
|
31
|
+
image_helper.crop(test.width)
|
32
|
+
|
33
|
+
diff = image_helper.compare(test.to_s, "diff.png")
|
34
|
+
|
35
|
+
# If the images are different, let the class know about it so that it gets added to the manifest
|
36
|
+
if diff > 0
|
37
|
+
@diffs["#{test}"] = {
|
38
|
+
type: 'page',
|
39
|
+
width: test.width,
|
40
|
+
name: test.name,
|
41
|
+
diff: diff,
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Kontrast
|
2
|
+
class PageRunner
|
3
|
+
include ImageUploader
|
4
|
+
include ThumbnailCreator
|
5
|
+
|
6
|
+
attr_reader :diffs
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@diffs = {}
|
10
|
+
@selenium_handler = nil
|
11
|
+
@page_comparator = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def run(total_nodes, current_node)
|
15
|
+
# Nothing to run
|
16
|
+
return if Kontrast.page_test_suite.nil?
|
17
|
+
|
18
|
+
# Load & bind specs
|
19
|
+
Kontrast.page_test_suite.bind_specs
|
20
|
+
|
21
|
+
# Assign tests and run them
|
22
|
+
suite = split_run(total_nodes, current_node)
|
23
|
+
parallel_run(suite, current_node)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Given the total number of nodes and the index of the current node,
|
27
|
+
# we determine which tests the current node will run
|
28
|
+
def split_run(total_nodes, current_node)
|
29
|
+
test_suite = Kontrast.page_test_suite
|
30
|
+
tests_to_run = []
|
31
|
+
|
32
|
+
index = 0
|
33
|
+
test_suite.tests.each do |test|
|
34
|
+
if index % total_nodes == current_node
|
35
|
+
tests_to_run << test
|
36
|
+
end
|
37
|
+
index += 1
|
38
|
+
end
|
39
|
+
|
40
|
+
return tests_to_run
|
41
|
+
end
|
42
|
+
|
43
|
+
# Runs tests, handles all image operations, creates manifest for current node
|
44
|
+
def parallel_run(suite, current_node)
|
45
|
+
# Load test handlers
|
46
|
+
@selenium_handler = SeleniumHandler.new
|
47
|
+
@page_comparator = PageComparator.new
|
48
|
+
|
49
|
+
# Run per-page tasks
|
50
|
+
suite.each do |test|
|
51
|
+
begin
|
52
|
+
print "Processing #{test.name} @ #{test.width}... "
|
53
|
+
|
54
|
+
# Run the browser and take screenshots
|
55
|
+
@selenium_handler.run_comparison(test)
|
56
|
+
|
57
|
+
# Compare images
|
58
|
+
print "Diffing... "
|
59
|
+
@page_comparator.diff(test)
|
60
|
+
|
61
|
+
# Create thumbnails for gallery
|
62
|
+
print "Creating thumbnails... "
|
63
|
+
create_thumbnails(test, ['test.png', 'production.png', 'diff.png'])
|
64
|
+
|
65
|
+
# Upload to S3
|
66
|
+
if Kontrast.configuration.run_parallel
|
67
|
+
print "Uploading... "
|
68
|
+
upload_images(test)
|
69
|
+
end
|
70
|
+
|
71
|
+
puts "\n", ("=" * 85)
|
72
|
+
rescue Net::ReadTimeout => e
|
73
|
+
puts "Test timed out. Message: #{e.inspect}"
|
74
|
+
if Kontrast.configuration.fail_build
|
75
|
+
raise e
|
76
|
+
end
|
77
|
+
rescue StandardError => e
|
78
|
+
puts "Exception: #{e.inspect}"
|
79
|
+
puts e.backtrace.inspect
|
80
|
+
if Kontrast.configuration.fail_build
|
81
|
+
raise e
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
ensure
|
86
|
+
# Log diffs
|
87
|
+
puts @page_comparator.diffs
|
88
|
+
|
89
|
+
# We need the diff at the runner level to create the manifest
|
90
|
+
@diffs = @page_comparator.diffs
|
91
|
+
|
92
|
+
@selenium_handler.cleanup
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|