sauce_ruby 3.5.6
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 +7 -0
- data/bin/sauce +103 -0
- data/lib/childprocess/process.rb +34 -0
- data/lib/generators/sauce/install/install_generator.rb +54 -0
- data/lib/parallel_tests/cli_patch.rb +23 -0
- data/lib/parallel_tests/saucecucumber/runner.rb +43 -0
- data/lib/parallel_tests/saucerspec/runner.rb +40 -0
- data/lib/sauce.rb +33 -0
- data/lib/sauce/capybara.rb +189 -0
- data/lib/sauce/client.rb +40 -0
- data/lib/sauce/config.rb +434 -0
- data/lib/sauce/driver_pool.rb +5 -0
- data/lib/sauce/heroku.rb +18 -0
- data/lib/sauce/job.rb +159 -0
- data/lib/sauce/parallel.rb +16 -0
- data/lib/sauce/parallel/test_broker.rb +110 -0
- data/lib/sauce/parallel/test_group.rb +24 -0
- data/lib/sauce/railtie.rb +11 -0
- data/lib/sauce/raketasks.rb +83 -0
- data/lib/sauce/rspec/rspec.rb +186 -0
- data/lib/sauce/rspec/rspec_formatter.rb +20 -0
- data/lib/sauce/rspec/rspec_one_support.rb +66 -0
- data/lib/sauce/selenium.rb +95 -0
- data/lib/sauce/test_base.rb +21 -0
- data/lib/sauce/test_unit.rb +111 -0
- data/lib/sauce/utilities.rb +80 -0
- data/lib/sauce/utilities/connect.rb +45 -0
- data/lib/sauce/utilities/rails_server.rb +95 -0
- data/lib/sauce/utilities/rake.rb +32 -0
- data/lib/sauce/version.rb +9 -0
- data/lib/sauce/webmock.rb +16 -0
- data/lib/tasks/parallel_testing.rb +148 -0
- data/spec/cucumber_helper.rb +42 -0
- data/spec/integration/connect/spec/spec_helper.rb +21 -0
- data/spec/integration/connect/spec/start_tunnel_spec.rb +9 -0
- data/spec/integration/connect/spec/with_capybara_spec.rb +10 -0
- data/spec/integration/connect_integration_spec.rb +99 -0
- data/spec/integration/rspec-capybara/spec/capybara_required_last_spec.rb +18 -0
- data/spec/integration/rspec-capybara/spec/integration_spec.rb +17 -0
- data/spec/integration/rspec-capybara/spec/sauce_config_spec.rb +13 -0
- data/spec/integration/rspec-capybara/spec/sauce_required_last_spec.rb +21 -0
- data/spec/integration/rspec-capybara/spec/selenium/selenium_with_capybara.rb +12 -0
- data/spec/integration/rspec-capybara/spec/spec_helper.rb +37 -0
- data/spec/integration/rspec/spec/integration_spec.rb +13 -0
- data/spec/integration/rspec/spec/selenium/selenium_directory_spec.rb +20 -0
- data/spec/integration/rspec/spec/spec_helper.rb +52 -0
- data/spec/integration/rspec/spec/tagging/selenium_tagging_spec.rb +29 -0
- data/spec/integration/testunit/test/capybara_integration_test.rb +37 -0
- data/spec/integration/testunit/test/integration_test.rb +21 -0
- data/spec/integration/testunit/test/test_helper.rb +13 -0
- data/spec/parallel_tests/sauce_rspec_runner_spec.rb +23 -0
- data/spec/sauce/capybara_spec.rb +386 -0
- data/spec/sauce/config/browser_spec.rb +73 -0
- data/spec/sauce/config/config_spec.rb +400 -0
- data/spec/sauce/config/default_browsers_spec.rb +46 -0
- data/spec/sauce/config/environment_config_spec.rb +106 -0
- data/spec/sauce/config/load_defaults_spec.rb +50 -0
- data/spec/sauce/config/perfile_browser_spec.rb +105 -0
- data/spec/sauce/connect_spec.rb +21 -0
- data/spec/sauce/cucumber_spec.rb +212 -0
- data/spec/sauce/driver_pool_spec.rb +8 -0
- data/spec/sauce/file_detector_spec.rb +15 -0
- data/spec/sauce/jasmine_spec.rb +30 -0
- data/spec/sauce/parallel/test_broker_spec.rb +77 -0
- data/spec/sauce/selenium_spec.rb +60 -0
- data/spec/sauce/tasks_spec.rb +180 -0
- data/spec/sauce/utilities/rails_server_spec.rb +109 -0
- data/spec/sauce/utilities/rake_spec.rb +46 -0
- data/spec/sauce/utilities/utilities_spec.rb +137 -0
- data/spec/sauce_helper.rb +8 -0
- data/spec/spec_helper.rb +27 -0
- metadata +390 -0
data/lib/sauce/client.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Sauce
|
5
|
+
# The module that brokers most communication with Sauce Labs' REST API
|
6
|
+
class Client
|
7
|
+
class BadAccessError < StandardError; end #:nodoc
|
8
|
+
class MisconfiguredError < StandardError; end #:nodoc
|
9
|
+
|
10
|
+
attr_accessor :client
|
11
|
+
attr_accessor :protocol, :host, :port, :api_path, :api_version, :ip, :api_url
|
12
|
+
attr_accessor :jobs
|
13
|
+
|
14
|
+
def initialize(options={})
|
15
|
+
config = Sauce::Config.new
|
16
|
+
|
17
|
+
@protocol = options[:protocol] || "http"
|
18
|
+
@host = options[:host] || "saucelabs.com"
|
19
|
+
@port = options[:port] || 80
|
20
|
+
@api_path = options[:api_path] || "rest"
|
21
|
+
@api_version= options[:api_version] || 1
|
22
|
+
|
23
|
+
raise MisconfiguredError if config.username.nil? or config.access_key.nil?
|
24
|
+
@api_url = "#{@protocol}://#{config.username}:#{config.access_key}@#{@host}:#{@port}/#{@api_path}/v#{@api_version}/#{config.username}/"
|
25
|
+
@client = RestClient::Resource.new @api_url
|
26
|
+
|
27
|
+
@jobs = Sauce::Job
|
28
|
+
@jobs.client = @client
|
29
|
+
@jobs.account = {
|
30
|
+
:username => config.username,
|
31
|
+
:access_key => config.access_key,
|
32
|
+
:ip => @ip
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def [](url)
|
37
|
+
@client[url]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/sauce/config.rb
ADDED
@@ -0,0 +1,434 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'yaml'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Sauce
|
6
|
+
def self.config
|
7
|
+
yield get_config
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.get_config(default = false)
|
11
|
+
get_default = default == :default ? {} : false
|
12
|
+
@cfg ||= Sauce::Config.new(get_default)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.clear_config
|
16
|
+
@cfg = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
class Config
|
20
|
+
attr_reader :opts
|
21
|
+
|
22
|
+
DEFAULT_OPTIONS = {
|
23
|
+
:host => "ondemand.saucelabs.com",
|
24
|
+
:port => 80,
|
25
|
+
:browser_url => "http://saucelabs.com",
|
26
|
+
:job_name => "Unnamed Ruby job",
|
27
|
+
:start_tunnel => true,
|
28
|
+
:start_local_application => true,
|
29
|
+
:warn_on_skipped_integration => true,
|
30
|
+
:skip_connection_test => false
|
31
|
+
}
|
32
|
+
|
33
|
+
DEFAULT_BROWSERS = {
|
34
|
+
:browsers => [
|
35
|
+
["Windows 8", "Internet Explorer", "10"],
|
36
|
+
["Windows 7", "Firefox", "20"],
|
37
|
+
["OS X 10.8", "Safari", "6"],
|
38
|
+
["Linux", "Chrome", nil]
|
39
|
+
]
|
40
|
+
}
|
41
|
+
|
42
|
+
POTENTIAL_PORTS = [
|
43
|
+
3000, 3001, 3030, 3210, 3333, 4000, 4001, 4040, 4321, 4502, 4503, 5000,
|
44
|
+
5001, 5050, 5555, 5432, 6000, 6001, 6060, 6666, 6543, 7000, 7070, 7774,
|
45
|
+
7777, 8000, 8001, 8003, 8031, 8080, 8081, 8765, 8888, 9000, 9001, 9080,
|
46
|
+
9090, 9876, 9999, 49221, 55001, 80, 443, 888, 2000, 2001, 2020, 2109,
|
47
|
+
2222, 2310
|
48
|
+
]
|
49
|
+
|
50
|
+
ENVIRONMENT_VARIABLES = %w{SAUCE_HOST SAUCE_PORT SAUCE_BROWSER_URL SAUCE_USERNAME
|
51
|
+
SAUCE_ACCESS_KEY SAUCE_OS SAUCE_BROWSER SAUCE_BROWSER_VERSION SAUCE_JOB_NAME
|
52
|
+
SAUCE_FIREFOX_PROFILE_URL SAUCE_USER_EXTENSIONS_URL
|
53
|
+
SAUCE_ONDEMAND_BROWSERS SAUCE_USER_NAME SAUCE_API_KEY}
|
54
|
+
|
55
|
+
PLATFORMS = {
|
56
|
+
"Windows 2003" => "WINDOWS",
|
57
|
+
"Windows 2008" => "VISTA",
|
58
|
+
"Linux" => "LINUX"
|
59
|
+
}
|
60
|
+
|
61
|
+
BROWSERS = {
|
62
|
+
"iexplore" => "internet explorer",
|
63
|
+
"ie" => "internet explorer"
|
64
|
+
}
|
65
|
+
|
66
|
+
SAUCE_OPTIONS = %w{record-video record-screenshots capture-html tags
|
67
|
+
sauce-advisor single-window user-extensions-url firefox-profile-url
|
68
|
+
max-duration idle-timeout build custom-data tunnel-identifier
|
69
|
+
selenium-version command-timeout prerun prerun-args screen-resolution
|
70
|
+
disable-popup-handler avoid-proxy public name iedriver-version parent-tunnel}
|
71
|
+
|
72
|
+
def self.get_application_port
|
73
|
+
port_index = ENV["TEST_ENV_NUMBER"].to_i
|
74
|
+
return POTENTIAL_PORTS[port_index]
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.called_from_integrations?
|
78
|
+
@called_from_integrations || false
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.called_from_integrations
|
82
|
+
@called_from_integrations = true
|
83
|
+
end
|
84
|
+
|
85
|
+
# Creates a new instance of Sauce::Config
|
86
|
+
#
|
87
|
+
# @param [Hash, Boolean] opts Any value you'd set with [:option], as a hash. If false, skip loading default options
|
88
|
+
# @option opts [Boolean] :without_defaults Set true to skip loading default values
|
89
|
+
#
|
90
|
+
# @return [Sauce::Config]
|
91
|
+
def initialize(opts={})
|
92
|
+
@opts = {}
|
93
|
+
@undefaulted_opts = {}
|
94
|
+
if opts != false
|
95
|
+
if (!opts[:without_defaults])
|
96
|
+
@opts.merge! DEFAULT_OPTIONS
|
97
|
+
@opts.merge! DEFAULT_BROWSERS
|
98
|
+
@opts.merge!({:application_port => Sauce::Config.get_application_port})
|
99
|
+
|
100
|
+
@undefaulted_opts.merge! load_options_from_yaml
|
101
|
+
@undefaulted_opts.merge! load_options_from_environment
|
102
|
+
@undefaulted_opts.merge! load_options_from_heroku unless ENV["SAUCE_DISABLE_HEROKU_CONFIG"]
|
103
|
+
|
104
|
+
global_config = Sauce.get_config
|
105
|
+
@undefaulted_opts.merge! global_config.opts if global_config.opts
|
106
|
+
@whitelisted_capabilities = global_config.whitelisted_capabilities
|
107
|
+
end
|
108
|
+
|
109
|
+
@undefaulted_opts.merge! opts
|
110
|
+
@opts.merge! @undefaulted_opts
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def [](key)
|
115
|
+
@opts[key]
|
116
|
+
end
|
117
|
+
|
118
|
+
def []=(key, value)
|
119
|
+
if(key == :browsers)
|
120
|
+
value = [value] unless value.first.instance_of?(Array)
|
121
|
+
end
|
122
|
+
@undefaulted_opts.merge!({key => value})
|
123
|
+
@opts[key] = value
|
124
|
+
end
|
125
|
+
|
126
|
+
def has_key?(key)
|
127
|
+
@opts.has_key? key
|
128
|
+
end
|
129
|
+
|
130
|
+
def silence_warnings
|
131
|
+
false
|
132
|
+
end
|
133
|
+
|
134
|
+
def method_missing(meth, *args)
|
135
|
+
unless self.silence_warnings
|
136
|
+
warn "[DEPRECATED] This method (#{meth}) is deprecated, please use the [] and []= accessors instead"
|
137
|
+
end
|
138
|
+
if meth.to_s =~ /(.*)=$/
|
139
|
+
self[$1.to_sym] = args[0]
|
140
|
+
return args[0]
|
141
|
+
elsif meth.to_s =~ /(.*)\?$/
|
142
|
+
return self[$1.to_sym]
|
143
|
+
else
|
144
|
+
return self[meth]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def whitelisted_capabilities
|
149
|
+
@whitelisted_capabilities ||= Set.new
|
150
|
+
end
|
151
|
+
|
152
|
+
def whitelist capability
|
153
|
+
cap = capability.to_s
|
154
|
+
wl = whitelisted_capabilities || Set.new
|
155
|
+
@whitelisted_capabilities = wl.add cap
|
156
|
+
end
|
157
|
+
|
158
|
+
def to_browser_string
|
159
|
+
browser_options = {
|
160
|
+
'username' => @opts[:username],
|
161
|
+
'access-key' => @opts[:access_key],
|
162
|
+
'os' => os,
|
163
|
+
'browser' => browser,
|
164
|
+
'browser-version' => browser_version,
|
165
|
+
'name' => @opts[:name] || @opts[:job_name]}
|
166
|
+
|
167
|
+
SAUCE_OPTIONS.each do |opt|
|
168
|
+
[opt, opt.gsub("-", "_")].map(&:to_sym).each do |sym|
|
169
|
+
browser_options[opt] = @opts[sym] if @opts.include? sym
|
170
|
+
end
|
171
|
+
end
|
172
|
+
return browser_options.to_json
|
173
|
+
end
|
174
|
+
|
175
|
+
def to_desired_capabilities
|
176
|
+
desired_capabilities = {
|
177
|
+
:browserName => BROWSERS[browser] || browser,
|
178
|
+
:version => browser_version,
|
179
|
+
:platform => PLATFORMS[os] || os,
|
180
|
+
:name =>@opts[:job_name],
|
181
|
+
:client_version => client_version
|
182
|
+
}
|
183
|
+
|
184
|
+
allowed_options = whitelisted_capabilities + SAUCE_OPTIONS
|
185
|
+
|
186
|
+
allowed_options.each do |opt|
|
187
|
+
[opt, opt.gsub("-", "_")].map(&:to_sym).each do |sym|
|
188
|
+
if @opts.include? sym
|
189
|
+
desired_capabilities[opt.to_sym] = @opts[sym]
|
190
|
+
elsif @opts.include? sym.to_s
|
191
|
+
desired_capabilities[opt.to_sym] = @opts[sym.to_s]
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
desired_capabilities
|
197
|
+
end
|
198
|
+
|
199
|
+
def browsers
|
200
|
+
if @undefaulted_opts[:browser]
|
201
|
+
# If a specific browser was requested, ignore :browsers and
|
202
|
+
# use that one. This allows a setup with :browsers to launch
|
203
|
+
# sub-processes pointed just at each browser in the list.
|
204
|
+
return [[os, browser, browser_version]]
|
205
|
+
end
|
206
|
+
|
207
|
+
return @opts[:browsers] if @opts.include? :browsers
|
208
|
+
return [[os, browser, browser_version]]
|
209
|
+
end
|
210
|
+
|
211
|
+
def caps_for_location(file, linenumber=nil)
|
212
|
+
Sauce::Config.called_from_integrations
|
213
|
+
perfile_browsers = @opts[:perfile_browsers]
|
214
|
+
|
215
|
+
if perfile_browsers
|
216
|
+
platforms = []
|
217
|
+
test_location = "#{file}:#{linenumber}"
|
218
|
+
if linenumber && (perfile_browsers.include? test_location)
|
219
|
+
platforms = perfile_browsers[test_location]
|
220
|
+
else
|
221
|
+
platforms = perfile_browsers[file]
|
222
|
+
end
|
223
|
+
platforms.map { |p| [p['os'], p['browser'], p['version'], (p['caps'] || {})] }
|
224
|
+
else
|
225
|
+
browsers
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def browser
|
230
|
+
if single_browser_set?
|
231
|
+
return @undefaulted_opts[:browser]
|
232
|
+
end
|
233
|
+
if !ENV["TEST_ENV_NUMBER"] && @opts[:browsers]
|
234
|
+
@opts[:browsers][0][1]
|
235
|
+
else
|
236
|
+
raise StandardError, no_browser_message
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def os
|
241
|
+
if single_browser_set?
|
242
|
+
return @undefaulted_opts[:os]
|
243
|
+
end
|
244
|
+
if !ENV["TEST_ENV_NUMBER"] && @opts[:browsers]
|
245
|
+
@opts[:browsers][0][0]
|
246
|
+
else
|
247
|
+
@opts[:os]
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def browser_version
|
252
|
+
if single_browser_set?
|
253
|
+
return @undefaulted_opts[:browser_version] || @undefaulted_opts[:version]
|
254
|
+
end
|
255
|
+
if !ENV["TEST_ENV_NUMBER"] && @opts[:browsers]
|
256
|
+
@opts[:browsers][0][2]
|
257
|
+
else
|
258
|
+
@opts[:browser_version]
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def domain
|
263
|
+
return @opts[:domain] if @opts.include? :domain
|
264
|
+
return URI.parse(@opts[:browser_url]).host
|
265
|
+
end
|
266
|
+
|
267
|
+
def local?
|
268
|
+
return ENV['LOCAL_SELENIUM']
|
269
|
+
end
|
270
|
+
|
271
|
+
def username
|
272
|
+
@opts[:username]
|
273
|
+
end
|
274
|
+
|
275
|
+
def access_key
|
276
|
+
@opts[:access_key]
|
277
|
+
end
|
278
|
+
|
279
|
+
def host
|
280
|
+
@opts[:host]
|
281
|
+
end
|
282
|
+
|
283
|
+
def port
|
284
|
+
@opts[:port]
|
285
|
+
end
|
286
|
+
|
287
|
+
def after_job(hook, &block)
|
288
|
+
hooks = @opts[:after_job_hooks] || {}
|
289
|
+
hooks[hook] = block unless hooks[hook]
|
290
|
+
@opts[:after_job_hooks] = hooks
|
291
|
+
end
|
292
|
+
|
293
|
+
def run_post_job_hooks(job_id, platform, job_name, job_success)
|
294
|
+
@opts[:after_job_hooks].each do |key, hook|
|
295
|
+
hook.call job_id, platform, job_name, job_success
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
def tools
|
300
|
+
tools = []
|
301
|
+
tools << "Rspec" if is_defined? "RSpec"
|
302
|
+
tools << "Capybara" if is_defined? "Capybara"
|
303
|
+
tools << "Cucumber" if is_defined? "Cucumber"
|
304
|
+
tools << "Test::Unit" if is_defined?("Test", "Unit")
|
305
|
+
tools
|
306
|
+
end
|
307
|
+
|
308
|
+
# Only here to be stubbed for testing. Gross.
|
309
|
+
def is_defined? (top_mod, sub_mod = nil)
|
310
|
+
return_value = Object.const_defined? top_mod
|
311
|
+
unless !return_value || sub_mod.nil?
|
312
|
+
return_value = Object.const_get(top_mod).const_defined? sub_mod
|
313
|
+
end
|
314
|
+
|
315
|
+
return_value
|
316
|
+
end
|
317
|
+
|
318
|
+
private
|
319
|
+
|
320
|
+
def client_version
|
321
|
+
"Ruby: #{RUBY_ENGINE} #{RUBY_VERSION} (#{RUBY_PLATFORM}) Sauce gem: #{Sauce.version} Tools: #{tools.to_s}"
|
322
|
+
end
|
323
|
+
|
324
|
+
def load_options_from_environment
|
325
|
+
return extract_options_from_hash(ENV)
|
326
|
+
end
|
327
|
+
|
328
|
+
# Heroku supports multiple apps per $PWD. Specify $SAUCE_HEROKU_APP if
|
329
|
+
# needed otherwise this can still time out.
|
330
|
+
def load_options_from_heroku
|
331
|
+
@@heroku_environment ||= begin
|
332
|
+
if File.exists?(File.expand_path('~/.heroku'))
|
333
|
+
heroku_app = ENV['SAUCE_HEROKU_APP']
|
334
|
+
cmd = "heroku config #{heroku_app ? "--app #{heroku_app}": ''}"
|
335
|
+
cmd += "--shell 2>/dev/null"
|
336
|
+
buffer = IO.popen(cmd) { |out| out.read }
|
337
|
+
if $?.exitstatus == 0
|
338
|
+
env = {}
|
339
|
+
buffer.split("\n").each do |line|
|
340
|
+
key, value = line.split("=")
|
341
|
+
env[key] = value
|
342
|
+
end
|
343
|
+
extract_options_from_hash(env)
|
344
|
+
else
|
345
|
+
{}
|
346
|
+
end
|
347
|
+
else
|
348
|
+
{}
|
349
|
+
end
|
350
|
+
rescue Errno::ENOENT
|
351
|
+
{} # not a Heroku environment
|
352
|
+
end
|
353
|
+
return @@heroku_environment
|
354
|
+
end
|
355
|
+
|
356
|
+
def load_options_from_yaml
|
357
|
+
paths = [
|
358
|
+
"ondemand.yml",
|
359
|
+
File.join("config", "ondemand.yml"),
|
360
|
+
File.expand_path("../../../ondemand.yml", __FILE__),
|
361
|
+
File.join(File.expand_path("~"), ".sauce", "ondemand.yml")
|
362
|
+
]
|
363
|
+
|
364
|
+
paths.each do |path|
|
365
|
+
if File.exist? path
|
366
|
+
conf = YAML.load_file(path)
|
367
|
+
return conf.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
|
368
|
+
end
|
369
|
+
end
|
370
|
+
return {}
|
371
|
+
end
|
372
|
+
|
373
|
+
def extract_options_from_hash(env)
|
374
|
+
hash = Hash[env]
|
375
|
+
opts = {}
|
376
|
+
|
377
|
+
on_demand = hash.delete "SAUCE_ONDEMAND_BROWSERS"
|
378
|
+
env_browsers = hash.delete "SAUCE_BROWSERS"
|
379
|
+
username = hash.delete("SAUCE_USERNAME") || hash.delete("SAUCE_USER_NAME")
|
380
|
+
access_key = hash.delete("SAUCE_ACCESS_KEY") || hash.delete("SAUCE_API_KEY")
|
381
|
+
|
382
|
+
hash.select {|k,v| k.start_with? "SAUCE_"}.each do |k,v|
|
383
|
+
opts[k.downcase.sub("sauce_", "").to_sym] = v
|
384
|
+
end
|
385
|
+
|
386
|
+
opts[:job_name] = hash['SAUCE_JOB_NAME'] || hash['JOB_NAME']
|
387
|
+
opts[:build] = (hash['BUILD_TAG'] ||
|
388
|
+
hash['BUILD_NUMBER'] ||
|
389
|
+
hash['TRAVIS_BUILD_NUMBER'] ||
|
390
|
+
hash['CIRCLE_BUILD_NUM'])
|
391
|
+
|
392
|
+
if hash.include? 'URL'
|
393
|
+
opts['SAUCE_BROWSER_URL'] = "http://#{hash['URL']}/"
|
394
|
+
end
|
395
|
+
|
396
|
+
if on_demand
|
397
|
+
browsers = JSON.parse(on_demand)
|
398
|
+
opts[:browsers] = browsers.map { |x| [x['os'], x['browser'], x['browser-version']] }
|
399
|
+
end
|
400
|
+
|
401
|
+
if env_browsers
|
402
|
+
browsers = JSON.parse(env_browsers)
|
403
|
+
opts[:browsers] = browsers.map { |x| [x['os'], x['browser'], x['version'], x['caps']] }
|
404
|
+
end
|
405
|
+
|
406
|
+
if hash.include? 'SAUCE_PERFILE_BROWSERS'
|
407
|
+
opts[:perfile_browsers] = JSON.parse(hash['SAUCE_PERFILE_BROWSERS'])
|
408
|
+
end
|
409
|
+
|
410
|
+
opts[:username] = username if username
|
411
|
+
opts[:access_key] = access_key if access_key
|
412
|
+
|
413
|
+
return opts.delete_if {|key, value| value.nil?}
|
414
|
+
end
|
415
|
+
|
416
|
+
private
|
417
|
+
|
418
|
+
def single_browser_set?
|
419
|
+
@undefaulted_opts[:browser] || @undefaulted_opts[:os] || @undefaulted_opts[:version]
|
420
|
+
end
|
421
|
+
|
422
|
+
def no_browser_message
|
423
|
+
<<-MESSAGE
|
424
|
+
No browser has been configured.
|
425
|
+
|
426
|
+
It seems you're trying to run your tests in parallel, but haven't configured your specs/tests to use the Sauce integration.
|
427
|
+
|
428
|
+
To fix this, add :sauce => true to your specs or make your tests subclasses of Sauce::TestCase or Sauce::RailsTestCase.
|
429
|
+
|
430
|
+
For more details check the gem readme at https://github.com/saucelabs/sauce_ruby/blob/master/README.markdown
|
431
|
+
MESSAGE
|
432
|
+
end
|
433
|
+
end
|
434
|
+
end
|