sauce 0.11.3 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +1 -2
- data/VERSION +1 -1
- data/lib/generators/sauce_generator.rb +40 -0
- data/lib/generators/templates/sauce.rake +1 -0
- data/lib/sauce/integrations.rb +111 -7
- data/lib/sauce/raketasks.rb +44 -2
- data/lib/sauce/utilities.rb +26 -5
- metadata +7 -5
data/README.markdown
CHANGED
@@ -10,13 +10,12 @@ Current:
|
|
10
10
|
* Drop-in replacement for Selenium::Client::Driver that takes care of connecting to Sauce OnDemand
|
11
11
|
* RSpec, Test::Unit, and Rails integration for tests, including automatic setup of Sauce Connect
|
12
12
|
* ActiveRecord-like interface for tunnels and jobs: Find/create/destroy
|
13
|
+
* Start/stop local instances of Sauce RC
|
13
14
|
|
14
15
|
Planned:
|
15
16
|
|
16
|
-
* Include selenium-client RSpec/Test::Unit integration
|
17
17
|
* Webrat integration
|
18
18
|
* Extend to automatic retrieval of jobs logs, videos, reverse tunnels
|
19
|
-
* Start/stop local instances of Sauce RC
|
20
19
|
|
21
20
|
Install
|
22
21
|
-------
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.12.0
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class SauceGenerator < Rails::Generators::Base
|
2
|
+
source_root File.expand_path("../templates", __FILE__)
|
3
|
+
|
4
|
+
argument :username, :type => nil
|
5
|
+
argument :api_key, :type => nil
|
6
|
+
|
7
|
+
def copy_rake_tasks
|
8
|
+
copy_file "sauce.rake", "lib/tasks/sauce.rake"
|
9
|
+
end
|
10
|
+
|
11
|
+
def setup_spec
|
12
|
+
if File.directory? 'spec'
|
13
|
+
empty_directory "spec/selenium"
|
14
|
+
append_file "spec/spec_helper.rb", generate_config
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def setup_test
|
19
|
+
empty_directory "test/selenium"
|
20
|
+
append_file "test/test_helper.rb", generate_config
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def generate_config
|
26
|
+
@random_id ||= rand(100000)
|
27
|
+
return <<-CONFIG
|
28
|
+
require 'sauce'
|
29
|
+
|
30
|
+
Sauce.config do |conf|
|
31
|
+
conf.browser_url = "http://#{@random_id}.test/"
|
32
|
+
conf.browsers = [
|
33
|
+
["Windows 2003", "firefox", "3."]
|
34
|
+
]
|
35
|
+
conf.application_host = "127.0.0.1"
|
36
|
+
conf.application_port = "3001"
|
37
|
+
end
|
38
|
+
CONFIG
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'sauce/raketasks'
|
data/lib/sauce/integrations.rb
CHANGED
@@ -4,10 +4,17 @@ begin
|
|
4
4
|
module RSpec
|
5
5
|
class SeleniumExampleGroup < Spec::Example::ExampleGroup
|
6
6
|
attr_reader :selenium
|
7
|
+
@@need_tunnel = false
|
8
|
+
|
9
|
+
def self.inherited(subclass)
|
10
|
+
# only setup tunnel if somebody needs it
|
11
|
+
@@need_tunnel = true
|
12
|
+
super(subclass)
|
13
|
+
end
|
7
14
|
|
8
15
|
before :suite do
|
9
16
|
config = Sauce::Config.new
|
10
|
-
if config.application_host && !config.local?
|
17
|
+
if @@need_tunnel && config.application_host && !config.local?
|
11
18
|
@@tunnel = Sauce::Connect.new(:host => config.application_host, :port => config.application_port || 80)
|
12
19
|
@@tunnel.wait_until_ready
|
13
20
|
end
|
@@ -46,7 +53,66 @@ begin
|
|
46
53
|
end
|
47
54
|
end
|
48
55
|
rescue LoadError
|
49
|
-
# User doesn't have RSpec installed
|
56
|
+
# User doesn't have RSpec 1.x installed
|
57
|
+
end
|
58
|
+
|
59
|
+
begin
|
60
|
+
require 'rspec'
|
61
|
+
module Sauce
|
62
|
+
module RSpec
|
63
|
+
module SeleniumExampleGroup
|
64
|
+
attr_reader :selenium
|
65
|
+
alias_method :page, :selenium
|
66
|
+
alias_method :s, :selenium
|
67
|
+
|
68
|
+
def self.included(othermod)
|
69
|
+
othermod.around do |the_test|
|
70
|
+
config = Sauce::Config.new
|
71
|
+
description = the_test.metadata[:full_description]
|
72
|
+
config.browsers.each do |os, browser, version|
|
73
|
+
if config.local?
|
74
|
+
@selenium = ::Selenium::Client::Driver.new(:host => "127.0.0.1",
|
75
|
+
:port => 4444,
|
76
|
+
:browser => "*" + browser,
|
77
|
+
:url => "http://127.0.0.1:#{config.local_application_port}/")
|
78
|
+
else
|
79
|
+
@selenium = Sauce::Selenium.new({:os => os, :browser => browser, :browser_version => version,
|
80
|
+
:job_name => "#{description}"})
|
81
|
+
end
|
82
|
+
@selenium.start
|
83
|
+
begin
|
84
|
+
the_test.run
|
85
|
+
ensure
|
86
|
+
@selenium.stop
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
::RSpec.configuration.include(self, :example_group => {
|
93
|
+
:file_path => Regexp.compile('spec[\\\/]selenium')
|
94
|
+
})
|
95
|
+
::RSpec.configuration.before :suite do
|
96
|
+
need_tunnel = false
|
97
|
+
config = Sauce::Config.new
|
98
|
+
if config.application_host && !config.local?
|
99
|
+
need_tunnel = ::RSpec.configuration.settings[:files_to_run].any? {|file| file =~ /spec\/selenium\//}
|
100
|
+
end
|
101
|
+
if need_tunnel
|
102
|
+
@@tunnel = Sauce::Connect.new(:host => config.application_host, :port => config.application_port || 80)
|
103
|
+
@@tunnel.wait_until_ready
|
104
|
+
end
|
105
|
+
end
|
106
|
+
::RSpec.configuration.after :suite do
|
107
|
+
if defined? @@tunnel
|
108
|
+
@@tunnel.disconnect
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
rescue LoadError
|
115
|
+
# User doesn't have RSpec 2.x installed
|
50
116
|
end
|
51
117
|
|
52
118
|
begin
|
@@ -59,7 +125,12 @@ begin
|
|
59
125
|
alias_method :s, :selenium
|
60
126
|
|
61
127
|
def run(*args, &blk)
|
62
|
-
|
128
|
+
if self.respond_to? :name
|
129
|
+
my_name = self.name
|
130
|
+
else
|
131
|
+
my_name = self.__name__
|
132
|
+
end
|
133
|
+
unless my_name =~ /^default_test/
|
63
134
|
config = Sauce::Config.new
|
64
135
|
config.browsers.each do |os, browser, version|
|
65
136
|
if config.local?
|
@@ -69,7 +140,7 @@ begin
|
|
69
140
|
:url => "http://127.0.0.1:#{config.local_application_port}/")
|
70
141
|
else
|
71
142
|
@selenium = Sauce::Selenium.new({:os => os, :browser => browser, :browser_version => version,
|
72
|
-
:job_name => "#{
|
143
|
+
:job_name => "#{my_name}"})
|
73
144
|
end
|
74
145
|
@selenium.start
|
75
146
|
super(*args, &blk)
|
@@ -83,6 +154,10 @@ begin
|
|
83
154
|
end
|
84
155
|
end
|
85
156
|
end
|
157
|
+
rescue LoadError
|
158
|
+
# User doesn't have Test::Unit installed
|
159
|
+
end
|
160
|
+
begin
|
86
161
|
require 'test/unit/ui/console/testrunner'
|
87
162
|
class Test::Unit::UI::Console::TestRunner
|
88
163
|
def attach_to_mediator_with_sauce_tunnel
|
@@ -111,7 +186,31 @@ begin
|
|
111
186
|
end
|
112
187
|
end
|
113
188
|
rescue LoadError
|
114
|
-
# User
|
189
|
+
# User is on Ruby 1.9
|
190
|
+
end
|
191
|
+
|
192
|
+
begin
|
193
|
+
require 'minitest/unit'
|
194
|
+
module MiniTest
|
195
|
+
class Unit
|
196
|
+
run_without_tunnel = self.instance_method(:run)
|
197
|
+
|
198
|
+
define_method(:run) do |args|
|
199
|
+
config = Sauce::Config.new
|
200
|
+
if config.application_host && !config.local?
|
201
|
+
@sauce_tunnel = Sauce::Connect.new(:host => config.application_host, :port => config.application_port || 80)
|
202
|
+
@sauce_tunnel.wait_until_ready
|
203
|
+
end
|
204
|
+
result = run_without_tunnel.bind(self).call(args)
|
205
|
+
if defined? @sauce_tunnel
|
206
|
+
@sauce_tunnel.disconnect
|
207
|
+
end
|
208
|
+
return result
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
rescue LoadError
|
213
|
+
# User is not on Ruby 1.9
|
115
214
|
end
|
116
215
|
|
117
216
|
if defined?(ActiveSupport::TestCase)
|
@@ -123,7 +222,12 @@ if defined?(ActiveSupport::TestCase)
|
|
123
222
|
alias_method :s, :selenium
|
124
223
|
|
125
224
|
def run(*args, &blk)
|
126
|
-
|
225
|
+
if self.respond_to? :name
|
226
|
+
my_name = self.name
|
227
|
+
else
|
228
|
+
my_name = self.__name__
|
229
|
+
end
|
230
|
+
unless my_name =~ /^default_test/
|
127
231
|
config = Sauce::Config.new
|
128
232
|
config.browsers.each do |os, browser, version|
|
129
233
|
if config.local?
|
@@ -133,7 +237,7 @@ if defined?(ActiveSupport::TestCase)
|
|
133
237
|
:url => "http://127.0.0.1:#{config.local_application_port}/")
|
134
238
|
else
|
135
239
|
@selenium = Sauce::Selenium.new({:os => os, :browser => browser, :browser_version => version,
|
136
|
-
:job_name => "#{
|
240
|
+
:job_name => "#{my_name}"})
|
137
241
|
end
|
138
242
|
@selenium.start
|
139
243
|
super(*args, &blk)
|
data/lib/sauce/raketasks.rb
CHANGED
@@ -1,9 +1,15 @@
|
|
1
1
|
require 'sauce'
|
2
2
|
|
3
|
-
spec_prereq = File.exist?(File.join(
|
3
|
+
spec_prereq = File.exist?(File.join(::Rails.root.to_s, 'config', 'database.yml')) ? "db:test:prepare" : :noop
|
4
4
|
task :noop do
|
5
5
|
end
|
6
6
|
|
7
|
+
class Rake::Task
|
8
|
+
def abandon
|
9
|
+
@actions.clear
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
7
13
|
include Sauce::Utilities
|
8
14
|
|
9
15
|
if defined?(Spec::Rake::SpecTask)
|
@@ -27,13 +33,49 @@ if defined?(Spec::Rake::SpecTask)
|
|
27
33
|
|
28
34
|
desc "" # Hide it from rake -T
|
29
35
|
Spec::Rake::SpecTask.new :runtests do |t|
|
30
|
-
t.spec_opts = ['--options', "\"#{
|
36
|
+
t.spec_opts = ['--options', "\"#{Rails.root.join('spec', 'spec.opts')}\""]
|
31
37
|
t.spec_files = FileList["spec/selenium/**/*_spec.rb"]
|
32
38
|
end
|
33
39
|
end
|
34
40
|
|
35
41
|
task :selenium => "selenium:sauce"
|
36
42
|
end
|
43
|
+
|
44
|
+
Rake::Task[:spec].abandon
|
45
|
+
desc "Run all specs in spec directory (excluding plugin specs)"
|
46
|
+
Spec::Rake::SpecTask.new(:spec => spec_prereq) do |t|
|
47
|
+
t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""]
|
48
|
+
t.spec_files = FileList['spec/**/*_spec.rb'].exclude('spec/selenium/*')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
if defined?(RSpec::Core::RakeTask)
|
53
|
+
namespace :spec do
|
54
|
+
namespace :selenium do
|
55
|
+
desc "Run the Selenium acceptance tests in spec/selenium using Sauce OnDemand"
|
56
|
+
task :sauce => spec_prereq do
|
57
|
+
with_rails_server do
|
58
|
+
Rake::Task["spec:selenium:runtests"].invoke
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
desc "Run the Selenium acceptance tests in spec/selenium using a local Selenium server"
|
63
|
+
task :local => spec_prereq do
|
64
|
+
with_rails_server do
|
65
|
+
with_selenium_rc do
|
66
|
+
Rake::Task["spec:selenium:runtests"].invoke
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
desc "" # Hide it from rake -T
|
72
|
+
RSpec::Core::RakeTask.new :runtests do |t|
|
73
|
+
t.pattern = "spec/selenium/**/*_spec.rb"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
task :selenium => "selenium:sauce"
|
78
|
+
end
|
37
79
|
end
|
38
80
|
|
39
81
|
namespace :test do
|
data/lib/sauce/utilities.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
require 'socket'
|
3
|
+
|
1
4
|
module Sauce
|
2
5
|
module Utilities
|
3
6
|
def silence_stream(stream)
|
@@ -9,6 +12,22 @@ module Sauce
|
|
9
12
|
stream.reopen(old_stream)
|
10
13
|
end
|
11
14
|
|
15
|
+
def wait_for_server_on_port(port)
|
16
|
+
while true
|
17
|
+
begin
|
18
|
+
Timeout::timeout(2) do
|
19
|
+
socket = TCPSocket.new('127.0.0.1', port)
|
20
|
+
socket.close unless socket.nil?
|
21
|
+
return
|
22
|
+
end
|
23
|
+
rescue Errno::ECONNREFUSED,
|
24
|
+
Errno::EBADF, # Windows
|
25
|
+
Timeout::Error
|
26
|
+
end
|
27
|
+
sleep 2
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
12
31
|
def with_selenium_rc
|
13
32
|
ENV['LOCAL_SELENIUM'] = "true"
|
14
33
|
STDERR.puts "Starting Selenium RC server on port 4444..."
|
@@ -16,7 +35,7 @@ module Sauce
|
|
16
35
|
server.jar_file = File.expand_path(File.dirname(__FILE__) + "/../../support/selenium-server.jar")
|
17
36
|
silence_stream(STDOUT) do
|
18
37
|
server.start :background => true
|
19
|
-
|
38
|
+
wait_for_server_on_port(4444)
|
20
39
|
end
|
21
40
|
STDERR.puts "Selenium RC running!"
|
22
41
|
begin
|
@@ -28,11 +47,13 @@ module Sauce
|
|
28
47
|
|
29
48
|
def with_rails_server
|
30
49
|
STDERR.puts "Starting Rails server on port 3001..."
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
50
|
+
if File.exists?('script/server')
|
51
|
+
server = IO.popen("ruby script/server RAILS_ENV=test --port 3001 --daemon")
|
52
|
+
elsif File.exists?('script/rails')
|
53
|
+
server = IO.popen("script/rails server -p 3001 -e test")
|
35
54
|
end
|
55
|
+
|
56
|
+
wait_for_server_on_port(3001)
|
36
57
|
STDERR.puts "Rails server running!"
|
37
58
|
begin
|
38
59
|
yield
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sauce
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 47
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 12
|
9
|
+
- 0
|
10
|
+
version: 0.12.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Sean Grove
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2010-12-
|
19
|
+
date: 2010-12-13 00:00:00 -08:00
|
20
20
|
default_executable: sauce
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -147,6 +147,8 @@ files:
|
|
147
147
|
- examples/test_saucelabs2.rb
|
148
148
|
- generators/sauce/sauce_generator.rb
|
149
149
|
- generators/sauce/templates/sauce.rake
|
150
|
+
- lib/generators/sauce_generator.rb
|
151
|
+
- lib/generators/templates/sauce.rake
|
150
152
|
- lib/sauce.rb
|
151
153
|
- lib/sauce/client.rb
|
152
154
|
- lib/sauce/config.rb
|