capybara-screenshot-diff 1.1.0 → 1.4.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.
- checksums.yaml +4 -4
- data/.gitattributes +4 -0
- data/.github/workflows/test.yml +129 -0
- data/.gitignore +1 -1
- data/.standard.yml +11 -0
- data/Dockerfile +60 -0
- data/README.md +107 -4
- data/Rakefile +10 -8
- data/bin/console +3 -3
- data/bin/install-vips +11 -0
- data/bin/standardrb +29 -0
- data/capybara-screenshot-diff.gemspec +18 -26
- data/gemfiles/rails42.gemfile +4 -2
- data/gemfiles/rails50.gemfile +3 -2
- data/gemfiles/rails51.gemfile +3 -2
- data/gemfiles/rails52.gemfile +3 -2
- data/gemfiles/rails60_gems.rb +8 -0
- data/gemfiles/rails61_gems.rb +7 -0
- data/gems.rb +29 -0
- data/lib/capybara/screenshot/diff.rb +24 -14
- data/lib/capybara/screenshot/diff/drivers/chunky_png_driver.rb +355 -0
- data/lib/capybara/screenshot/diff/drivers/utils.rb +24 -0
- data/lib/capybara/screenshot/diff/drivers/vips_driver.rb +180 -0
- data/lib/capybara/screenshot/diff/image_compare.rb +144 -288
- data/lib/capybara/screenshot/diff/os.rb +7 -7
- data/lib/capybara/screenshot/diff/stabilization.rb +92 -43
- data/lib/capybara/screenshot/diff/test_methods.rb +47 -52
- data/lib/capybara/screenshot/diff/vcs.rb +8 -3
- data/lib/capybara/screenshot/diff/version.rb +1 -1
- data/matrix_test.rb +20 -22
- metadata +20 -111
- data/.rubocop.yml +0 -62
- data/.rubocop_todo.yml +0 -52
- data/.travis.yml +0 -33
- data/Gemfile +0 -6
- data/gemfiles/common.gemfile +0 -12
- data/gemfiles/rails60.gemfile +0 -5
@@ -3,16 +3,16 @@
|
|
3
3
|
module Capybara
|
4
4
|
module Screenshot
|
5
5
|
module Os
|
6
|
-
ON_WINDOWS = !!(RbConfig::CONFIG[
|
7
|
-
ON_MAC = !!(RbConfig::CONFIG[
|
8
|
-
ON_LINUX = !!(RbConfig::CONFIG[
|
6
|
+
ON_WINDOWS = !!(RbConfig::CONFIG["host_os"] =~ /mswin|mingw|cygwin/)
|
7
|
+
ON_MAC = !!(RbConfig::CONFIG["host_os"] =~ /darwin/)
|
8
|
+
ON_LINUX = !!(RbConfig::CONFIG["host_os"] =~ /linux/)
|
9
9
|
|
10
10
|
def os_name
|
11
|
-
return
|
12
|
-
return
|
13
|
-
return
|
11
|
+
return "windows" if ON_WINDOWS
|
12
|
+
return "macos" if ON_MAC
|
13
|
+
return "linux" if ON_LINUX
|
14
14
|
|
15
|
-
|
15
|
+
"unknown"
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative "os"
|
4
4
|
|
5
5
|
module Capybara
|
6
6
|
module Screenshot
|
@@ -20,16 +20,13 @@ module Stabilization
|
|
20
20
|
}()
|
21
21
|
JS
|
22
22
|
|
23
|
-
def take_stable_screenshot(comparison,
|
24
|
-
area_size_limit:, skip_area:)
|
25
|
-
blurred_input = prepare_page_for_screenshot
|
23
|
+
def take_stable_screenshot(comparison, stability_time_limit:, wait:)
|
26
24
|
previous_file_name = comparison.old_file_name
|
27
25
|
screenshot_started_at = last_image_change_at = Time.now
|
26
|
+
clean_stabilization_images(comparison.new_file_name)
|
27
|
+
|
28
28
|
1.step do |i|
|
29
29
|
take_right_size_screenshot(comparison)
|
30
|
-
|
31
|
-
break unless Capybara::Screenshot.stability_time_limit
|
32
|
-
|
33
30
|
if comparison.quick_equal?
|
34
31
|
clean_stabilization_images(comparison.new_file_name)
|
35
32
|
break
|
@@ -37,12 +34,13 @@ def take_stable_screenshot(comparison, color_distance_limit:, shift_distance_lim
|
|
37
34
|
comparison.reset
|
38
35
|
|
39
36
|
if previous_file_name
|
40
|
-
stabilization_comparison =
|
41
|
-
|
42
|
-
|
43
|
-
|
37
|
+
stabilization_comparison = make_stabilization_comparison_from(
|
38
|
+
comparison,
|
39
|
+
comparison.new_file_name,
|
40
|
+
previous_file_name
|
41
|
+
)
|
44
42
|
if stabilization_comparison.quick_equal?
|
45
|
-
if (Time.now - last_image_change_at) >
|
43
|
+
if (Time.now - last_image_change_at) > stability_time_limit
|
46
44
|
clean_stabilization_images(comparison.new_file_name)
|
47
45
|
break
|
48
46
|
end
|
@@ -50,48 +48,64 @@ def take_stable_screenshot(comparison, color_distance_limit:, shift_distance_lim
|
|
50
48
|
else
|
51
49
|
last_image_change_at = Time.now
|
52
50
|
end
|
53
|
-
|
54
|
-
check_max_wait_time(comparison, screenshot_started_at,
|
55
|
-
shift_distance_limit: shift_distance_limit)
|
56
51
|
end
|
57
52
|
|
58
|
-
previous_file_name = "#{comparison.new_file_name.chomp(
|
59
|
-
|
53
|
+
previous_file_name = "#{comparison.new_file_name.chomp(".png")}" \
|
54
|
+
"_x#{format("%02i", i)}_#{(Time.now - screenshot_started_at).round(1)}s" \
|
55
|
+
"_#{stabilization_comparison.difference_region&.to_s&.gsub(", ", "_") || :initial}.png~"
|
60
56
|
FileUtils.mv comparison.new_file_name, previous_file_name
|
57
|
+
|
58
|
+
check_max_wait_time(
|
59
|
+
comparison,
|
60
|
+
screenshot_started_at,
|
61
|
+
max_wait_time: max_wait_time(comparison.shift_distance_limit, wait)
|
62
|
+
)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def notice_how_to_avoid_this
|
67
|
+
unless @_csd_retina_warned
|
68
|
+
warn "Halving retina screenshot. " \
|
69
|
+
'You should add "force-device-scale-factor=1" to your Chrome chromeOptions args.'
|
70
|
+
@_csd_retina_warned = true
|
61
71
|
end
|
62
|
-
ensure
|
63
|
-
blurred_input&.click
|
64
72
|
end
|
65
73
|
|
66
74
|
private
|
67
75
|
|
68
|
-
def
|
76
|
+
def make_stabilization_comparison_from(comparison, new_file_name, previous_file_name)
|
77
|
+
ImageCompare.new(new_file_name, previous_file_name, **comparison.driver_options)
|
78
|
+
end
|
79
|
+
|
80
|
+
def reduce_retina_image_size(file_name, driver)
|
69
81
|
return if !ON_MAC || !selenium? || !Capybara::Screenshot.window_size
|
70
82
|
|
71
|
-
|
72
|
-
|
73
|
-
return if saved_image
|
83
|
+
expected_image_width = Capybara::Screenshot.window_size[0]
|
84
|
+
saved_image = driver.from_file(file_name)
|
85
|
+
return if driver.width_for(saved_image) < expected_image_width * 2
|
74
86
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
87
|
+
notice_how_to_avoid_this
|
88
|
+
|
89
|
+
new_height = expected_image_width * driver.height_for(saved_image) / driver.width_for(saved_image)
|
90
|
+
resized_image = driver.resize_image_to(saved_image, expected_image_width, new_height)
|
91
|
+
|
92
|
+
Dir.mktmpdir do |dir|
|
93
|
+
resized_image_file = "#{dir}/resized.png"
|
94
|
+
driver.save_image_to(resized_image, resized_image_file)
|
95
|
+
FileUtils.mv(resized_image_file, file_name)
|
79
96
|
end
|
80
|
-
height = (width * saved_image.height) / saved_image.width
|
81
|
-
resized_image = saved_image.resample_bilinear(width, height)
|
82
|
-
resized_image.save(file_name)
|
83
97
|
end
|
84
98
|
|
85
99
|
def stabilization_images(base_file)
|
86
|
-
Dir["#{base_file.chomp(
|
100
|
+
Dir["#{base_file.chomp(".png")}_x*.png~"].sort
|
87
101
|
end
|
88
102
|
|
89
103
|
def clean_stabilization_images(base_file)
|
90
104
|
FileUtils.rm stabilization_images(base_file)
|
91
105
|
end
|
92
106
|
|
93
|
-
def prepare_page_for_screenshot
|
94
|
-
assert_images_loaded
|
107
|
+
def prepare_page_for_screenshot(timeout:)
|
108
|
+
assert_images_loaded(timeout: timeout)
|
95
109
|
if Capybara::Screenshot.blur_active_element
|
96
110
|
active_element = execute_script(<<-JS)
|
97
111
|
ae = document.activeElement;
|
@@ -103,7 +117,15 @@ def prepare_page_for_screenshot
|
|
103
117
|
JS
|
104
118
|
blurred_input = page.driver.send :unwrap_script_result, active_element
|
105
119
|
end
|
106
|
-
|
120
|
+
if Capybara::Screenshot.hide_caret && !@hid_caret
|
121
|
+
execute_script(<<~JS)
|
122
|
+
var style = document.createElement('style');
|
123
|
+
document.head.appendChild(style);
|
124
|
+
var styleSheet = style.sheet;
|
125
|
+
styleSheet.insertRule("* { caret-color: transparent !important; }", 0);
|
126
|
+
JS
|
127
|
+
@hid_caret = true
|
128
|
+
end
|
107
129
|
blurred_input
|
108
130
|
end
|
109
131
|
|
@@ -111,19 +133,43 @@ def take_right_size_screenshot(comparison)
|
|
111
133
|
save_screenshot(comparison.new_file_name)
|
112
134
|
|
113
135
|
# TODO(uwe): Remove when chromedriver takes right size screenshots
|
114
|
-
reduce_retina_image_size(comparison.new_file_name)
|
136
|
+
reduce_retina_image_size(comparison.new_file_name, comparison.driver)
|
115
137
|
# ODOT
|
116
138
|
end
|
117
139
|
|
118
|
-
def check_max_wait_time(comparison, screenshot_started_at,
|
140
|
+
def check_max_wait_time(comparison, screenshot_started_at, max_wait_time:)
|
141
|
+
return if (Time.now - screenshot_started_at) < max_wait_time
|
142
|
+
|
143
|
+
annotate_stabilization_images(comparison)
|
144
|
+
# FIXME(uwe): Change to store the failure and only report if the test succeeds functionally.
|
145
|
+
fail("Could not get stable screenshot within #{max_wait_time}s\n" \
|
146
|
+
"#{stabilization_images(comparison.new_file_name).join("\n")}")
|
147
|
+
end
|
148
|
+
|
149
|
+
def annotate_stabilization_images(comparison)
|
150
|
+
previous_file = comparison.old_file_name
|
151
|
+
stabilization_images(comparison.new_file_name).each do |file_name|
|
152
|
+
if File.exist? previous_file
|
153
|
+
stabilization_comparison = make_stabilization_comparison_from(
|
154
|
+
comparison,
|
155
|
+
file_name,
|
156
|
+
previous_file
|
157
|
+
)
|
158
|
+
if stabilization_comparison.different?
|
159
|
+
FileUtils.mv stabilization_comparison.annotated_new_file_name, file_name
|
160
|
+
end
|
161
|
+
FileUtils.rm stabilization_comparison.annotated_old_file_name
|
162
|
+
end
|
163
|
+
previous_file = file_name
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def max_wait_time(shift_distance_limit, wait)
|
119
168
|
shift_factor = shift_distance_limit ? (shift_distance_limit * 2 + 1) ^ 2 : 1
|
120
|
-
|
121
|
-
assert((Time.now - screenshot_started_at) < max_wait_time,
|
122
|
-
"Could not get stable screenshot within #{max_wait_time}s\n" \
|
123
|
-
"#{stabilization_images(comparison.new_file_name).join("\n")}")
|
169
|
+
wait * shift_factor
|
124
170
|
end
|
125
171
|
|
126
|
-
def assert_images_loaded(timeout:
|
172
|
+
def assert_images_loaded(timeout:)
|
127
173
|
return unless respond_to? :evaluate_script
|
128
174
|
|
129
175
|
start = Time.now
|
@@ -131,8 +177,11 @@ def assert_images_loaded(timeout: Capybara.default_max_wait_time)
|
|
131
177
|
pending_image = evaluate_script IMAGE_WAIT_SCRIPT
|
132
178
|
break unless pending_image
|
133
179
|
|
134
|
-
assert(
|
135
|
-
|
180
|
+
assert(
|
181
|
+
(Time.now - start) < timeout,
|
182
|
+
"Images not loaded after #{timeout}s: #{pending_image.inspect}"
|
183
|
+
)
|
184
|
+
|
136
185
|
sleep 0.1
|
137
186
|
end
|
138
187
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require_relative
|
9
|
-
require_relative
|
10
|
-
require_relative
|
3
|
+
require "English"
|
4
|
+
require "capybara"
|
5
|
+
require "action_controller"
|
6
|
+
require "action_dispatch"
|
7
|
+
require "active_support/core_ext/string/strip"
|
8
|
+
require_relative "image_compare"
|
9
|
+
require_relative "stabilization"
|
10
|
+
require_relative "vcs"
|
11
11
|
|
12
12
|
# Add the `screenshot` method to ActionDispatch::IntegrationTest
|
13
13
|
module Capybara
|
@@ -42,19 +42,13 @@ def screenshot_dir
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def current_capybara_driver_class
|
45
|
-
Capybara.
|
45
|
+
Capybara.current_session.driver.class
|
46
46
|
end
|
47
47
|
|
48
48
|
def selenium?
|
49
49
|
current_capybara_driver_class <= Capybara::Selenium::Driver
|
50
50
|
end
|
51
51
|
|
52
|
-
def poltergeist?
|
53
|
-
return false unless defined?(Capybara::Poltergeist::Driver)
|
54
|
-
|
55
|
-
current_capybara_driver_class <= Capybara::Poltergeist::Driver
|
56
|
-
end
|
57
|
-
|
58
52
|
def screenshot_section(name)
|
59
53
|
@screenshot_section = name.to_s
|
60
54
|
end
|
@@ -68,44 +62,59 @@ def screenshot_group(name)
|
|
68
62
|
end
|
69
63
|
|
70
64
|
# @return [Boolean] wether a screenshot was taken
|
71
|
-
def screenshot(
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
65
|
+
def screenshot(
|
66
|
+
name,
|
67
|
+
stability_time_limit: Screenshot.stability_time_limit,
|
68
|
+
wait: Capybara.default_max_wait_time,
|
69
|
+
**driver_options
|
70
|
+
)
|
71
|
+
return false unless Screenshot.active?
|
72
|
+
return false if window_size_is_wrong?
|
73
|
+
|
74
|
+
driver_options = {
|
75
|
+
area_size_limit: Diff.area_size_limit,
|
76
|
+
color_distance_limit: Diff.color_distance_limit,
|
77
|
+
driver: Diff.driver,
|
78
|
+
shift_distance_limit: Diff.shift_distance_limit,
|
79
|
+
skip_area: Diff.skip_area,
|
80
|
+
tolerance: Diff.tolerance
|
81
|
+
}.merge(driver_options)
|
82
|
+
|
83
|
+
# Allow nil or single or multiple areas
|
84
|
+
if driver_options[:skip_area]
|
85
|
+
driver_options[:skip_area] = driver_options[:skip_area].compact.flatten&.each_cons(4)&.to_a
|
86
|
+
end
|
78
87
|
|
79
88
|
if @screenshot_counter
|
80
|
-
name = "#{format(
|
89
|
+
name = "#{format("%02i", @screenshot_counter)}_#{name}"
|
81
90
|
@screenshot_counter += 1
|
82
91
|
end
|
83
92
|
name = full_name(name)
|
84
93
|
file_name = "#{Screenshot.screenshot_area_abs}/#{name}.png"
|
85
94
|
|
86
95
|
FileUtils.mkdir_p File.dirname(file_name)
|
87
|
-
comparison = ImageCompare.new(file_name,
|
88
|
-
dimensions: Screenshot.window_size, color_distance_limit: color_distance_limit,
|
89
|
-
area_size_limit: area_size_limit, shift_distance_limit: shift_distance_limit,
|
90
|
-
skip_area: skip_area)
|
96
|
+
comparison = ImageCompare.new(file_name, **driver_options)
|
91
97
|
checkout_vcs(name, comparison)
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
98
|
+
begin
|
99
|
+
blurred_input = prepare_page_for_screenshot(timeout: wait)
|
100
|
+
if stability_time_limit
|
101
|
+
take_stable_screenshot(comparison, stability_time_limit: stability_time_limit, wait: wait)
|
102
|
+
else
|
103
|
+
take_right_size_screenshot(comparison)
|
104
|
+
end
|
105
|
+
ensure
|
106
|
+
blurred_input&.click
|
107
|
+
end
|
108
|
+
|
109
|
+
return false unless comparison.old_file_exists?
|
97
110
|
|
98
111
|
(@test_screenshots ||= []) << [caller(1..1).first, name, comparison]
|
112
|
+
|
99
113
|
true
|
100
114
|
end
|
101
115
|
|
102
116
|
def window_size_is_wrong?
|
103
117
|
selenium? && Screenshot.window_size &&
|
104
|
-
|
105
|
-
# FIXME(uwe): This happens with headless chrome. Why?!
|
106
|
-
page.driver.browser.manage.window.size.width &&
|
107
|
-
# EMXIF
|
108
|
-
|
109
118
|
page.driver.browser.manage.window.size !=
|
110
119
|
::Selenium::WebDriver::Dimension.new(*Screenshot.window_size)
|
111
120
|
end
|
@@ -113,21 +122,7 @@ def window_size_is_wrong?
|
|
113
122
|
def assert_image_not_changed(caller, name, comparison)
|
114
123
|
return unless comparison.different?
|
115
124
|
|
116
|
-
|
117
|
-
max_color_distance = if RUBY_VERSION >= '2.4'
|
118
|
-
comparison.max_color_distance.ceil(1)
|
119
|
-
else
|
120
|
-
comparison.max_color_distance.ceil
|
121
|
-
end
|
122
|
-
# ODOT
|
123
|
-
|
124
|
-
max_shift_distance = comparison.max_shift_distance
|
125
|
-
"Screenshot does not match for '#{name}' (area: #{comparison.size}px #{comparison.dimensions}" \
|
126
|
-
", max_color_distance: #{max_color_distance}" \
|
127
|
-
"#{", max_shift_distance: #{max_shift_distance}" if max_shift_distance})\n" \
|
128
|
-
"#{comparison.new_file_name}\n#{comparison.annotated_old_file_name}\n" \
|
129
|
-
"#{comparison.annotated_new_file_name}\n" \
|
130
|
-
"at #{caller}"
|
125
|
+
"Screenshot does not match for '#{name}' #{comparison.error_message}\nat #{caller}"
|
131
126
|
end
|
132
127
|
end
|
133
128
|
end
|
@@ -1,15 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative "os"
|
4
4
|
module Capybara
|
5
5
|
module Screenshot
|
6
6
|
module Diff
|
7
7
|
module Vcs
|
8
|
-
SILENCE_ERRORS = Os::ON_WINDOWS ?
|
8
|
+
SILENCE_ERRORS = Os::ON_WINDOWS ? "2>nul" : "2>/dev/null"
|
9
9
|
|
10
10
|
def restore_git_revision(name, target_file_name)
|
11
11
|
redirect_target = "#{target_file_name} #{SILENCE_ERRORS}"
|
12
|
-
|
12
|
+
show_command = "git show HEAD~0:./#{Capybara::Screenshot.screenshot_area}/#{name}.png"
|
13
|
+
if Capybara::Screenshot.use_lfs
|
14
|
+
`#{show_command} | git lfs smudge > #{redirect_target}`
|
15
|
+
else
|
16
|
+
`#{show_command} > #{redirect_target}`
|
17
|
+
end
|
13
18
|
FileUtils.rm_f(target_file_name) unless $CHILD_STATUS == 0
|
14
19
|
end
|
15
20
|
|
data/matrix_test.rb
CHANGED
@@ -1,31 +1,29 @@
|
|
1
1
|
#!/usr/bin/env ruby -w
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
4
|
+
update_gemfiles = ARGV.delete("--update")
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
require 'yaml'
|
9
|
-
travis = YAML.safe_load(File.read('.travis.yml'))
|
6
|
+
require "yaml"
|
7
|
+
travis = YAML.safe_load(File.read(".travis.yml"))
|
10
8
|
|
11
9
|
def run_script(ruby, env, gemfile)
|
12
10
|
env.scan(/\b(?<key>[A-Z_]+)="(?<value>.+?)"/) do |key, value|
|
13
11
|
ENV[key] = value
|
14
12
|
end
|
15
|
-
puts
|
13
|
+
puts "*" * 80
|
16
14
|
puts "Testing #{ruby} #{gemfile} #{env}"
|
17
15
|
puts
|
18
16
|
system("chruby-exec #{ruby} -- bundle exec rake") || exit(1)
|
19
17
|
puts "Testing #{ruby} #{gemfile} OK"
|
20
|
-
puts
|
18
|
+
puts "*" * 80
|
21
19
|
end
|
22
20
|
|
23
21
|
def use_gemfile(ruby, gemfile, update_gemfiles)
|
24
|
-
puts
|
25
|
-
ENV[
|
22
|
+
puts "$" * 80
|
23
|
+
ENV["BUNDLE_GEMFILE"] = gemfile
|
26
24
|
|
27
25
|
bundler_version = `grep -A1 "BUNDLED WITH" #{gemfile}.lock | tail -n 1`
|
28
|
-
bundler_version =
|
26
|
+
bundler_version = "~> 2.0" if bundler_version.strip.empty?
|
29
27
|
|
30
28
|
version_arg = "-v '#{bundler_version}'"
|
31
29
|
bundler_gem_check_cmd = "chruby-exec #{ruby} -- gem query -i -n bundler #{version_arg} >/dev/null"
|
@@ -37,33 +35,33 @@ def use_gemfile(ruby, gemfile, update_gemfiles)
|
|
37
35
|
system "chruby-exec #{ruby} -- bundle check >/dev/null || chruby-exec #{ruby} -- bundle install"
|
38
36
|
end || exit(1)
|
39
37
|
yield
|
40
|
-
puts
|
38
|
+
puts "$" * 80
|
41
39
|
end
|
42
40
|
|
43
|
-
travis[
|
44
|
-
next if
|
41
|
+
travis["rvm"].each do |ruby|
|
42
|
+
next if /head/.match?(ruby) # ruby-install does not support HEAD installation
|
45
43
|
|
46
|
-
puts
|
44
|
+
puts "#" * 80
|
47
45
|
puts "Testing #{ruby}"
|
48
46
|
puts
|
49
47
|
system "ruby-install --no-reinstall #{ruby}" || exit(1)
|
50
|
-
travis[
|
51
|
-
if travis[
|
52
|
-
(travis[
|
53
|
-
.any? { |f| f[
|
54
|
-
puts
|
48
|
+
travis["gemfile"].each do |gemfile|
|
49
|
+
if travis["matrix"] &&
|
50
|
+
(travis["matrix"]["exclude"].to_a + travis["matrix"]["allow_failures"].to_a)
|
51
|
+
.any? { |f| f["rvm"] == ruby && (f["gemfile"].nil? || f["gemfile"] == gemfile) }
|
52
|
+
puts "Skipping known failure."
|
55
53
|
next
|
56
54
|
end
|
57
55
|
use_gemfile(ruby, gemfile, update_gemfiles) do
|
58
|
-
travis[
|
56
|
+
travis["env"].each do |env|
|
59
57
|
run_script(ruby, env, gemfile)
|
60
58
|
end
|
61
59
|
end
|
62
60
|
end
|
63
61
|
puts "Testing #{ruby} OK"
|
64
|
-
puts
|
62
|
+
puts "#" * 80
|
65
63
|
end
|
66
64
|
|
67
65
|
print "\033[0;32m"
|
68
|
-
print
|
66
|
+
print " TESTS PASSED OK!"
|
69
67
|
puts "\033[0m"
|