sauce 1.0.2 → 2.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.
Files changed (56) hide show
  1. data/.document +5 -0
  2. data/.gitignore +30 -0
  3. data/Gemfile +16 -0
  4. data/README.markdown +39 -145
  5. data/Rakefile +46 -20
  6. data/bin/sauce +72 -61
  7. data/gemfiles/rails2.gemfile +10 -0
  8. data/gemfiles/rails2.gemfile.lock +77 -0
  9. data/gemfiles/rails3.gemfile +9 -0
  10. data/gemfiles/rails3.gemfile.lock +137 -0
  11. data/lib/generators/sauce/install/install_generator.rb +1 -2
  12. data/lib/sauce.rb +0 -22
  13. data/lib/sauce/capybara.rb +70 -32
  14. data/lib/sauce/capybara/cucumber.rb +121 -0
  15. data/lib/sauce/config.rb +57 -13
  16. data/lib/sauce/connect.rb +22 -11
  17. data/lib/sauce/integrations.rb +27 -69
  18. data/lib/sauce/jasmine.rb +35 -0
  19. data/lib/sauce/jasmine/rake.rb +47 -0
  20. data/lib/sauce/jasmine/runner.rb +4 -0
  21. data/lib/sauce/job.rb +10 -6
  22. data/lib/sauce/raketasks.rb +0 -21
  23. data/lib/sauce/selenium.rb +9 -18
  24. data/lib/sauce/utilities.rb +0 -17
  25. data/sauce.gemspec +8 -60
  26. data/spec/integration/connect_integration_spec.rb +84 -0
  27. data/spec/sauce/capybara/cucumber_spec.rb +156 -0
  28. data/spec/sauce/capybara/spec_helper.rb +42 -0
  29. data/spec/sauce/capybara_spec.rb +121 -0
  30. data/spec/sauce/config_spec.rb +239 -0
  31. data/spec/sauce/jasmine_spec.rb +49 -0
  32. data/spec/sauce/selenium_spec.rb +57 -0
  33. data/spec/spec_helper.rb +4 -0
  34. data/support/Sauce-Connect.jar +0 -0
  35. data/test/test_integrations.rb +202 -0
  36. data/test/test_testcase.rb +13 -0
  37. metadata +170 -171
  38. data/examples/helper.rb +0 -16
  39. data/examples/other_spec.rb +0 -7
  40. data/examples/saucelabs_spec.rb +0 -12
  41. data/examples/test_saucelabs.rb +0 -13
  42. data/examples/test_saucelabs2.rb +0 -9
  43. data/support/sauce_connect +0 -938
  44. data/support/selenium-server.jar +0 -0
  45. data/support/simplejson/LICENSE.txt +0 -19
  46. data/support/simplejson/__init__.py +0 -437
  47. data/support/simplejson/decoder.py +0 -421
  48. data/support/simplejson/encoder.py +0 -501
  49. data/support/simplejson/ordered_dict.py +0 -119
  50. data/support/simplejson/scanner.py +0 -77
  51. data/support/simplejson/tool.py +0 -39
  52. data/test/test_config.rb +0 -112
  53. data/test/test_connect.rb +0 -45
  54. data/test/test_job.rb +0 -13
  55. data/test/test_selenium.rb +0 -50
  56. data/test/test_selenium2.rb +0 -9
@@ -20,13 +20,6 @@ if defined?(Spec::Rake::SpecTask)
20
20
  Rake::Task["spec:selenium:runtests"].invoke
21
21
  end
22
22
 
23
- desc "Run the Selenium acceptance tests in spec/selenium using a local Selenium server"
24
- task :local => spec_prereq do
25
- with_selenium_rc do
26
- Rake::Task["spec:selenium:runtests"].invoke
27
- end
28
- end
29
-
30
23
  desc "" # Hide it from rake -T
31
24
  Spec::Rake::SpecTask.new :runtests do |t|
32
25
  t.spec_opts = ['--options', "\"#{Rails.root.join('spec', 'spec.opts')}\""]
@@ -54,13 +47,6 @@ if defined?(RSpec::Core::RakeTask)
54
47
  Rake::Task["spec:selenium:runtests"].invoke
55
48
  end
56
49
 
57
- desc "Run the Selenium acceptance tests in spec/selenium using a local Selenium server"
58
- task :local => spec_prereq do
59
- with_selenium_rc do
60
- Rake::Task["spec:selenium:runtests"].invoke
61
- end
62
- end
63
-
64
50
  desc "" # Hide it from rake -T
65
51
  RSpec::Core::RakeTask.new :runtests do |t|
66
52
  spec_glob = ENV["SAUCE_SPEC_GLOB"] || "spec/selenium/**/*_spec.rb"
@@ -80,13 +66,6 @@ if defined?(Rake::TestTask)
80
66
  Rake::Task["test:selenium:runtests"].invoke
81
67
  end
82
68
 
83
- desc "Run the Selenium acceptance tests in spec/selenium using a local Selenium server"
84
- task :local do
85
- with_selenium_rc do
86
- Rake::Task["test:selenium:runtests"].invoke
87
- end
88
- end
89
-
90
69
  Rake::TestTask.new(:runtests) do |t|
91
70
  t.libs << "test"
92
71
  test_glob = ENV["SAUCE_TEST_GLOB"] || "test/selenium/**/*_test.rb"
@@ -1,29 +1,20 @@
1
1
  require "selenium/client"
2
2
  require "selenium/webdriver"
3
3
 
4
- module Sauce
5
- class Selenium < ::Selenium::Client::Driver
6
- def initialize(opts={})
7
- @config = Sauce::Config.new(opts)
8
- super(opts.merge({:host => @config.host, :port => @config.port,
9
- :browser => @config.to_browser_string, :url => @config.browser_url}))
10
- end
11
-
12
- def passed!
13
- self.set_context "sauce:job-result=passed"
14
- end
15
-
16
- def failed!
17
- self.set_context "sauce:job-result=failed"
18
- end
19
- end
4
+ require 'selenium/webdriver/remote/http/persistent'
20
5
 
6
+ module Sauce
21
7
  class Selenium2
8
+ attr_reader :config, :driver
9
+
22
10
  def initialize(opts={})
23
11
  @config = Sauce::Config.new(opts)
24
- http_client = ::Selenium::WebDriver::Remote::Http::Default.new
12
+ http_client = ::Selenium::WebDriver::Remote::Http::Persistent.new
25
13
  http_client.timeout = 300 # Browser launch can take a while
26
- @driver = ::Selenium::WebDriver.for(:remote, :url => "http://#{@config.username}:#{@config.access_key}@#{@config.host}:#{@config.port}/wd/hub", :desired_capabilities => @config.to_desired_capabilities, :http_client => http_client)
14
+ @driver = ::Selenium::WebDriver.for(:remote,
15
+ :url => "http://#{@config.username}:#{@config.access_key}@#{@config.host}:#{@config.port}/wd/hub",
16
+ :desired_capabilities => @config.to_desired_capabilities,
17
+ :http_client => http_client)
27
18
  http_client.timeout = 90 # Once the browser is up, commands should time out reasonably
28
19
  end
29
20
 
@@ -30,23 +30,6 @@ module Sauce
30
30
  end
31
31
  end
32
32
 
33
- def with_selenium_rc
34
- ENV['LOCAL_SELENIUM'] = "true"
35
- STDERR.puts "Starting Selenium RC server on port 4444..."
36
-
37
- jar_file = File.expand_path(File.dirname(__FILE__) + "/../../support/selenium-server.jar")
38
- command = ["java", "-jar", jar_file, "-port", "4444"]
39
- server = ChildProcess.build(*command)
40
- server.start
41
- wait_for_server_on_port(4444)
42
- STDERR.puts "Selenium RC running!"
43
- begin
44
- yield
45
- ensure
46
- Net::HTTP.get("127.0.0.1", "/selenium-server/driver/?cmd=shutDownSeleniumServer", 4444)
47
- end
48
- end
49
-
50
33
  class RailsServer
51
34
  include Sauce::Utilities
52
35
 
data/sauce.gemspec CHANGED
@@ -2,74 +2,23 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{sauce}
5
- s.version = "1.0.2"
5
+ s.version = '2.0.0'
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
- s.authors = ["Eric Allen", "Sean Grove", "Steven Hazel", "Santiago Suarez Ordoñez"]
9
- s.date = %q{2011-07-25}
8
+ s.authors = ["Eric Allen", "Sean Grove", "Steven Hazel", "R. Tyler Croy", "Santiago Suarez Ordoñez"]
9
+ s.date = %q{2012-06-26}
10
10
  s.default_executable = %q{sauce}
11
11
  s.description = %q{A Ruby interface to Sauce OnDemand.}
12
12
  s.email = %q{help@saucelabs.com}
13
13
  s.executables = ["sauce"]
14
- s.files = [
15
- "LICENSE",
16
- "README.markdown",
17
- "Rakefile",
18
- "bin/sauce",
19
- "examples/helper.rb",
20
- "examples/other_spec.rb",
21
- "examples/saucelabs_spec.rb",
22
- "examples/test_saucelabs.rb",
23
- "examples/test_saucelabs2.rb",
24
- "generators/sauce/sauce_generator.rb",
25
- "generators/sauce/templates/sauce.rake",
26
- "lib/generators/sauce/install/install_generator.rb",
27
- "lib/generators/sauce/install/templates/sauce.rake",
28
- "lib/sauce.rb",
29
- "lib/sauce/capybara.rb",
30
- "lib/sauce/client.rb",
31
- "lib/sauce/config.rb",
32
- "lib/sauce/connect.rb",
33
- "lib/sauce/heroku.rb",
34
- "lib/sauce/integrations.rb",
35
- "lib/sauce/job.rb",
36
- "lib/sauce/raketasks.rb",
37
- "lib/sauce/selenium.rb",
38
- "lib/sauce/utilities.rb",
39
- "sauce.gemspec",
40
- "support/sauce_connect",
41
- "support/selenium-server.jar",
42
- "support/simplejson/LICENSE.txt",
43
- "support/simplejson/__init__.py",
44
- "support/simplejson/decoder.py",
45
- "support/simplejson/encoder.py",
46
- "support/simplejson/ordered_dict.py",
47
- "support/simplejson/scanner.py",
48
- "support/simplejson/tool.py",
49
- "test/helper.rb",
50
- "test/test_config.rb",
51
- "test/test_job.rb",
52
- "test/test_connect.rb",
53
- "test/test_selenium.rb",
54
- "test/test_selenium2.rb"
55
- ]
14
+ # Include pretty much everything in Git except the examples/ directory
15
+ s.files = `git ls-files`.split("\n").collect { |f| f unless f.include? 'examples' }.compact
56
16
  s.homepage = %q{http://github.com/saucelabs/sauce_ruby}
57
17
  s.require_paths = ["lib"]
58
- s.rubygems_version = %q{1.4.2}
18
+ s.rubygems_version = %q{2.0.0}
59
19
  s.summary = %q{Ruby access to Sauce Labs' features}
60
- s.test_files = [
61
- "examples/helper.rb",
62
- "examples/other_spec.rb",
63
- "examples/saucelabs_spec.rb",
64
- "examples/test_saucelabs.rb",
65
- "examples/test_saucelabs2.rb",
66
- "test/helper.rb",
67
- "test/test_config.rb",
68
- "test/test_connect.rb",
69
- "test/test_selenium.rb",
70
- "test/test_job.rb",
71
- "test/test_selenium2.rb"
72
- ]
20
+ s.test_files = Dir['test/*.rb']
21
+ s.add_dependency('net-http-persistent')
73
22
 
74
23
  if s.respond_to? :specification_version then
75
24
  s.specification_version = 3
@@ -104,4 +53,3 @@ Gem::Specification.new do |s|
104
53
  s.add_dependency(%q<highline>, [">= 1.5.0"])
105
54
  end
106
55
  end
107
-
@@ -0,0 +1,84 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+
4
+ describe 'Sauce::Connect integration testing' do
5
+ def make_connection
6
+ Sauce::Connect.new({})
7
+ end
8
+
9
+ before :each do
10
+ Sauce.clear_config
11
+ end
12
+
13
+ context 'assuming valid Sauce Labs authentication' do
14
+ # Defining a nil in the let since the before block will run after the let.
15
+ # Running make_connection inside of a `let` block could end up with us
16
+ # using the previous test's Sauce.config. BAD NEWS
17
+ before :each do
18
+ @conn = make_connection
19
+ end
20
+
21
+ it 'should have start with an uninitialized status' do
22
+ @conn.status.should == 'uninitialized'
23
+ end
24
+
25
+ it 'should have a "running" status if the tunnel is connected' do
26
+ @conn.connect
27
+ @conn.wait_until_ready
28
+ @conn.status.should == 'running'
29
+ end
30
+
31
+ after :each do
32
+ @conn.disconnect if @conn
33
+ end
34
+ end
35
+
36
+ context 'assuming an invalid/nonexistent username' do
37
+ before :each do
38
+ Sauce.config do |config|
39
+ config[:username] = nil
40
+ config[:access_key] = nil
41
+ end
42
+ end
43
+
44
+ it 'should fail if the SAUCE_USERNAME is also empty' do
45
+ expect {
46
+ ENV['SAUCE_USERNAME'] = nil
47
+ make_connection
48
+ }.to raise_error(ArgumentError)
49
+ end
50
+
51
+ it 'should fail if the SAUCE_ACCESS_KEY is empty' do
52
+ expect {
53
+ ENV['SAUCE_USERNAME'] = 'testman'
54
+ ENV['SAUCE_ACCESS_KEY'] = nil
55
+ make_connection
56
+ }.to raise_error(ArgumentError)
57
+
58
+ end
59
+
60
+ after :each do
61
+ ENV['SAUCE_USERNAME'] = nil
62
+ end
63
+ end
64
+
65
+ context 'assuming the "fail" username' do
66
+ let(:conn) { Sauce::Connect.new(:host => 'saucelabs.com',
67
+ :port => 80,
68
+ :username => 'fail') }
69
+
70
+ it 'should set the error status' do
71
+ start = Time.now
72
+ conn.connect
73
+ while ((Time.now - start) < 60) && !conn.error
74
+ sleep 0.5
75
+ end
76
+
77
+ conn.error.should_not be nil
78
+ end
79
+
80
+ after :each do
81
+ conn.disconnect
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,156 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+ require 'sauce/capybara'
3
+ require 'sauce/capybara/cucumber'
4
+
5
+ # We need to pull in our local spec_helper.rb to test cucumbery things
6
+ require File.dirname(__FILE__) + '/spec_helper'
7
+
8
+ module Sauce::Capybara
9
+ describe Cucumber do
10
+ include Sauce::Capybara::Cucumber
11
+ include Sauce::Cucumber::SpecHelper
12
+
13
+ describe '#use_sauce_driver' do
14
+ before :each do
15
+ ::Capybara.current_driver = :test
16
+ end
17
+
18
+ it 'should change Capybara.current_driver to :sauce' do
19
+ use_sauce_driver
20
+ ::Capybara.current_driver.should == :sauce
21
+ end
22
+ end
23
+
24
+ describe 'generating job names' do
25
+ context 'with a simple, standard scenario' do
26
+ let(:scenario) do
27
+ s = double('Cucumber::AST::Scenario')
28
+ s.stub(:name).and_return('This is a simple scenario')
29
+ s
30
+ end
31
+ let(:feature) do
32
+ f = double('Cucumber::AST::Feature')
33
+ f.stub(:short_name).and_return('A simple feature')
34
+ f
35
+ end
36
+
37
+ before :each do
38
+ scenario.stub(:feature).and_return(feature)
39
+ end
40
+
41
+ describe '#name_from_scenario' do
42
+ it 'should generated a useful name' do
43
+ expected = 'A simple feature - This is a simple scenario'
44
+ name_from_scenario(scenario).should == expected
45
+ end
46
+ end
47
+
48
+ describe 'jenkins_name_from_scenario' do
49
+ it 'should generate the dotted name the Jenkins plugin wants' do
50
+ expected = 'A simple feature.This is a simple scenario.This is a simple scenario'
51
+ jenkins_name_from_scenario(scenario).should == expected
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ context 'Around hook' do
58
+ let(:session_id) { 'deadbeef' }
59
+ let(:driver) do
60
+ driver = mock('Sauce::Selenium2 Driver')
61
+ driver.stub_chain(:browser, :quit)
62
+ driver.stub_chain(:browser, :session_id).and_return(session_id)
63
+ driver
64
+ end
65
+
66
+ before :each do
67
+ # Need to create our nice mocked Capybara driver
68
+ Capybara.stub_chain(:current_session, :driver).and_return(driver)
69
+ Sauce::Job.stub(:new).and_return(nil)
70
+ end
71
+
72
+ context 'with a scenario outline' do
73
+ before :each do
74
+ $ran_scenario = 0
75
+ end
76
+
77
+ let(:feature) do
78
+ """
79
+ Feature: A dummy feature with a table
80
+ @selenium
81
+ Scenario Outline: Mic check
82
+ Given a <Number>
83
+ When I raise no exceptions
84
+ Examples: Numbers
85
+ | Number |
86
+ | 1 |
87
+ | 2 |
88
+ """
89
+ end
90
+
91
+ it 'should have executed the scenario outline twice' do
92
+ define_steps do
93
+ Given /^a (\d+)$/ do |number|
94
+ $ran_scenario = $ran_scenario + 1
95
+ end
96
+ When /^I raise no exceptions$/ do
97
+ end
98
+ # Set up and invoke our defined Around hook
99
+ Around('@selenium') do |scenario, block|
100
+ # We need to fully reference the module function here due to a
101
+ # change in scoping that will happen to this block courtesy of
102
+ # define_steps
103
+ Sauce::Capybara::Cucumber.around_hook(scenario, block)
104
+ end
105
+ end
106
+
107
+ run_defined_feature feature
108
+ $ran_scenario.should == 2
109
+ end
110
+
111
+ end
112
+
113
+ context 'with a correct scenario' do
114
+ let(:feature) do
115
+ """
116
+ Feature: A dummy feature
117
+ @selenium
118
+ Scenario: A dummy scenario
119
+ Given a scenario
120
+ When I raise no exceptions
121
+ """
122
+ end
123
+
124
+ before :each do
125
+ # Using this gnarly global just because it's easier to just use a
126
+ # global than try to fish the scenario results back out of the
127
+ # Cucumber bits
128
+ $ran_scenario = nil
129
+ end
130
+
131
+ it 'should have executed the feature once' do
132
+ define_steps do
133
+ Given /^a scenario$/ do
134
+ end
135
+ When /^I raise no exceptions$/ do
136
+ $ran_scenario = true
137
+ end
138
+ # Set up and invoke our defined Around hook
139
+ Around('@selenium') do |scenario, block|
140
+ # We need to fully reference the module function here due to a
141
+ # change in scoping that will happen to this block courtesy of
142
+ # define_steps
143
+ Sauce::Capybara::Cucumber.around_hook(scenario, block)
144
+ end
145
+ end
146
+
147
+ # Make sure we actually configure ourselves
148
+ Sauce.should_receive(:config)
149
+ run_defined_feature feature
150
+ $ran_scenario.should be true
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
156
+
@@ -0,0 +1,42 @@
1
+ # NOTE: This file is verbatim "borrowed" from the cucumber source tree:
2
+ # <https://github.com/cucumber/cucumber/blob/master/spec/cucumber/formatter/spec_helper.rb>
3
+
4
+ require 'cucumber'
5
+
6
+ module Sauce
7
+ module Cucumber
8
+ module SpecHelper
9
+ def run_defined_feature(content)
10
+ features = load_features(content || raise("No feature content defined!"))
11
+ run(features)
12
+ end
13
+
14
+ def step_mother
15
+ @step_mother ||= ::Cucumber::Runtime.new
16
+ end
17
+
18
+ def load_features(content)
19
+ feature_file = ::Cucumber::FeatureFile.new('mock.feature', content)
20
+ features = ::Cucumber::Ast::Features.new
21
+ filters = []
22
+ feature = feature_file.parse(filters, {})
23
+ features.add_feature(feature) if feature
24
+ features
25
+ end
26
+
27
+ def run(features)
28
+ configuration = ::Cucumber::Configuration.default
29
+ tree_walker = ::Cucumber::Ast::TreeWalker.new(step_mother, [@formatter], configuration)
30
+ tree_walker.visit_features(features)
31
+ end
32
+
33
+ def define_steps(&block)
34
+ rb = step_mother.load_programming_language('rb')
35
+ dsl = Object.new
36
+ dsl.extend ::Cucumber::RbSupport::RbDsl
37
+ dsl.instance_exec &block
38
+ end
39
+ end
40
+ end
41
+ end
42
+