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/heroku.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Sauce
|
2
|
+
if ENV['SAUCE_ONDEMAND_HEROKU_URL'] and ENV['URL']
|
3
|
+
|
4
|
+
# Heroku Configuation
|
5
|
+
config = JSON.parse RestClient.get(ENV['SAUCE_ONDEMAND_HEROKU_URL']).body
|
6
|
+
Sauce::Selenium_browsers = JSON.parse config["SAUCE_ONDEMAND_BROWSERS"]
|
7
|
+
Sauce::Selenium_url = "#{config['SAUCE_ONDEMAND_PROTOCOL']}#{ENV['URL']}"
|
8
|
+
Sauce::Selenium_host = config["SAUCE_ONDEMAND_SERVER" ]
|
9
|
+
Sauce::Selenium_port = config["SAUCE_ONDEMAND_PORT" ]
|
10
|
+
else
|
11
|
+
|
12
|
+
# Local Configuration
|
13
|
+
Sauce::Selenium_url = ENV['SELENIUM_URL'] || "http://localhost:3000"
|
14
|
+
Sauce::Selenium_host = ENV['SELENIUM_HOST'] || "localhost"
|
15
|
+
Sauce::Selenium_port = ENV['SELENIUM_PORT'] || "4444"
|
16
|
+
Sauce::Selenium_browsers = ENV['SELENIUM_BROWSER'] || ["*firefox"]
|
17
|
+
end
|
18
|
+
end
|
data/lib/sauce/job.rb
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'sauce/client'
|
2
|
+
|
3
|
+
module Sauce
|
4
|
+
# Interact with a Sauce Labs selenium jobs as if it were a ruby object
|
5
|
+
class Job
|
6
|
+
|
7
|
+
class CannotDeleteJobError < StandardError; end #:nodoc
|
8
|
+
|
9
|
+
attr_accessor :id, :owner, :status, :error
|
10
|
+
attr_accessor :name, :browser, :browser_version, :os
|
11
|
+
attr_accessor :creation_time, :start_time, :end_time
|
12
|
+
attr_accessor :public, :video_url, :log_url, :tags
|
13
|
+
attr_accessor :passed, :custom_data
|
14
|
+
|
15
|
+
# Get the class @@client.
|
16
|
+
# TODO: Consider metaprogramming this away
|
17
|
+
def self.client
|
18
|
+
@@client
|
19
|
+
end
|
20
|
+
|
21
|
+
# Set the class @@client.
|
22
|
+
# TODO: Consider metaprogramming this away
|
23
|
+
def self.client=(client)
|
24
|
+
@@client = client
|
25
|
+
end
|
26
|
+
|
27
|
+
# Get the class @@client.
|
28
|
+
# TODO: Consider metaprogramming this away
|
29
|
+
def self.account
|
30
|
+
@@account
|
31
|
+
end
|
32
|
+
|
33
|
+
# Set the class @@client.
|
34
|
+
# TODO: Consider metaprogramming this away
|
35
|
+
def self.account=(account)
|
36
|
+
@@account = account
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.first
|
40
|
+
self.all.first
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.last
|
44
|
+
self.all.last
|
45
|
+
end
|
46
|
+
|
47
|
+
# Misnomer: Gets the most recent 100 jobs
|
48
|
+
# TODO: Allow/automate paging
|
49
|
+
def self.all(options={})
|
50
|
+
url = "jobs"
|
51
|
+
url += "?full=true" if options[:full] #unless options[:id_only]
|
52
|
+
responses = @@client[url].get
|
53
|
+
responses = JSON.parse responses.to_s
|
54
|
+
return responses.collect{|response| Sauce::Job.new(response)}
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.destroy
|
58
|
+
self.all.each { |tunnel| tunnel.destroy }
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.find(options={})
|
62
|
+
if options.class == String
|
63
|
+
id = options
|
64
|
+
elsif options.class == Hash
|
65
|
+
id = options[:id]
|
66
|
+
end
|
67
|
+
|
68
|
+
@@client ||= Sauce::Client.new
|
69
|
+
|
70
|
+
#puts "GET-URL: #{@@client.url}jobs/#{id}"
|
71
|
+
response = @@client["jobs/#{id}"].get
|
72
|
+
|
73
|
+
# TODO: Return nil if bad response
|
74
|
+
Sauce::Job.new JSON.parse(response.to_s)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Creates an instance representing a job.
|
78
|
+
def initialize(options)
|
79
|
+
build!(options)
|
80
|
+
@client = Sauce::Client.new
|
81
|
+
end
|
82
|
+
|
83
|
+
# Retrieves the latest information on this job from the Sauce Labs' server
|
84
|
+
def refresh!
|
85
|
+
response = JSON.parse @@client["jobs/#{@id}"].get.body
|
86
|
+
#puts "\tjob refresh with: #{response}"
|
87
|
+
build! response
|
88
|
+
self
|
89
|
+
end
|
90
|
+
|
91
|
+
# Save/update the current information for the job
|
92
|
+
def save
|
93
|
+
#puts "Saving job:\n -X PUT #{@@client['jobs']}/#{@id} -H 'Content-Type: application/json' -d '#{self.to_json}'"
|
94
|
+
response = @client["jobs/#{@id}"].put(self.to_json,
|
95
|
+
{:content_type => :json,
|
96
|
+
:accept => :json}).body
|
97
|
+
JSON.parse(response)
|
98
|
+
end
|
99
|
+
|
100
|
+
def to_json(options={})
|
101
|
+
json = {
|
102
|
+
:id => @id,
|
103
|
+
:'custom-data' => @custom_data,
|
104
|
+
:owner => @owner,
|
105
|
+
:status => @status,
|
106
|
+
:error => @error,
|
107
|
+
:name => @name,
|
108
|
+
:browser => @browser,
|
109
|
+
:browser_version => @browser_version,
|
110
|
+
:os => @os,
|
111
|
+
:creation_time => @creation_time,
|
112
|
+
:start_time => @start_time,
|
113
|
+
:end_time => @end_time,
|
114
|
+
:video_url => @video_url,
|
115
|
+
:log_url => @log_url,
|
116
|
+
:public => @public,
|
117
|
+
:tags => @tags,
|
118
|
+
:passed => @passed
|
119
|
+
}
|
120
|
+
|
121
|
+
options[:except].each { |key| json.delete(key) } if options[:except]
|
122
|
+
json = json.select { |key,value| options[:only].include? key } if options[:only]
|
123
|
+
|
124
|
+
return json.to_json
|
125
|
+
end
|
126
|
+
|
127
|
+
def delete
|
128
|
+
raise CannonDeleteJobError("Cannot delete jobs via Sauce Labs' REST API currently")
|
129
|
+
end
|
130
|
+
|
131
|
+
protected
|
132
|
+
|
133
|
+
# Sets all internal variables from a hash
|
134
|
+
def build!(options)
|
135
|
+
# Massage JSON
|
136
|
+
options.each { |key,value| options[key] = false if options[key] == "false" }
|
137
|
+
|
138
|
+
@id = options["id"]
|
139
|
+
@owner = options["owner"]
|
140
|
+
@status = options["status"]
|
141
|
+
@error = options["error"]
|
142
|
+
@name = options["name"]
|
143
|
+
@browser = options["browser"]
|
144
|
+
@browser_version = options["browser_version"]
|
145
|
+
@os = options["os"]
|
146
|
+
@creation_time = options["creation_time"].to_i
|
147
|
+
@start_time = options["start_time"].to_i
|
148
|
+
@end_time = options["end_time"].to_i
|
149
|
+
@video_url = options["video_url"]
|
150
|
+
@log_url = options["log_url"]
|
151
|
+
@public = options["public"]
|
152
|
+
@tags = options["tags"]
|
153
|
+
@passed = options["passed"]
|
154
|
+
@custom_data = options['custom-data']
|
155
|
+
|
156
|
+
raise NoIDError if @id.nil? or @id.empty?
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'parallel_tests'
|
2
|
+
|
3
|
+
def start_tunnel_for_parallel_tests(c)
|
4
|
+
c[:start_tunnel] = ParallelTests.first_process?
|
5
|
+
if ParallelTests.first_process?
|
6
|
+
at_exit do
|
7
|
+
if ParallelTests.first_process?
|
8
|
+
ParallelTests.wait_for_other_processes_to_finish
|
9
|
+
end
|
10
|
+
end
|
11
|
+
else
|
12
|
+
while not File.exist? "sauce_connect.ready"
|
13
|
+
sleep 0.5
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require "rest-client"
|
2
|
+
require "json"
|
3
|
+
require "yaml"
|
4
|
+
require "sauce/parallel/test_group"
|
5
|
+
require "thread"
|
6
|
+
|
7
|
+
module Sauce
|
8
|
+
class TestBroker
|
9
|
+
CUCUMBER_CONFIG_FILES = ["./features/support/sauce_helper.rb"]
|
10
|
+
RSPEC_CONFIG_FILES = ["./spec/sauce_helper.rb", "./spec/spec_helper.rb"]
|
11
|
+
|
12
|
+
def self.reset
|
13
|
+
if defined? @@platforms
|
14
|
+
remove_class_variable(:@@platforms)
|
15
|
+
end
|
16
|
+
@groups = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.environment_mutex
|
20
|
+
@@m ||= Mutex.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.next_environment(group)
|
24
|
+
environment_mutex.synchronize do
|
25
|
+
browsers = {}
|
26
|
+
group.each do |file|
|
27
|
+
file = "./" + file
|
28
|
+
test_groups[file] ||= TestGroup.new(self.test_platforms)
|
29
|
+
browsers[file] ||= []
|
30
|
+
browsers[file] << test_groups[file].next_platform
|
31
|
+
end
|
32
|
+
|
33
|
+
on_windows = RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/
|
34
|
+
format_string = on_windows ? "%s" : "'%s'"
|
35
|
+
perfile_browsers = format_string % [JSON.generate(browsers)]
|
36
|
+
|
37
|
+
return {:SAUCE_PERFILE_BROWSERS => perfile_browsers}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.test_groups
|
42
|
+
@groups ||= {}
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.test_groups=(groups)
|
46
|
+
@groups = groups.reduce({}) do |hash, g|
|
47
|
+
hash[g] = TestGroup.new(self.test_platforms)
|
48
|
+
hash
|
49
|
+
end
|
50
|
+
|
51
|
+
@group_indexes = groups.uniq.reduce({}) do |rh, g|
|
52
|
+
rh[g] =(groups.each_index.select {|i| groups[i] == g})
|
53
|
+
rh
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.group_index(group)
|
58
|
+
@group_indexes[group].shift
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.test_platforms(tool=:rspec)
|
62
|
+
unless defined? @@platforms
|
63
|
+
load_sauce_config(tool)
|
64
|
+
@@platforms ||= Sauce.get_config[:browsers]
|
65
|
+
end
|
66
|
+
@@platforms
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.concurrency
|
70
|
+
response = RestClient.get "#{rest_jobs_url}/#{SAUCE_USERNAME}/limits"
|
71
|
+
res = JSON.parse(response)["concurrency"]
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.rest_jobs_url
|
75
|
+
"https://#{AUTH_DETAILS}@saucelabs.com/rest/v1"
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.load_sauce_config(tool=:rspec)
|
79
|
+
case tool
|
80
|
+
when :rspec
|
81
|
+
primary_files = RSPEC_CONFIG_FILES
|
82
|
+
secondary_files = CUCUMBER_CONFIG_FILES
|
83
|
+
when :cucumber
|
84
|
+
primary_files = CUCUMBER_CONFIG_FILES
|
85
|
+
secondary_files = RSPEC_CONFIG_FILES
|
86
|
+
end
|
87
|
+
|
88
|
+
configuration_file = self.find_config_file(primary_files, secondary_files)
|
89
|
+
unless configuration_file
|
90
|
+
possible_config_files = primary_files + secondary_files
|
91
|
+
error_message = "Could not find Sauce configuration. Please make sure one of the following files exists:\n"
|
92
|
+
error_message << possible_config_files.map { |file_path| " - #{file_path}" }.join("\n")
|
93
|
+
raise error_message
|
94
|
+
end
|
95
|
+
require configuration_file
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.find_config_file(primary_files, secondary_files)
|
99
|
+
find_in_file_list(primary_files) || find_in_file_list(secondary_files)
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.find_in_file_list(list)
|
103
|
+
list.find { |file_path| File.exists?(file_path) }
|
104
|
+
end
|
105
|
+
|
106
|
+
SAUCE_USERNAME = ENV["SAUCE_USERNAME"]
|
107
|
+
SAUCE_ACCESS_KEY = ENV["SAUCE_ACCESS_KEY"]
|
108
|
+
AUTH_DETAILS = "#{SAUCE_USERNAME}:#{SAUCE_ACCESS_KEY}"
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Sauce
|
2
|
+
class TestGroup
|
3
|
+
def initialize(platforms)
|
4
|
+
@platforms = platforms
|
5
|
+
@index = 0
|
6
|
+
end
|
7
|
+
|
8
|
+
def next_platform
|
9
|
+
platform = @platforms[@index]
|
10
|
+
@index += 1
|
11
|
+
begin
|
12
|
+
caps ={
|
13
|
+
'os' => platform[0],
|
14
|
+
'browser' => platform[1],
|
15
|
+
'version' => platform[2]
|
16
|
+
}
|
17
|
+
caps.merge!({:caps => platform[3]}) if platform[3]
|
18
|
+
caps
|
19
|
+
rescue NoMethodError => e
|
20
|
+
puts "I don't have any config"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'sauce'
|
2
|
+
|
3
|
+
spec_prereq = File.exist?(File.join(::Rails.root.to_s, 'config', 'database.yml')) ? "db:test:prepare" : :noop
|
4
|
+
task :noop do
|
5
|
+
end
|
6
|
+
|
7
|
+
class Rake::Task
|
8
|
+
def abandon
|
9
|
+
@actions.clear
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
include Sauce::Utilities
|
14
|
+
|
15
|
+
if defined?(Spec::Rake::SpecTask)
|
16
|
+
namespace :spec do
|
17
|
+
namespace :selenium do
|
18
|
+
desc "Run the Selenium acceptance tests in spec/selenium using Sauce OnDemand"
|
19
|
+
task :sauce => spec_prereq do
|
20
|
+
Rake::Task["spec:selenium:runtests"].invoke
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "" # Hide it from rake -T
|
24
|
+
Spec::Rake::SpecTask.new :runtests do |t|
|
25
|
+
t.spec_opts = ['--options', "\"#{Rails.root.join('spec', 'spec.opts')}\""]
|
26
|
+
spec_glob = ENV["SAUCE_SPEC_GLOB"] || "spec/selenium/**/*_spec.rb"
|
27
|
+
t.spec_files = FileList[spec_glob]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
task :selenium => "selenium:sauce"
|
32
|
+
end
|
33
|
+
|
34
|
+
Rake::Task[:spec].abandon
|
35
|
+
desc "Run all specs in spec directory (excluding plugin specs)"
|
36
|
+
Spec::Rake::SpecTask.new(:spec => spec_prereq) do |t|
|
37
|
+
t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""]
|
38
|
+
t.spec_files = FileList['spec/**/*_spec.rb'].exclude('spec/selenium/*')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
if defined?(RSpec::Core::RakeTask)
|
43
|
+
namespace :spec do
|
44
|
+
namespace :selenium do
|
45
|
+
desc "Run the Selenium acceptance tests in spec/selenium using Sauce OnDemand"
|
46
|
+
task :sauce => spec_prereq do
|
47
|
+
Rake::Task["spec:selenium:runtests"].invoke
|
48
|
+
end
|
49
|
+
|
50
|
+
desc "" # Hide it from rake -T
|
51
|
+
RSpec::Core::RakeTask.new :runtests do |t|
|
52
|
+
spec_glob = ENV["SAUCE_SPEC_GLOB"] || "spec/selenium/**/*_spec.rb"
|
53
|
+
t.pattern = spec_glob
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
task :selenium => "selenium:sauce"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
if defined?(Rake::TestTask)
|
62
|
+
namespace :test do
|
63
|
+
namespace :selenium do
|
64
|
+
desc "Run the Selenium acceptance tests in test/selenium using Sauce OnDemand"
|
65
|
+
task :sauce do
|
66
|
+
Rake::Task["test:selenium:runtests"].invoke
|
67
|
+
end
|
68
|
+
|
69
|
+
Rake::TestTask.new(:runtests) do |t|
|
70
|
+
t.libs << "test"
|
71
|
+
test_glob = ENV["SAUCE_TEST_GLOB"] || "test/selenium/**/*_test.rb"
|
72
|
+
t.pattern = test_glob
|
73
|
+
t.verbose = true
|
74
|
+
end
|
75
|
+
# Hide it from rake -T
|
76
|
+
Rake::Task['test:selenium:runtests'].instance_variable_set(:@full_comment, nil)
|
77
|
+
Rake::Task['test:selenium:runtests'].instance_variable_set(:@comment, nil)
|
78
|
+
Rake::Task['test:selenium:runtests'].enhance(["db:test:prepare"])
|
79
|
+
end
|
80
|
+
|
81
|
+
task :selenium => "selenium:sauce"
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'sauce/utilities'
|
2
|
+
require 'sauce_whisk'
|
3
|
+
require 'sauce/rspec/rspec_one_support'
|
4
|
+
require 'sauce/rspec/rspec_formatter'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'rspec/core'
|
8
|
+
module Sauce
|
9
|
+
module RSpec
|
10
|
+
@@server = nil
|
11
|
+
|
12
|
+
def self.server
|
13
|
+
return @@server
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.server=(s)
|
17
|
+
@@server = s
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.setup_environment
|
21
|
+
::RSpec.configuration.before(:all, :sauce => true) do
|
22
|
+
Sauce::RSpec.start_tools_for_sauce_tag
|
23
|
+
end
|
24
|
+
|
25
|
+
::RSpec.configuration.before :all do
|
26
|
+
Sauce::RSpec.start_tools_for_selenium_directory
|
27
|
+
Sauce::RSpec.register_default_hook
|
28
|
+
Sauce::RSpec.register_jenkins_hook if ENV['JENKINS_SERVER_COOKIE']
|
29
|
+
end
|
30
|
+
|
31
|
+
::RSpec.configuration.after :suite do
|
32
|
+
Sauce::RSpec.stop_tools
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.start_tools_for_sauce_tag
|
37
|
+
config = Sauce::Config.new
|
38
|
+
if config[:start_tunnel]
|
39
|
+
Sauce::Utilities::Connect.start_from_config(config)
|
40
|
+
end
|
41
|
+
|
42
|
+
unless self.server
|
43
|
+
self.server= Sauce::Utilities::RailsServer.start_if_required(config)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.start_tools_for_selenium_directory
|
48
|
+
config = Sauce::Config.new
|
49
|
+
# TODO: Check which rspec version this changed in -- If < 2, change.
|
50
|
+
files_to_run = ::RSpec.configuration.respond_to?(:files_to_run) ? ::RSpec.configuration.files_to_run :
|
51
|
+
::RSpec.configuration.settings[:files_to_run]
|
52
|
+
|
53
|
+
running_selenium_specs = files_to_run.any? {|file| file =~ /spec\/selenium\//}
|
54
|
+
need_tunnel = running_selenium_specs && config[:application_host]
|
55
|
+
|
56
|
+
if need_tunnel && config[:start_tunnel]
|
57
|
+
Sauce::Utilities::Connect.start_from_config(config)
|
58
|
+
end
|
59
|
+
|
60
|
+
if running_selenium_specs
|
61
|
+
unless self.server
|
62
|
+
self.server= Sauce::Utilities::RailsServer.start_if_required(config)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.register_default_hook
|
68
|
+
Sauce.config do |c|
|
69
|
+
c.after_job :rspec do |id, platform, name, success|
|
70
|
+
SauceWhisk::Jobs.change_status id, success
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.register_jenkins_hook
|
76
|
+
Sauce.config do |c|
|
77
|
+
c.after_job :jenkins do |id, platform, name, success|
|
78
|
+
puts "SauceOnDemandSessionID=#{id} job-name=#{name}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.stop_tools
|
84
|
+
Sauce::Utilities::Connect.close
|
85
|
+
server.stop if self.server
|
86
|
+
Sauce::Utilities.warn_if_suspect_misconfiguration
|
87
|
+
end
|
88
|
+
|
89
|
+
module SeleniumExampleGroup
|
90
|
+
include Sauce::TestBase
|
91
|
+
attr_reader :selenium
|
92
|
+
alias_method :s, :selenium
|
93
|
+
|
94
|
+
def self.rspec_current_example
|
95
|
+
lambda { |context| ::RSpec.current_example }
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.context_example
|
99
|
+
lambda { |context| context.example }
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.find_example_method
|
103
|
+
::RSpec.respond_to?(:current_example) ? rspec_current_example : context_example
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.current_example
|
107
|
+
@@current_example_fetcher ||= find_example_method
|
108
|
+
end
|
109
|
+
|
110
|
+
# TODO V4 -- Remove this entirely
|
111
|
+
def page
|
112
|
+
if self.class.included_modules.any? {|m| m.name == 'Capybara::DSL'}
|
113
|
+
::Capybara.current_session
|
114
|
+
else
|
115
|
+
warn Sauce::Utilities.page_deprecation_message
|
116
|
+
@selenium
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.included(othermod)
|
121
|
+
othermod.around do |the_test|
|
122
|
+
config = Sauce::Config.new
|
123
|
+
description = the_test.metadata[:full_description]
|
124
|
+
file = the_test.metadata[:file_path]
|
125
|
+
exceptions = {}
|
126
|
+
test_each config.caps_for_location(file), description do |selenium, caps|
|
127
|
+
|
128
|
+
example = SeleniumExampleGroup.current_example.call(self)
|
129
|
+
example.instance_variable_set(:@exception, nil)
|
130
|
+
|
131
|
+
@selenium = selenium
|
132
|
+
Sauce.driver_pool[Thread.current.object_id] = @selenium
|
133
|
+
example.metadata[:sauce_public_link] = SauceWhisk.public_link(@selenium.session_id)
|
134
|
+
|
135
|
+
begin
|
136
|
+
the_test.run
|
137
|
+
success = example.exception.nil?
|
138
|
+
ensure
|
139
|
+
@selenium.stop
|
140
|
+
begin
|
141
|
+
os = caps[:os]
|
142
|
+
browser = caps[:browser]
|
143
|
+
version = caps[:version]
|
144
|
+
unless success
|
145
|
+
exceptions["#{os} - #{browser} #{version}"] = example.exception
|
146
|
+
end
|
147
|
+
platform = {:os => os, :browser => browser, :version => version}
|
148
|
+
config.run_post_job_hooks(@selenium.session_id, platform, description, success)
|
149
|
+
rescue Exception => e
|
150
|
+
STDERR.puts "Error running post job hooks"
|
151
|
+
STDERR.puts e
|
152
|
+
end
|
153
|
+
Sauce.driver_pool.delete Thread.current.object_id
|
154
|
+
end
|
155
|
+
if (exceptions.length > 0)
|
156
|
+
example.instance_variable_set(:@exception, exceptions.first[1])
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.inclusion_params
|
163
|
+
params = [self]
|
164
|
+
gem_version = Gem::Version.new ::RSpec::Core::Version::STRING
|
165
|
+
file_path_hash = {:file_path => Regexp.compile('spec[\\\/]selenium')}
|
166
|
+
if (gem_version >= Gem::Version.new('2.99.0'))
|
167
|
+
params = params + [file_path_hash]
|
168
|
+
else
|
169
|
+
params = params + [{:example_group => file_path_hash}]
|
170
|
+
end
|
171
|
+
params
|
172
|
+
end
|
173
|
+
|
174
|
+
::RSpec.configuration.include(*self.inclusion_params)
|
175
|
+
::RSpec.configuration.include(self, :sauce => true)
|
176
|
+
|
177
|
+
Sauce::RSpec.setup_environment
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
rescue LoadError, TypeError
|
182
|
+
# User doesn't have RSpec 2.x installed
|
183
|
+
rescue => e
|
184
|
+
STDERR.puts "Exception caught: #{e.to_s}"
|
185
|
+
exit 1
|
186
|
+
end
|