sauce 3.0.0.beta.2 → 3.0.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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MWU4Y2I5MTU4YTZmNGYyODc2OTFjZjFjM2U5NTI4M2VlZjgxZTlmMw==
4
+ NTM3Y2Y1ZDY0MjBjZWUxYjU4YWExNTBjNDI3M2NjNjA5OWVmNjJlZA==
5
5
  data.tar.gz: !binary |-
6
- ZDExNzRjOWJhZTIzZDczYjdiZDg4ZTc3YzZkZmVhZDQ1OGZkMWU5Yw==
6
+ Yzg4ZmE2NjcyYTcyYTdmMGRlYTViYzk0YjRkMjY1ZjQ4MzZjMzMxMQ==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- YzQ0OWE1MTYyZjQzMThlMTBhMjAxZjBiZDNmYzI3Zjc3MDY3NDAxNTAwMGJm
10
- MGYwN2RkMmYyN2RiOTRlOWMzMzI1NTBkYTAzNjBkYjY4YWVlOTkzMzdhNGYw
11
- NzBmN2JhNWZhYWYxNjFlNTA2MDlmNWYwNzgwNzgyM2NmMTQxOGY=
9
+ YjZhNGY0MzA3NTU2MjI3NWFjMDMxYjBhY2ZjOWMxNDQ3M2ViNDAzZjI5YTc3
10
+ ZTNmNDJmNTg4OWQ5NWI4OTUwNGU0MTZkZmNkYjIzNDFkNzExYjVkMWQyZWFk
11
+ N2Y3NDVlNzdjOWI2NTMyMzdjNTMxNzUwOWRhNDEwMzNlZWM4NDg=
12
12
  data.tar.gz: !binary |-
13
- Njk2NWFhNmJmYzA2ZDRkNWNhMTg2MDUzMGI1NzM5MjBkODBjMDg3NzRiZjA0
14
- OTQxM2FiMGYyNTE4MTUxNWZhMzc2MzU4NTM4ZjhiZTRjMmQ3OTAyYzUyOGI2
15
- N2VhY2U4Y2UxYTAzNTQ3OWEyNGJmNWQxNzQwZGY1ODdlNjkxYzU=
13
+ MmY4MDVmODIwNDBhZjU3MzQxY2ZhODU1M2IwNDY0ZmNhZjg2MTBjZTBkZTU0
14
+ M2RlMjRlMTRjMjZjMWM1NWNiNWQ5NGE4NmNhM2I1NzdmZWQ2MmI2MGE5ZGVm
15
+ NjQ1YjA0NDdiNjIxYzlkZmU4ZTAwOWFlYWQxZDM4MWIzMzcwZTE=
@@ -0,0 +1,44 @@
1
+ require "parallel_tests/cucumber/runner"
2
+
3
+ module ParallelTests
4
+ module Saucecucumber
5
+ class Runner < ParallelTests::Cucumber::Runner
6
+
7
+ def self.run_tests(test_files, process_number, num_processes, options)
8
+ options = options.dup
9
+ sanitized_test_files = test_files.map { |val| Shellwords.escape(val) }
10
+ env = Sauce::TestBroker.next_environment(test_files)
11
+ env.merge!({"AUTOTEST" => "1"}) if $stdout.tty? # display color when we are in a terminal
12
+ options.merge!({:env => env})
13
+ runtime_logging = " --format ParallelTests::Cucumber::RuntimeLogger --out #{runtime_log}"
14
+ cmd = [
15
+ executable,
16
+ (runtime_logging if File.directory?(File.dirname(runtime_log))),
17
+ cucumber_opts(options[:test_options]),
18
+ *sanitized_test_files
19
+ ].compact.join(" ")
20
+ execute_command(cmd, process_number, num_processes, options)
21
+ end
22
+
23
+ def self.tests_in_groups(tests, num_groups, options={})
24
+ originals = (options[:group_by] == :steps) ? Grouper.by_steps(find_tests(tests, options), num_groups, options) : super
25
+ all_tests = originals.flatten * Sauce::TestBroker.test_platforms.length
26
+ base_group_size = all_tests.length / num_groups
27
+ num_full_groups = all_tests.length - (base_group_size * num_groups)
28
+
29
+ curpos = 0
30
+ groups = []
31
+ num_groups.times do |i|
32
+ group_size = base_group_size
33
+ if i < num_full_groups
34
+ group_size += 1
35
+ end
36
+ groups << all_tests.slice(curpos, group_size)
37
+ curpos += group_size
38
+ end
39
+
40
+ groups
41
+ end
42
+ end
43
+ end
44
+ end
@@ -6,13 +6,14 @@ module ParallelTests
6
6
  class Runner < ParallelTests::RSpec::Runner
7
7
 
8
8
  def self.run_tests(test_files, process_number, num_processes, options)
9
+ our_options = options.dup
9
10
  exe = executable # expensive, so we cache
10
11
  version = (exe =~ /\brspec\b/ ? 2 : 1)
11
- cmd = [exe, options[:test_options], (rspec_2_color if version == 2), spec_opts, *test_files].compact.join(" ")
12
+ cmd = [exe, our_options[:test_options], (rspec_2_color if version == 2), spec_opts, *test_files].compact.join(" ")
12
13
  env = Sauce::TestBroker.next_environment(test_files)
13
14
  env << " #{rspec_1_color}" if version == 1
14
- options = options.merge(:env => env)
15
- execute_command(cmd, process_number, num_processes, options)
15
+ our_options.merge!(:env => env)
16
+ execute_command(cmd, process_number, num_processes, our_options)
16
17
  end
17
18
 
18
19
 
data/lib/sauce.rb CHANGED
@@ -7,6 +7,7 @@ require 'sauce/selenium'
7
7
  require 'sauce/integrations'
8
8
  require 'tasks/parallel_testing'
9
9
  require 'parallel_tests/saucerspec/runner'
10
+ require 'parallel_tests/saucecucumber/runner'
10
11
 
11
12
  # Ruby before 1.9.3-p382 does not handle exit codes correctly when nested
12
13
  if RUBY_VERSION == "1.9.3" && RUBY_PATCHLEVEL < 392
@@ -9,24 +9,6 @@ $sauce_tunnel = nil
9
9
 
10
10
  module Sauce
11
11
  module Capybara
12
- def connect_tunnel(options={})
13
- begin
14
- require 'sauce/connect'
15
- rescue LoadError
16
- puts 'Please install the `sauce-connect` gem if you intend on using Sauce Connect with your tests!'
17
- raise
18
- end
19
-
20
- unless $sauce_tunnel.nil?
21
- return $sauce_tunnel
22
- end
23
- $sauce_tunnel = Sauce::Connect.new(options)
24
- $sauce_tunnel.connect
25
- $sauce_tunnel.wait_until_ready
26
- $sauce_tunnel
27
- end
28
- module_function :connect_tunnel
29
-
30
12
  class Driver < ::Capybara::Selenium::Driver
31
13
  RETRY_ON = [::Selenium::WebDriver::Error::UnhandledError,
32
14
  ::Selenium::WebDriver::Error::UnknownError]
@@ -99,11 +81,9 @@ module Sauce
99
81
  unless @browser
100
82
 
101
83
  @browser = Sauce::Selenium2.new
102
- # This at_exit call is causing failed rspec tests to exit(0).
103
- # Should remain disabled until it's fixed.
104
- # at_exit do
105
- # finish!
106
- # end
84
+ at_exit do
85
+ finish!
86
+ end
107
87
  end
108
88
  end
109
89
  @browser
data/lib/sauce/config.rb CHANGED
@@ -74,6 +74,10 @@ module Sauce
74
74
  @opts[key] = value
75
75
  end
76
76
 
77
+ def has_key?(key)
78
+ @opts.has_key? key
79
+ end
80
+
77
81
  def silence_warnings
78
82
  false
79
83
  end
@@ -130,6 +134,16 @@ module Sauce
130
134
  return [[os, browser, browser_version]]
131
135
  end
132
136
 
137
+ def browsers_for_file(file)
138
+ if @opts[:perfile_browsers]
139
+ @opts[:perfile_browsers][file].map do |h|
140
+ [h['os'], h['browser'], h['version']]
141
+ end
142
+ else
143
+ browsers
144
+ end
145
+ end
146
+
133
147
  def browser
134
148
  if @undefaulted_opts[:browser]
135
149
  return @undefaulted_opts[:browser]
@@ -264,39 +278,38 @@ module Sauce
264
278
 
265
279
  def extract_options_from_hash(env)
266
280
  opts = {}
267
- opts[:host] = env['SAUCE_HOST']
268
- opts[:port] = env['SAUCE_PORT']
269
- opts[:browser_url] = env['SAUCE_BROWSER_URL']
270
281
 
271
- opts[:username] = env['SAUCE_USERNAME'] || env['SAUCE_USER_NAME']
272
- opts[:access_key] = env['SAUCE_ACCESS_KEY'] || env['SAUCE_API_KEY']
282
+ on_demand = env.delete "SAUCE_ONDEMAND_BROWSERS"
283
+ env_browsers = env.delete "SAUCE_BROWSERS"
273
284
 
274
- opts[:os] = env['SAUCE_OS']
275
- opts[:browser] = env['SAUCE_BROWSER']
276
- opts[:browser_version] = env['SAUCE_BROWSER_VERSION']
285
+ env.select {|k,v| k.start_with? "SAUCE_"}.each do |k,v|
286
+ opts[k.downcase.sub("sauce_", "").to_sym] = v
287
+ end
277
288
 
278
289
  opts[:job_name] = env['SAUCE_JOB_NAME'] || env['JOB_NAME']
279
- opts[:build] = (env['BUILD_NUMBER'] ||
290
+ opts[:build] = (env['BUILD_TAG'] ||
291
+ env['BUILD_NUMBER'] ||
280
292
  env['TRAVIS_BUILD_NUMBER'] ||
281
293
  env['CIRCLE_BUILD_NUM'])
282
294
 
283
- opts[:firefox_profile_url] = env['SAUCE_FIREFOX_PROFILE_URL']
284
- opts[:user_extensions_url] = env['SAUCE_USER_EXTENSIONS_URL']
285
-
286
295
  if env.include? 'URL'
287
296
  opts['SAUCE_BROWSER_URL'] = "http://#{env['URL']}/"
288
297
  end
289
298
 
290
- if env.include? 'SAUCE_ONDEMAND_BROWSERS'
291
- browsers = JSON.parse(env['SAUCE_ONDEMAND_BROWSERS'])
299
+ if on_demand
300
+ browsers = JSON.parse(on_demand)
292
301
  opts[:browsers] = browsers.map { |x| [x['os'], x['browser'], x['browser-version']] }
293
302
  end
294
303
 
295
- if env.include? 'SAUCE_BROWSERS'
296
- browsers = JSON.parse(env['SAUCE_BROWSERS'])
304
+ if env_browsers
305
+ browsers = JSON.parse(env_browsers)
297
306
  opts[:browsers] = browsers.map { |x| [x['os'], x['browser'], x['version']] }
298
307
  end
299
308
 
309
+ if env.include? 'SAUCE_PERFILE_BROWSERS'
310
+ opts[:perfile_browsers] = JSON.parse(env['SAUCE_PERFILE_BROWSERS'])
311
+ end
312
+
300
313
  return opts.delete_if {|key, value| value.nil?}
301
314
  end
302
315
  end
@@ -19,9 +19,7 @@ begin
19
19
  config = Sauce::Config.new
20
20
  if @@need_tunnel
21
21
  if config[:application_host]
22
- @@tunnel = Sauce::Connect.new(:host => config[:application_host], :port => config[:application_port] || 80)
23
- @@tunnel.connect
24
- @@tunnel.wait_until_ready
22
+ Sauce::Utilities::Connect.start(:host => config[:application_host], :port => config[:application_port] || 80)
25
23
  end
26
24
  if config[:start_local_application] &&
27
25
  Sauce::Utilities::RailsServer.is_rails_app?
@@ -32,7 +30,7 @@ begin
32
30
  end
33
31
 
34
32
  after :suite do
35
- @@tunnel.disconnect if defined? @@tunnel
33
+ Sauce::Utilities::Connect.close
36
34
  @@server.stop if defined? @@server
37
35
  end
38
36
 
@@ -75,7 +73,8 @@ begin
75
73
  othermod.around do |the_test|
76
74
  config = Sauce::Config.new
77
75
  description = the_test.metadata[:full_description]
78
- config.browsers.each do |os, browser, version|
76
+ file = the_test.metadata[:file_path]
77
+ config.browsers_for_file(file).each do |os, browser, version|
79
78
  @selenium = Sauce::Selenium2.new({:os => os,
80
79
  :browser => browser,
81
80
  :browser_version => version,
@@ -102,9 +101,7 @@ begin
102
101
 
103
102
  config = Sauce::Config.new
104
103
  if config[:application_host]
105
- @@tunnel ||= Sauce::Connect.new(:host => config[:application_host], :port => config[:application_port] || 80)
106
- @@tunnel.connect
107
- @@tunnel.wait_until_ready
104
+ Sauce::Utilities::Connect.start(:host => config[:application_host], :port => config[:application_port] || 80)
108
105
  end
109
106
 
110
107
  if config[:start_local_application] &&
@@ -127,9 +124,7 @@ begin
127
124
  end
128
125
 
129
126
  if need_tunnel || config[:start_tunnel]
130
- @@tunnel ||= Sauce::Connect.new(:host => config[:application_host], :port => config[:application_port] || 80)
131
- @@tunnel.connect
132
- @@tunnel.wait_until_ready
127
+ Sauce::Utilities::Connect.start(:host => config[:application_host], :port => config[:application_port] || 80)
133
128
  end
134
129
 
135
130
  if config[:start_local_application] &&
@@ -142,7 +137,7 @@ begin
142
137
  end
143
138
  end
144
139
  ::RSpec.configuration.after :suite do
145
- @@tunnel.disconnect if defined? @@tunnel
140
+ Sauce::Utilities::Connect.close
146
141
  @@server.stop if defined? @@server
147
142
  end
148
143
  end
@@ -2,16 +2,34 @@ require "rest-client"
2
2
  require "json"
3
3
  require "yaml"
4
4
  require "sauce/parallel/test_group"
5
+ require "thread"
5
6
 
6
7
  module Sauce
7
8
  class TestBroker
8
-
9
- def self.next_environment(group)
10
- unless test_groups.has_key? group
11
- test_groups[group] = TestGroup.new(self.test_platforms)
9
+
10
+ def self.reset
11
+ if defined? @@platforms
12
+ remove_class_variable(:@@platforms)
12
13
  end
14
+ @groups = {}
15
+ end
13
16
 
14
- test_groups[group].next_platform
17
+ def self.environment_mutex
18
+ @@m ||= Mutex.new
19
+ end
20
+
21
+ def self.next_environment(group)
22
+ environment_mutex.synchronize do
23
+ browsers = {}
24
+ group.each do |file|
25
+ file = "./" + file
26
+ test_groups[file] ||= TestGroup.new(self.test_platforms)
27
+ browsers[file] ||= []
28
+ browsers[file] << test_groups[file].next_platform
29
+ end
30
+
31
+ return {:SAUCE_PERFILE_BROWSERS => "'" + JSON.generate(browsers) + "'"}
32
+ end
15
33
  end
16
34
 
17
35
  def self.test_groups
@@ -37,8 +55,7 @@ module Sauce
37
55
  def self.test_platforms
38
56
  unless defined? @@platforms
39
57
  load_sauce_config
40
- brokers = Sauce.get_config
41
- @@platforms ||= brokers[:browsers]
58
+ @@platforms ||= Sauce.get_config[:browsers]
42
59
  end
43
60
  @@platforms
44
61
  end
@@ -53,11 +70,25 @@ module Sauce
53
70
  end
54
71
 
55
72
  def self.load_sauce_config
56
- if File.exists? "./spec/sauce_helper.rb"
57
- require "./spec/sauce_helper"
58
- else
59
- require "./spec/spec_helper"
73
+ begin
74
+ if File.exists? "./spec/sauce_helper.rb"
75
+ require "./spec/sauce_helper"
76
+ else
77
+ require "./spec/spec_helper"
78
+ end
79
+ rescue LoadError => e
80
+ # Gross, but maybe theyre using Cuke
81
+ begin
82
+ if File.exists? "./features/support/sauce_helper.rb"
83
+ require "./features/support/sauce_helper"
84
+ else
85
+ raise LoadError "Can't find sauce_helper, please add it in ./features/support/sauce_helper.rb"
86
+ end
87
+ rescue LoadError => e
88
+ #WHO KNOWS
89
+ end
60
90
  end
91
+
61
92
  end
62
93
 
63
94
  SAUCE_USERNAME = ENV["SAUCE_USERNAME"]
@@ -7,12 +7,12 @@ module Sauce
7
7
 
8
8
  def next_platform
9
9
  platform = @platforms[@index]
10
+ @index += 1
10
11
  begin
11
- @index = @index + 1
12
12
  {
13
- :SAUCE_OS => "'#{platform[0]}'",
14
- :SAUCE_BROWSER => "'#{platform[1]}'",
15
- :SAUCE_BROWSER_VERSION => "'#{platform[2]}'"
13
+ 'os' => platform[0],
14
+ 'browser' => platform[1],
15
+ 'version' => platform[2]
16
16
  }
17
17
  rescue NoMethodError => e
18
18
  puts "I don't have any config"
@@ -3,6 +3,7 @@ require 'socket'
3
3
  require 'childprocess'
4
4
  require 'net/http'
5
5
  require 'childprocess/process'
6
+ require 'sauce/parallel'
6
7
 
7
8
  module Sauce
8
9
  module Utilities
@@ -31,6 +32,40 @@ module Sauce
31
32
  end
32
33
  end
33
34
 
35
+ class Connect
36
+ def self.start(options={})
37
+ begin
38
+ require "sauce/connect"
39
+ rescue LoadError => e
40
+ STDERR.puts 'Please install the `sauce-connect` gem if you intend on using Sauce Connect with your tests!'
41
+ exit(1)
42
+ end
43
+
44
+ if ParallelTests.first_process?
45
+ unless @tunnel
46
+ @tunnel = Sauce::Connect.new options
47
+ @tunnel.connect
48
+ @tunnel.wait_until_ready
49
+ end
50
+ @tunnel
51
+ else
52
+ while not File.exist? "sauce_connect.ready"
53
+ sleep 0.5
54
+ end
55
+ end
56
+ end
57
+
58
+ def self.close
59
+ if @tunnel
60
+ if ParallelTests.first_process?
61
+ ParallelTests.wait_for_other_processes_to_finish
62
+ @tunnel.disconnect
63
+ @tunnel = nil
64
+ end
65
+ end
66
+ end
67
+ end
68
+
34
69
  class RailsServer
35
70
  include Sauce::Utilities
36
71
 
data/lib/sauce/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Sauce
2
2
  MAJOR_VERSION = '3.0'
3
- PATCH_VERSION = '0.beta.2'
3
+ PATCH_VERSION = '0'
4
4
 
5
5
  def version
6
6
  "#{MAJOR_VERSION}.#{PATCH_VERSION}"
@@ -4,59 +4,85 @@ require "parallel_tests/tasks"
4
4
  require "parallel_tests/cli_patch"
5
5
 
6
6
  namespace :sauce do
7
- task :spec, :arg1 do |t, args|
8
-
7
+ task :spec, :files, :concurrencies do |t, args|
9
8
  ::RSpec::Core::Runner.disable_autorun!
10
9
 
11
- args.with_defaults(:arg1 => [Sauce::TestBroker.concurrencies, 20].min)
12
- concurrency = args[:arg1]
10
+ args.with_defaults({
11
+ :concurrencies => [Sauce::TestBroker.concurrencies, 20].min,
12
+ :files => "spec"
13
+ })
13
14
  ParallelTests::CLI.new.run(["--type", "saucerspec",
14
- "-n", "#{concurrency}",
15
- "spec"])
15
+ "-n", "#{args[:concurrencies]}",
16
+ "#{args[:files]}"])
16
17
  end
17
18
 
18
- task :install => :create_helper do
19
- spec_helper_path = "spec/spec_helper.rb"
20
- unless File.open(spec_helper_path) { |f| f.read.match "require \"sauce_helper\""}
21
- File.open("spec/spec_helper.rb", "a") do |f|
22
- f.write "require \"sauce_helper\""
23
- end
24
- else
25
- puts "WARNING - The Sauce gem is already integrated into your rspec setup"
19
+ task :features, :files, :concurrency do |t, args|
20
+ args.with_defaults({
21
+ :concurrency => [Sauce::TestBroker.concurrencies, 20].min,
22
+ :files => "features"
23
+ })
24
+ ParallelTests::CLI.new.run(["--type", "saucecucumber", args[:files],
25
+ "-n", args[:concurrency].to_s])
26
+ end
27
+
28
+ namespace :install do
29
+ task :features do
30
+ Rake::Task["sauce:install:create_helper"].execute(:helper_type => :features)
31
+ puts <<-ENDLINE
32
+ The Sauce gem is now installed!
33
+
34
+ Next steps:
35
+
36
+ 1. Edit features/support/sauce_helper.rb with your required platforms
37
+ 2. Set the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables
38
+ 3. Run your tests with 'rake sauce:features'
39
+
40
+ ENDLINE
26
41
  end
27
- puts <<-ENDLINE
28
- The Sauce gem is now installed!
42
+ task :spec do
43
+ Rake::Task["sauce:install:create_helper"].execute(:helper_type => :spec)
44
+ spec_helper_path = "spec/spec_helper.rb"
45
+ unless File.open(spec_helper_path) { |f| f.read.match "require \"sauce_helper\""}
46
+ File.open("spec/spec_helper.rb", "a") do |f|
47
+ f.write "require \"sauce_helper\""
48
+ end
49
+ else
50
+ puts "WARNING - The Sauce gem is already integrated into your rspec setup"
51
+ end
52
+ puts <<-ENDLINE
53
+ The Sauce gem is now installed!
29
54
 
30
- Next steps:
55
+ Next steps:
31
56
 
32
- 1. Edit spec/sauce_helper.rb with your required platforms
33
- 2. Make sure we've not mangled your spec/spec_helper.rb requiring sauce_helper
34
- 3. Set the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables
35
- 3. Run your tests with 'rake sauce:spec'
57
+ 1. Edit spec/sauce_helper.rb with your required platforms
58
+ 2. Make sure we've not mangled your spec/spec_helper.rb requiring sauce_helper
59
+ 3. Set the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables
60
+ 3. Run your tests with 'rake sauce:spec'
36
61
 
37
- ENDLINE
38
- end
62
+ ENDLINE
63
+ end
64
+
65
+ task :create_helper, [:helper_type] do |t, args|
66
+ path = args[:helper_type].to_sym == :features ? "features/support/sauce_helper.rb" : "spec/sauce_helper.rb"
67
+ unless File.exists? path
68
+ File.open(path, "w") do |f|
69
+ f.write (<<-ENDFILE
70
+ # You should edit this file with the browsers you wish to use
71
+ # For options, check out http://saucelabs.com/platforms
72
+ require "sauce"
39
73
 
40
- task :create_helper do
41
- sauce_helper_path = "spec/sauce_helper.rb"
42
- unless File.exists? sauce_helper_path
43
- File.open(sauce_helper_path, "w") do |f|
44
- f.write (<<-ENDFILE
45
- # You should edit this file with the browsers you wish to use
46
- # For options, check out http://saucelabs.com/platforms
47
- require "sauce"
48
-
49
- Sauce.config do |config|
50
- config[:browsers] = [
51
- ["OS", "BROWSER", "VERSION"],
52
- ["OS", "BROWSER", "VERSION"]
53
- ]
54
- end
55
- ENDFILE
56
- )
74
+ Sauce.config do |config|
75
+ config[:browsers] = [
76
+ ["OS", "BROWSER", "VERSION"],
77
+ ["OS", "BROWSER", "VERSION"]
78
+ ]
79
+ end
80
+ ENDFILE
81
+ )
82
+ end
83
+ else
84
+ STDERR.puts "WARNING - sauce_helper has already been created."
57
85
  end
58
- else
59
- STDERR.puts "WARNING - sauce_helper has already been created."
60
86
  end
61
87
  end
62
- end
88
+ end
@@ -26,7 +26,7 @@ describe "Specs in the Selenium Directory" do
26
26
  end
27
27
 
28
28
  it "should be using Sauce Connect" do
29
- Sauce::RSpec::SeleniumExampleGroup.class_variable_defined?(:@@tunnel).should be_true
29
+ Sauce::Utilities::Connect.instance_variable_get(:@tunnel).should_not be_nil
30
30
  end
31
31
  end
32
32
 
@@ -25,7 +25,7 @@ describe "Specs with the @sauce tag", :sauce => true do
25
25
  end
26
26
 
27
27
  it "should be using Sauce Connect" do
28
- Sauce::RSpec::SeleniumExampleGroup.class_variable_defined?(:@@tunnel).should be_true
28
+ Sauce::Utilities::Connect.instance_variable_get(:@tunnel).should_not be_nil
29
29
  end
30
30
  end
31
31
 
@@ -3,38 +3,9 @@ require 'sauce/capybara'
3
3
  require 'sauce/connect'
4
4
 
5
5
  describe Sauce::Capybara do
6
- describe '#connect_tunnel' do
7
- before :each do
8
- $sauce_tunnel = nil
9
- end
10
-
11
- let(:connector) do
12
- connector = double()
13
- connector.should_receive(:connect)
14
- connector.should_receive(:wait_until_ready)
15
- connector
16
- end
17
-
18
- it 'should not do anything if the sauce tunnel exists' do
19
- $sauce_tunnel = 1337
20
- Sauce::Capybara.connect_tunnel.should == 1337
21
- end
22
-
23
- it 'should connect if the tunnel is not connected' do
24
- Sauce::Connect.should_receive(:new).and_return(connector)
25
6
 
26
- Sauce::Capybara.connect_tunnel
27
- end
28
-
29
- it 'should pass the quiet option to Sauce::Connect' do
30
- Sauce::Connect.should_receive(:new).with(
31
- hash_including(:quiet => true)).and_return(connector)
32
- Sauce::Capybara.connect_tunnel(:quiet => true)
33
- end
34
-
35
- after :each do
36
- $sauce_tunnel = nil
37
- end
7
+ after :each do
8
+ Sauce::Utilities::Connect.instance_variable_set(:@tunnel, false)
38
9
  end
39
10
 
40
11
  describe Sauce::Capybara::Driver do
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
2
  require 'sauce/config'
3
3
 
4
4
  describe Sauce::Config do
@@ -92,7 +92,7 @@ describe Sauce::Config do
92
92
  ENV['SAUCE_OS'] = "Linux"
93
93
  ENV['SAUCE_BROWSER'] = "firefox"
94
94
  ENV['SAUCE_BROWSER_VERSION'] = "3."
95
- ENV['BUILD_NUMBER'] = 'test env build'
95
+ ENV['BUILD_TAG'] = 'test env build'
96
96
 
97
97
  config = Sauce::Config.new
98
98
  browser_data = JSON.parse(config.to_browser_string)
@@ -112,7 +112,7 @@ describe Sauce::Config do
112
112
  ENV['SAUCE_BROWSER'] = 'firefox'
113
113
  ENV['SAUCE_BROWSER_VERSION'] = '3.'
114
114
  ENV['SAUCE_JOB_NAME'] = 'Named Ruby Job'
115
- ENV['BUILD_NUMBER'] = 'test env build'
115
+ ENV['BUILD_TAG'] = 'test env build'
116
116
 
117
117
  config = Sauce::Config.new
118
118
  browser_data = JSON.parse(config.to_browser_string)
@@ -0,0 +1,83 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+ require 'sauce/config'
3
+
4
+ describe "Sauce::Config" do
5
+ describe "#extract_options_from_hash" do
6
+ let(:test_options) {
7
+ {
8
+ "SAUCE_USERNAME" => "user",
9
+ "SAUCE_ACCESS_KEY" => "ac",
10
+ "SAUCE_APPLICATION_HOST" => "application_host"
11
+ }
12
+ }
13
+
14
+ let(:test_config) {Sauce::Config.new}
15
+
16
+ it "should set any options starting with SAUCE" do
17
+ test_config
18
+ opts = test_config.send(:extract_options_from_hash, test_options)
19
+
20
+ opts[:username].should eq "user"
21
+ opts[:application_host].should eq "application_host"
22
+ end
23
+
24
+ context "when passed build numbers" do
25
+ it "should accept BUILD_NUMBER" do
26
+ opts = test_config.send(:extract_options_from_hash, {"BUILD_NUMBER" => "build"})
27
+ opts[:build].should eq "build"
28
+ end
29
+
30
+ it "should accept TRAVIS_BUILD_NUMBER" do
31
+ opts = test_config.send(:extract_options_from_hash, {"TRAVIS_BUILD_NUMBER" => "build"})
32
+ opts[:build].should eq "build"
33
+ end
34
+
35
+ it "should accept CIRCLE_BUILD_NUM" do
36
+ opts = test_config.send(:extract_options_from_hash, {"CIRCLE_BUILD_NUM" => "build"})
37
+ opts[:build].should eq "build"
38
+ end
39
+ end
40
+
41
+ context "when passed browsers in a json array keyed to SAUCE_ONDEMAND_BROWSERS" do
42
+ let(:browsers) {
43
+ { "SAUCE_ONDEMAND_BROWSERS" => [
44
+ {:os => "os1", :browser => "ie1", "browser-version" => "version1"},
45
+ {:os => "os2", :browser => "ie2", "browser-version" => "version2"}
46
+ ].to_json,
47
+ "SAUCE_BROWSER" => "not_browser",
48
+ "SAUCE_BROWSER_VERSION" => "not_version",
49
+ "SAUCE_OS" => "not_os"
50
+ }
51
+ }
52
+
53
+ it "should extract the browsers" do
54
+ opts = test_config.send(:extract_options_from_hash, browsers)
55
+ opts[:browsers].should eq([
56
+ ["os1", "ie1", "version1"],
57
+ ["os2", "ie2", "version2"]
58
+ ])
59
+ end
60
+ end
61
+
62
+ context "when passed browsers in a json array keyed to SAUCE_BROWSERS" do
63
+ let(:browsers) {
64
+ { "SAUCE_BROWSERS" => [
65
+ {:os => "os1", :browser => "ie1", "version" => "version1"},
66
+ {:os => "os2", :browser => "ie2", "version" => "version2"}
67
+ ].to_json,
68
+ "SAUCE_BROWSER" => "not_browser",
69
+ "SAUCE_BROWSER_VERSION" => "not_version",
70
+ "SAUCE_OS" => "not_os"
71
+ }
72
+ }
73
+
74
+ it "should extract the browsers" do
75
+ opts = test_config.send(:extract_options_from_hash, browsers)
76
+ opts[:browsers].should eq([
77
+ ["os1", "ie1", "version1"],
78
+ ["os2", "ie2", "version2"]
79
+ ])
80
+ end
81
+ end
82
+ end
83
+ end
@@ -9,6 +9,10 @@ module Sauce::Capybara
9
9
  include Sauce::Capybara::Cucumber
10
10
  include Sauce::Cucumber::SpecHelper
11
11
 
12
+ before :each do
13
+ Sauce::Utilities::Connect.stub!(:start) {}
14
+ end
15
+
12
16
  describe '#use_sauce_driver' do
13
17
  before :each do
14
18
  ::Capybara.current_driver = :test
@@ -66,6 +70,7 @@ module Sauce::Capybara
66
70
  # Need to create our nice mocked Capybara driver
67
71
  Capybara.stub_chain(:current_session, :driver).and_return(driver)
68
72
  Sauce::Job.stub(:new).and_return(nil)
73
+ Sauce::Selenium2.stub(:new).with(anything).and_return Object.new
69
74
  end
70
75
 
71
76
  context 'with a scenario outline' do
@@ -109,6 +114,53 @@ module Sauce::Capybara
109
114
 
110
115
  end
111
116
 
117
+ context "when using sauce/connect" do
118
+ let(:feature) do
119
+ """
120
+ Feature: A dummy feature
121
+ @selenium
122
+ Scenario: A dummy scenario
123
+ Given a scenario
124
+ When I raise no exceptions
125
+ """
126
+ end
127
+
128
+ before :each do
129
+ Sauce::Utilities::Connect.rspec_reset
130
+
131
+ Sauce.config do |c|
132
+ c[:start_tunnel] = true
133
+ end
134
+ $ran_scenario = nil
135
+ end
136
+
137
+ after :all do
138
+ Sauce::Utilities::Connect.stub!(:start) {}
139
+ end
140
+
141
+ it 'should have set up a tunnel' do
142
+ define_steps do
143
+ Given /^a scenario$/ do
144
+ end
145
+ When /^I raise no exceptions$/ do
146
+ $ran_scenario = true
147
+ end
148
+ # Set up and invoke our defined Around hook
149
+ Around('@selenium') do |scenario, block|
150
+ # We need to fully reference the module function here due to a
151
+ # change in scoping that will happen to this block courtesy of
152
+ # define_steps
153
+ Sauce::Capybara::Cucumber.around_hook(scenario, block)
154
+ end
155
+ end
156
+
157
+ # Make sure we actually configure ourselves
158
+ Sauce::Utilities::Connect.should_receive(:start).with(anything).and_return {true}
159
+ run_defined_feature feature
160
+ $ran_scenario.should be true
161
+ end
162
+ end
163
+
112
164
  context 'with a correct scenario' do
113
165
  let(:feature) do
114
166
  """
@@ -1,3 +1,4 @@
1
+ require "json"
1
2
  require "rspec"
2
3
  require "sauce/parallel/test_broker"
3
4
 
@@ -5,32 +6,65 @@ describe Sauce::TestBroker do
5
6
 
6
7
  describe "#next_environment" do
7
8
 
8
- before :all do
9
- Sauce.config do |c|
10
- c.browsers = [
11
- ["Windows 7", "Opera", "10"],
12
- ["Linux", "Firefox", "19"]
13
- ]
14
- end
9
+ before :each do
10
+ Sauce::TestBroker.reset
15
11
  end
16
12
 
17
- it "returns the first environment for new entries" do
18
- first_environment = Sauce::TestBroker.next_environment "spec/a_spec"
13
+ it "returns the first browser for new entries" do
14
+ first_environment = Sauce::TestBroker.next_environment ["spec/a_spec"]
19
15
  first_environment.should eq({
20
- :SAUCE_OS => "'Windows 7'",
21
- :SAUCE_BROWSER => "'Opera'",
22
- :SAUCE_BROWSER_VERSION => "'10'"
16
+ :SAUCE_PERFILE_BROWSERS => (
17
+ "'" +
18
+ JSON.generate({"./spec/a_spec" => [{"os" => "Windows 7",
19
+ "browser" => "Opera",
20
+ "version" => "10"}]}) +
21
+ "'")
23
22
  })
24
23
  end
25
24
 
26
- it "should only return an environment once" do
27
- Sauce::TestBroker.next_environment "spec/b_spec"
28
- second_environment = Sauce::TestBroker.next_environment "spec/b_spec"
25
+ it "only returns a browser once for a given file" do
26
+ Sauce::TestBroker.next_environment ["spec/a_spec"]
27
+ second_environment = Sauce::TestBroker.next_environment ["spec/a_spec"]
29
28
 
30
29
  second_environment.should eq({
31
- :SAUCE_OS => "'Linux'",
32
- :SAUCE_BROWSER => "'Firefox'",
33
- :SAUCE_BROWSER_VERSION => "'19'"
30
+ :SAUCE_PERFILE_BROWSERS => (
31
+ "'" +
32
+ JSON.generate({"./spec/a_spec" => [{"os" => "Linux",
33
+ "browser" => "Firefox",
34
+ "version" => "19"}]}) +
35
+ "'")
36
+ })
37
+ end
38
+
39
+ it "returns multiple browsers for files given multiple times" do
40
+ first_environment = Sauce::TestBroker.next_environment ["spec/a_spec",
41
+ "spec/a_spec"]
42
+ first_environment.should eq({
43
+ :SAUCE_PERFILE_BROWSERS => (
44
+ "'" +
45
+ JSON.generate({"./spec/a_spec" => [{"os" => "Windows 7",
46
+ "browser" => "Opera",
47
+ "version" => "10"},
48
+ {"os" => "Linux",
49
+ "browser" => "Firefox",
50
+ "version" => "19"}]}) +
51
+ "'")
52
+ })
53
+ end
54
+
55
+ it "uses the first browser for each of multiple files" do
56
+ first_environment = Sauce::TestBroker.next_environment ["spec/a_spec",
57
+ "spec/b_spec"]
58
+ first_environment.should eq({
59
+ :SAUCE_PERFILE_BROWSERS => (
60
+ "'" +
61
+ JSON.generate({"./spec/a_spec" => [{"os" => "Windows 7",
62
+ "browser" => "Opera",
63
+ "version" => "10"}],
64
+ "./spec/b_spec" => [{"os" => "Windows 7",
65
+ "browser" => "Opera",
66
+ "version" => "10"}]}) +
67
+ "'")
34
68
  })
35
69
  end
36
70
  end
@@ -40,4 +74,4 @@ describe Sauce::TestBroker do
40
74
  Sauce::TestBroker.test_platforms.should eq Sauce.get_config.browsers
41
75
  end
42
76
  end
43
- end
77
+ end
@@ -0,0 +1,87 @@
1
+ require "spec_helper"
2
+ require "sauce/connect"
3
+
4
+ Sauce.config do |c|
5
+ c[:start_tunnel] = false
6
+ end
7
+
8
+ describe "Sauce::Utilities::Connect" do
9
+
10
+ before :each do
11
+ @mock_tunnel = double()
12
+ end
13
+
14
+ after :each do
15
+ Sauce::Utilities::Connect.instance_variable_set(:@tunnel, nil)
16
+ end
17
+ describe "##start" do
18
+ it "should call Sauce Connect when included" do
19
+ @mock_tunnel.stub(:connect).and_return true
20
+ @mock_tunnel.stub(:wait_until_ready).and_return true
21
+ Sauce::Connect.should_receive(:new).with(anything) {@mock_tunnel}
22
+ Sauce::Utilities::Connect.start
23
+ end
24
+
25
+ it "should throw an exception when Sauce Connect is not included" do
26
+ Object.should_receive(:require).with("sauce/connect").and_raise LoadError
27
+
28
+ lambda {Sauce::Utilities::Connect.start}.should raise_error SystemExit
29
+ end
30
+
31
+ it "should connect the new tunnel" do
32
+ Sauce::Connect.rspec_reset
33
+ @mock_tunnel.should_receive(:connect).with().and_return(true)
34
+ @mock_tunnel.should_receive(:wait_until_ready).and_return(true)
35
+
36
+ Sauce::Connect.stub!(:new).with(anything).and_return @mock_tunnel
37
+
38
+ Sauce::Utilities::Connect.start
39
+ end
40
+
41
+ it "should return the tunnel when done" do
42
+ @mock_tunnel.stub(:connect).and_return true
43
+ @mock_tunnel.stub(:wait_until_ready).and_return true
44
+ Sauce::Connect.should_receive(:new).with(anything) {@mock_tunnel}
45
+ tunnel = Sauce::Utilities::Connect.start
46
+ tunnel.should be @mock_tunnel
47
+ end
48
+
49
+ it "only opens one tunnel" do
50
+ @mock_tunnel.stub(:connect).and_return true
51
+ @mock_tunnel.stub(:wait_until_ready).and_return true
52
+ Sauce::Connect.should_receive(:new).with(anything) {@mock_tunnel}
53
+ tunnel = Sauce::Utilities::Connect.start
54
+
55
+ tunnel_2 = Sauce::Utilities::Connect.start
56
+
57
+ tunnel.should be tunnel_2
58
+ end
59
+ end
60
+
61
+ describe "#close" do
62
+ it "makes the tunnel nil when terminated" do
63
+ @mock_tunnel.stub(:connect).and_return true
64
+ @mock_tunnel.stub(:wait_until_ready).and_return true
65
+ @mock_tunnel.should_receive(:disconnect).and_return true
66
+ Sauce::Connect.stub(:new).with(anything) {@mock_tunnel}
67
+ Sauce::Utilities::Connect.start
68
+
69
+ Sauce::Utilities::Connect.close
70
+ Sauce::Utilities::Connect.instance_variable_get(:@tunnel).should be nil
71
+ end
72
+
73
+ it "calls disconnect" do
74
+ @mock_tunnel.stub(:connect).and_return true
75
+ @mock_tunnel.stub(:wait_until_ready).and_return true
76
+ @mock_tunnel.should_receive(:disconnect).and_return true
77
+ Sauce::Connect.stub(:new).with(anything) {@mock_tunnel}
78
+ tunnel = Sauce::Utilities::Connect.start
79
+
80
+ Sauce::Utilities::Connect.close
81
+ end
82
+
83
+ it "does not error if no tunnel exists" do
84
+ Sauce::Utilities::Connect.close
85
+ end
86
+ end
87
+ end
data/spec/sauce_helper.rb CHANGED
@@ -2,7 +2,7 @@ require "sauce"
2
2
 
3
3
  Sauce.config do |c|
4
4
  c[:browsers] = [
5
- ["Windows 7", "Opera", 10],
6
- ["Linux", "Firefox", 19]
5
+ ["Windows 7", "Opera", "10"],
6
+ ["Linux", "Firefox", "19"]
7
7
  ]
8
- end
8
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require "rspec"
1
2
  $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
2
3
 
3
4
  ['sauce-jasmine', 'sauce-cucumber', 'sauce-connect'].each do |gem|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sauce
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.beta.2
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dylan Lacey
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2013-06-02 00:00:00.000000000 Z
16
+ date: 2013-06-07 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: capybara
@@ -29,6 +29,20 @@ dependencies:
29
29
  - - ~>
30
30
  - !ruby/object:Gem::Version
31
31
  version: 2.1.0
32
+ - !ruby/object:Gem::Dependency
33
+ name: rspec
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: '2.0'
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '2.0'
32
46
  - !ruby/object:Gem::Dependency
33
47
  name: net-http-persistent
34
48
  requirement: !ruby/object:Gem::Requirement
@@ -194,6 +208,7 @@ files:
194
208
  - lib/childprocess/process.rb
195
209
  - lib/generators/sauce/install/install_generator.rb
196
210
  - lib/parallel_tests/cli_patch.rb
211
+ - lib/parallel_tests/saucecucumber/runner.rb
197
212
  - lib/parallel_tests/saucerspec/runner.rb
198
213
  - lib/sauce/capybara.rb
199
214
  - lib/sauce/client.rb
@@ -224,12 +239,14 @@ files:
224
239
  - spec/integration/testunit/test/integration_test.rb
225
240
  - spec/parallel_tests/sauce_rspec_runner_spec.rb
226
241
  - spec/sauce/capybara_spec.rb
227
- - spec/sauce/config_spec.rb
242
+ - spec/sauce/config/config_spec.rb
243
+ - spec/sauce/config/environment_config_spec.rb
228
244
  - spec/sauce/cucumber_spec.rb
229
245
  - spec/sauce/driver_pool_spec.rb
230
246
  - spec/sauce/jasmine_spec.rb
231
247
  - spec/sauce/parallel/test_broker_spec.rb
232
248
  - spec/sauce/selenium_spec.rb
249
+ - spec/sauce/utilities_spec.rb
233
250
  - spec/sauce_helper.rb
234
251
  - spec/spec_helper.rb
235
252
  - bin/sauce
@@ -247,9 +264,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
247
264
  version: '0'
248
265
  required_rubygems_version: !ruby/object:Gem::Requirement
249
266
  requirements:
250
- - - ! '>'
267
+ - - ! '>='
251
268
  - !ruby/object:Gem::Version
252
- version: 1.3.1
269
+ version: '0'
253
270
  requirements: []
254
271
  rubyforge_project:
255
272
  rubygems_version: 2.0.3
@@ -270,11 +287,13 @@ test_files:
270
287
  - spec/integration/testunit/test/integration_test.rb
271
288
  - spec/parallel_tests/sauce_rspec_runner_spec.rb
272
289
  - spec/sauce/capybara_spec.rb
273
- - spec/sauce/config_spec.rb
290
+ - spec/sauce/config/config_spec.rb
291
+ - spec/sauce/config/environment_config_spec.rb
274
292
  - spec/sauce/cucumber_spec.rb
275
293
  - spec/sauce/driver_pool_spec.rb
276
294
  - spec/sauce/jasmine_spec.rb
277
295
  - spec/sauce/parallel/test_broker_spec.rb
278
296
  - spec/sauce/selenium_spec.rb
297
+ - spec/sauce/utilities_spec.rb
279
298
  - spec/sauce_helper.rb
280
299
  - spec/spec_helper.rb