saucelabs-adapter 0.7.6
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.markdown +150 -0
- data/Rakefile +108 -0
- data/VERSION +1 -0
- data/generators/saucelabs_adapter/saucelabs_adapter_generator.rb +49 -0
- data/generators/saucelabs_adapter/templates/jsunit.rake +62 -0
- data/generators/saucelabs_adapter/templates/jsunit_suite_example.rb +19 -0
- data/generators/saucelabs_adapter/templates/saucelabs_adapter.rake +53 -0
- data/generators/saucelabs_adapter/templates/selenium.yml +66 -0
- data/lib/saucelabs-adapter.rb +1 -0
- data/lib/saucelabs_adapter.rb +6 -0
- data/lib/saucelabs_adapter/jsunit_selenium_support.rb +121 -0
- data/lib/saucelabs_adapter/run_utils.rb +14 -0
- data/lib/saucelabs_adapter/sauce_tunnel.rb +122 -0
- data/lib/saucelabs_adapter/selenium_config.rb +152 -0
- data/lib/saucelabs_adapter/test_unit_adapter.rb +49 -0
- data/lib/saucerest-ruby/gateway.rb +35 -0
- data/lib/saucerest-ruby/saucerest.rb +56 -0
- data/spec/selenium_config_spec.rb +151 -0
- data/test/helper.rb +10 -0
- data/test/test_saucelabs-adapter.rb +10 -0
- metadata +124 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
if defined?(ActiveSupport)
|
2
|
+
puts "[saucelabs-adapter] Inserting ActiveSupport::TestCase before_setup :configure_selenium hook" if ENV['SAUCELABS_ADAPTER_DEBUG']
|
3
|
+
|
4
|
+
module ::ActiveSupport
|
5
|
+
class TestCase
|
6
|
+
setup :configure_selenium # 'before_setup' callback from ActiveSupport::TestCase
|
7
|
+
|
8
|
+
def configure_selenium
|
9
|
+
puts "[saucelabs-adapter] gem is loading..." if ENV['SAUCELABS_ADAPTER_DEBUG']
|
10
|
+
selenium_config = SaucelabsAdapter::SeleniumConfig.new(ENV['SELENIUM_ENV'])
|
11
|
+
if defined?(Polonium)
|
12
|
+
polonium_config = Polonium::Configuration.instance
|
13
|
+
selenium_config.configure_polonium(polonium_config)
|
14
|
+
elsif defined?(Webrat)
|
15
|
+
webrat_config = Webrat.configuration
|
16
|
+
selenium_config.configure_webrat(webrat_config)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
if defined?(Test)
|
24
|
+
puts "[saucelabs-adapter] Inserting Test::Unit::UI::Console::TestRunner attach_to_mediator tunnel start hook" if ENV['SAUCELABS_ADAPTER_DEBUG']
|
25
|
+
|
26
|
+
class Test::Unit::UI::Console::TestRunner
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def attach_to_mediator_with_sauce_tunnel
|
31
|
+
attach_to_mediator_without_sauce_tunnel
|
32
|
+
@selenium_config = SaucelabsAdapter::SeleniumConfig.new(ENV['SELENIUM_ENV'])
|
33
|
+
if @selenium_config.start_sauce_tunnel?
|
34
|
+
@mediator.add_listener(Test::Unit::UI::TestRunnerMediator::STARTED, &method(:setup_tunnel))
|
35
|
+
@mediator.add_listener(Test::Unit::UI::TestRunnerMediator::FINISHED, &method(:teardown_tunnel))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
alias_method_chain :attach_to_mediator, :sauce_tunnel unless private_method_defined?(:attach_to_mediator_without_sauce_tunnel)
|
40
|
+
|
41
|
+
def setup_tunnel(suite_name)
|
42
|
+
@tunnel = SaucelabsAdapter::SauceTunnel.new(@selenium_config)
|
43
|
+
end
|
44
|
+
|
45
|
+
def teardown_tunnel(suite_name)
|
46
|
+
@tunnel.shutdown
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# http://groups.google.com/group/capistrano/browse_thread/thread/455c0c8a6faa9cc8?pli=1
|
2
|
+
class Net::SSH::Gateway
|
3
|
+
# Opens a SSH tunnel from a port on a remote host to a given host and port
|
4
|
+
# on the local side
|
5
|
+
# (equivalent to openssh -R parameter)
|
6
|
+
def open_remote(port, host, remote_port, remote_host = "127.0.0.1")
|
7
|
+
ensure_open!
|
8
|
+
|
9
|
+
@session_mutex.synchronize do
|
10
|
+
@session.forward.remote(port, host, remote_port, remote_host)
|
11
|
+
end
|
12
|
+
|
13
|
+
if block_given?
|
14
|
+
begin
|
15
|
+
yield [remote_port, remote_host]
|
16
|
+
ensure
|
17
|
+
close_remote(remote_port, remote_host)
|
18
|
+
end
|
19
|
+
else
|
20
|
+
return [remote_port, remote_host]
|
21
|
+
end
|
22
|
+
rescue Errno::EADDRINUSE
|
23
|
+
retry
|
24
|
+
end
|
25
|
+
|
26
|
+
# Cancels port-forwarding over an open port that was previously opened via
|
27
|
+
# #open_remote.
|
28
|
+
def close_remote(port, host = "127.0.0.1")
|
29
|
+
ensure_open!
|
30
|
+
|
31
|
+
@session_mutex.synchronize do
|
32
|
+
@session.forward.cancel_remote(port, host)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rest_client'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module SauceREST
|
6
|
+
|
7
|
+
# A simple class for using the Sauce Labs REST API
|
8
|
+
class Client
|
9
|
+
@@roots = {
|
10
|
+
:script => 'scripts',
|
11
|
+
:job => 'jobs',
|
12
|
+
:result => 'results',
|
13
|
+
:tunnel => 'tunnels'
|
14
|
+
}
|
15
|
+
|
16
|
+
def initialize base_url
|
17
|
+
@base_url = base_url
|
18
|
+
@resource = RestClient::Resource.new @base_url
|
19
|
+
end
|
20
|
+
|
21
|
+
def create type, *args
|
22
|
+
doc = args[-1]
|
23
|
+
doc_json = doc.to_json
|
24
|
+
resp_json = @resource[@@roots[type]].post(doc_json,
|
25
|
+
:content_type =>
|
26
|
+
'application/octet-stream')
|
27
|
+
resp = JSON.parse resp_json
|
28
|
+
return resp
|
29
|
+
end
|
30
|
+
|
31
|
+
def get type, docid
|
32
|
+
resp_json = @resource[@@roots[type] + '/' + docid].get
|
33
|
+
resp = JSON.parse resp_json
|
34
|
+
return resp
|
35
|
+
end
|
36
|
+
|
37
|
+
def attach docid, name, data
|
38
|
+
resp_json = @resource[@@roots[:script] + '/' + docid + '/' + name].put data
|
39
|
+
resp = JSON.parse resp_json
|
40
|
+
return resp
|
41
|
+
end
|
42
|
+
|
43
|
+
def delete type, docid
|
44
|
+
resp_json = @resource[@@roots[type] + '/' + docid].delete
|
45
|
+
resp = JSON.parse resp_json
|
46
|
+
return resp
|
47
|
+
end
|
48
|
+
|
49
|
+
def list type
|
50
|
+
resp_json = @resource[@@roots[type] + '/'].get
|
51
|
+
resp = JSON.parse resp_json
|
52
|
+
return resp
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_support/core_ext/object' # for .blank?
|
3
|
+
|
4
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'saucelabs_adapter')
|
5
|
+
SELENIUM_YML_FIXTURE_FILE = File.join(File.dirname(__FILE__), 'fixtures', 'selenium.yml')
|
6
|
+
|
7
|
+
# Doing this to capture args because I seriously doubt we can mock out .new()
|
8
|
+
module Selenium
|
9
|
+
module Client
|
10
|
+
class Driver
|
11
|
+
attr_reader :args
|
12
|
+
def initialize(args)
|
13
|
+
@args = args
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "SeleniumConfig" do
|
20
|
+
|
21
|
+
context "given a local configuration" do
|
22
|
+
before do
|
23
|
+
@selenium_config = SaucelabsAdapter::SeleniumConfig.new('local', SELENIUM_YML_FIXTURE_FILE)
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#start_sauce_tunnel?" do
|
27
|
+
it "should return false" do
|
28
|
+
@selenium_config.start_sauce_tunnel?.should be_false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "selenium_browser_key" do
|
33
|
+
it "should contain just the string from the yml file" do
|
34
|
+
@selenium_config.selenium_browser_key.should == "*chrome /Applications/Firefox.app/Contents/MacOS/firefox-bin"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#configure_polonium" do
|
39
|
+
before do
|
40
|
+
@polonium_configuration = mock("Polonium::Configuration")
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should call the appropriate configuration methods on the polonium configuration object" do
|
44
|
+
@polonium_configuration.should_receive(:'selenium_server_host=').with("127.0.0.1")
|
45
|
+
@polonium_configuration.should_receive(:'selenium_server_port=').with("4444")
|
46
|
+
@polonium_configuration.should_receive(:'browser=').with(@selenium_config.selenium_browser_key)
|
47
|
+
@polonium_configuration.should_receive(:'external_app_server_host=').with("127.0.0.1")
|
48
|
+
@polonium_configuration.should_receive(:'external_app_server_port=').with("4000")
|
49
|
+
|
50
|
+
@selenium_config.configure_polonium(@polonium_configuration)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#configure_webrat" do
|
55
|
+
before do
|
56
|
+
@webrat_configuration = mock("Webrat::Configuration")
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should call the appropriate configuration methods on the webrat configuration object" do
|
60
|
+
@webrat_configuration.should_receive(:'selenium_server_address=').with("127.0.0.1")
|
61
|
+
@webrat_configuration.should_receive(:'selenium_server_port=').with("4444")
|
62
|
+
@webrat_configuration.should_receive(:'selenium_browser_key=').with(@selenium_config.selenium_browser_key)
|
63
|
+
@webrat_configuration.should_receive(:'application_address=').with("127.0.0.1")
|
64
|
+
@webrat_configuration.should_receive(:'application_port=').with("4000")
|
65
|
+
|
66
|
+
@selenium_config.configure_webrat(@webrat_configuration)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "given a saucelabs/firefix/linux configuration" do
|
72
|
+
before do
|
73
|
+
@selenium_config = SaucelabsAdapter::SeleniumConfig.new('stanza_saucelabs_firefox_linux_saucetunnel', SELENIUM_YML_FIXTURE_FILE)
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "#start_sauce_tunnel?" do
|
77
|
+
it "should return true" do
|
78
|
+
@selenium_config.start_sauce_tunnel?.should be_true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "selenium_browser_key" do
|
83
|
+
before do
|
84
|
+
@browser_data = JSON.parse(@selenium_config.selenium_browser_key)
|
85
|
+
end
|
86
|
+
|
87
|
+
{
|
88
|
+
'username' => "YOUR-SAUCELABS-USERNAME",
|
89
|
+
'access-key' => "YOUR-SAUCELABS-ACCESS-KEY",
|
90
|
+
'os' => "Linux",
|
91
|
+
'browser' => "firefox",
|
92
|
+
'browser-version' => "3.",
|
93
|
+
'max-duration' => 1234
|
94
|
+
}.each do |browser_data_key, browser_data_value|
|
95
|
+
it "should contain a #{browser_data_key} of #{browser_data_value}" do
|
96
|
+
@browser_data[browser_data_key].should == browser_data_value
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should contain a job_name of our hostname" do
|
101
|
+
@browser_data['job-name'].should == Socket.gethostname
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "#configure_polonium" do
|
106
|
+
before do
|
107
|
+
@polonium_configuration = mock("Polonium::Configuration")
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should call the appropriate configuration methods on the polonium configuration object" do
|
111
|
+
@polonium_configuration.should_receive(:'selenium_server_host=').with("saucelabs.com")
|
112
|
+
@polonium_configuration.should_receive(:'selenium_server_port=').with("4444")
|
113
|
+
@polonium_configuration.should_receive(:'browser=').with(@selenium_config.selenium_browser_key)
|
114
|
+
@polonium_configuration.should_receive(:'external_app_server_host=').with(@selenium_config.application_address)
|
115
|
+
@polonium_configuration.should_receive(:'external_app_server_port=').with("80")
|
116
|
+
|
117
|
+
@selenium_config.configure_polonium(@polonium_configuration)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "#configure_webrat" do
|
122
|
+
before do
|
123
|
+
@webrat_configuration = mock("Webrat::Configuration")
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should call the appropriate configuration methods on the webrat configuration object" do
|
127
|
+
@webrat_configuration.should_receive(:'selenium_server_address=').with("saucelabs.com")
|
128
|
+
@webrat_configuration.should_receive(:'selenium_server_port=').with("4444")
|
129
|
+
@webrat_configuration.should_receive(:'selenium_browser_key=').with(@selenium_config.selenium_browser_key)
|
130
|
+
@webrat_configuration.should_receive(:'application_address=').with(@selenium_config.application_address)
|
131
|
+
@webrat_configuration.should_receive(:'application_port=').with("80")
|
132
|
+
|
133
|
+
@selenium_config.configure_webrat(@webrat_configuration)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "#create_driver" do
|
138
|
+
before do
|
139
|
+
@driver = @selenium_config.create_driver
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should call Driver.new with the correct arguments" do
|
143
|
+
@driver.args[:host].should == 'saucelabs.com'
|
144
|
+
@driver.args[:port].should == '4444'
|
145
|
+
@driver.args[:browser].should_not be_blank
|
146
|
+
@driver.args[:url].should == "http://#{@selenium_config.application_address}:80"
|
147
|
+
@driver.args[:timeout_in_seconds].should == 600
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestSaucelabsAdapter < Test::Unit::TestCase
|
4
|
+
should "test happy paths" do
|
5
|
+
flunk "Practically, it's usually not useful to unit test stuff like saucelabs adapter. You just end up " +
|
6
|
+
"debugging the implementation and making the tests match. We really should have some happy path tests " +
|
7
|
+
"run under CI which run some dummy happy-path integration tests against the real sauce environment. " +
|
8
|
+
"Unfortunately, we don't have those. Yet."
|
9
|
+
end
|
10
|
+
end
|
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: saucelabs-adapter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.7.6
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kelly Felkins, Chad Woolley & Sam Pierson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-02-18 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rest-client
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.2.0
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: net-ssh
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.0.12
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: net-ssh-gateway
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.0.1
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: selenium-client
|
47
|
+
type: :runtime
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.2.17
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: lsof
|
57
|
+
type: :runtime
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 0.3.0
|
64
|
+
version:
|
65
|
+
description: "This gem augments Test::Unit and Polonium/Webrat to run Selenium tests in the cloud. "
|
66
|
+
email: pair+kelly+sam@pivotallabs.com
|
67
|
+
executables: []
|
68
|
+
|
69
|
+
extensions: []
|
70
|
+
|
71
|
+
extra_rdoc_files:
|
72
|
+
- LICENSE
|
73
|
+
- README.markdown
|
74
|
+
files:
|
75
|
+
- LICENSE
|
76
|
+
- Rakefile
|
77
|
+
- VERSION
|
78
|
+
- generators/saucelabs_adapter/saucelabs_adapter_generator.rb
|
79
|
+
- generators/saucelabs_adapter/templates/jsunit.rake
|
80
|
+
- generators/saucelabs_adapter/templates/jsunit_suite_example.rb
|
81
|
+
- generators/saucelabs_adapter/templates/saucelabs_adapter.rake
|
82
|
+
- generators/saucelabs_adapter/templates/selenium.yml
|
83
|
+
- lib/saucelabs-adapter.rb
|
84
|
+
- lib/saucelabs_adapter.rb
|
85
|
+
- lib/saucelabs_adapter/jsunit_selenium_support.rb
|
86
|
+
- lib/saucelabs_adapter/run_utils.rb
|
87
|
+
- lib/saucelabs_adapter/sauce_tunnel.rb
|
88
|
+
- lib/saucelabs_adapter/selenium_config.rb
|
89
|
+
- lib/saucelabs_adapter/test_unit_adapter.rb
|
90
|
+
- lib/saucerest-ruby/gateway.rb
|
91
|
+
- lib/saucerest-ruby/saucerest.rb
|
92
|
+
- README.markdown
|
93
|
+
has_rdoc: true
|
94
|
+
homepage: http://github.com/pivotal/saucelabs-adapter
|
95
|
+
licenses: []
|
96
|
+
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options:
|
99
|
+
- --charset=UTF-8
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: "0"
|
107
|
+
version:
|
108
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: "0"
|
113
|
+
version:
|
114
|
+
requirements: []
|
115
|
+
|
116
|
+
rubyforge_project:
|
117
|
+
rubygems_version: 1.3.5
|
118
|
+
signing_key:
|
119
|
+
specification_version: 3
|
120
|
+
summary: Adapter for running Selenium tests using SauceLabs.com
|
121
|
+
test_files:
|
122
|
+
- spec/selenium_config_spec.rb
|
123
|
+
- test/helper.rb
|
124
|
+
- test/test_saucelabs-adapter.rb
|