sauce 0.2.2 → 0.3.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.
data/LICENSE CHANGED
@@ -1,20 +1,19 @@
1
1
  Copyright (c) 2009 Sauce Labs Inc
2
2
 
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
10
9
 
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
13
12
 
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.markdown CHANGED
@@ -7,16 +7,17 @@ Features
7
7
  --------
8
8
  Current:
9
9
 
10
- * Treat tunnels like ruby objects. Find/create/destroy
10
+ * ActiveRecord-like interface for tunnels: Find/create/destroy
11
+ * Same with jobs
11
12
 
12
13
  Planned:
13
14
 
14
- * ActiveRecord-like interface for video recordings, jobs logs, reverse tunnels
15
+ * Extend to automatic retrieval of jobs logs, videos, reverse tunnels
15
16
  * Start/stop local instances of Sauce RC
16
17
 
17
18
  Install
18
19
  -------
19
- Make sure you're pulling in gems from gemcutter, and then:
20
+ Make sure you're pulling in gems from http://rubygems.org/, and then:
20
21
 
21
22
  `gem install sauce`
22
23
 
@@ -29,20 +30,21 @@ Here's how to start a tunnel using the Sauce gem
29
30
  account = YAML.load_file "live_account.yml"
30
31
  client = Sauce::Client.new(:username => account["username"],
31
32
  :access_key => account["access_key"])
32
- tunnel = client.create_tunnel('DomainNames' => ["123.456.789.123"])
33
+
34
+ tunnel = client.tunnel.create('DomainNames' => ["example.com"])
33
35
  tunnel.refresh!
34
36
 
35
- client.tunnels # => [#<Sauce::Tunnel:0x1250e6c
36
- @host=nil,
37
- @status="running",
38
- @id="389a1c2a3d49861474c512e9a904be9e",
39
- @client=#<RestClient::Resource:0x1257fb4
40
- @block=nil,
41
- @url="https://username:access_key@saucelabs.com/rest/username/",
42
- @options={}>,
43
- @owner="username">]
44
-
45
- tunnel.destroy # or client.destroy_all_tunnels
37
+ client.tunnels.all # => [#<Sauce::Tunnel:0x1250e6c
38
+ @host=nil,
39
+ @status="running",
40
+ @id="389a1c2a3d49861474c512e9a904be9e",
41
+ @client=#<RestClient::Resource:0x1257fb4
42
+ @block=nil,
43
+ @url="https://username:access_key@saucelabs.com/rest/username/",
44
+ @options={}>,
45
+ @owner="username">]
46
+
47
+ tunnel.destroy
46
48
 
47
49
  Note on Patches/Pull Requests
48
50
  -----------------------------
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.2
1
+ 0.3.0
data/lib/job.rb ADDED
@@ -0,0 +1,135 @@
1
+ require 'net/telnet'
2
+ require 'net/ssh'
3
+ require 'net/ssh/gateway'
4
+ require 'gateway_ext'
5
+
6
+ module Sauce
7
+ # Interact with a Sauce Labs selenium jobs as if it were a ruby object
8
+ class Job
9
+
10
+ #{"BrowserVersion": "3.", "Name": "prsel_./spec/integration/people_a_1_spec.rb", "_rev": "5-228269313", "CreationTime": 1266698090, "AssignmentTime": 1266698097, "Server": "10.212.146.145:4443", "AssignedTo": "f663372ba04444ce8cb3e6f61503f304", "ChefStartTime": 1266698101, "EndTime": 1266698139, "Type": "job", "Interactive": "true", "Status": "complete", "SeleniumServerLogUploadRequest": {"bucket": "sauce-userdata", "key": "sgrove/6337fe576deba0ba278dc1b5dfceac5f/selenium-server.log"}, "Tags": [], "ResultId": "6337fe576deba0ba278dc1b5dfceac5f", "AttachmentRequests": {}, "ModificationTime": 1266698139, "Browser": "firefox", "StartTime": 1266698101, "Owner": "sgrove", "_id": "01fc48caba6d15b46fad79e1b0562bbe", "OS": "Linux", "VideoUploadRequest": {"bucket": "sauce-userdata", "key": "sgrove/6337fe576deba0ba278dc1b5dfceac5f/video.flv"}}
11
+
12
+ attr_accessor :owner, :id, :name, :_rev, :server, :assigned_to, :sauce_type, :interactive, :status,:tags, :result_id
13
+ attr_accessor :selenium_server_log_upload_request, :attachment_requests, :videoupload_request
14
+ attr_accessor :creation_time, :assignment_time, :chef_start_time, :end_time, :modification_time, :start_time
15
+ attr_accessor :os, :browser, :browser_version
16
+
17
+ # TODO: Buckets for logs and videos
18
+
19
+ # Get the class @@client.
20
+ # TODO: Consider metaprogramming this away
21
+ def self.client
22
+ @@client
23
+ end
24
+
25
+ # Set the class @@client.
26
+ # TODO: Consider metaprogramming this away
27
+ def self.client=(client)
28
+ @@client = client
29
+ end
30
+
31
+ # Get the class @@client.
32
+ # TODO: Consider metaprogramming this away
33
+ def self.account
34
+ @@account
35
+ end
36
+
37
+ # Set the class @@client.
38
+ # TODO: Consider metaprogramming this away
39
+ def self.account=(account)
40
+ @@account = account
41
+ end
42
+
43
+ def self.first
44
+ self.all.first
45
+ end
46
+
47
+ def self.last
48
+ self.all.last
49
+ end
50
+
51
+ def self.all
52
+ =begin
53
+ responses = JSON.parse @@client["jobs/recent"].get
54
+ return responses.collect{|response| Sauce::Job.new(response)}
55
+ =end
56
+ return self.complete_jobs + self.in_progress_jobs
57
+ end
58
+
59
+ def self.destroy
60
+ self.all.each { |tunnel| tunnel.destroy }
61
+ end
62
+
63
+ def self.find id
64
+ #puts "GET-URL: #{@@client.url}jobs/#{id}"
65
+ Sauce::Job.new JSON.parse(@@client["jobs/#{id}"].get)
66
+ end
67
+
68
+ def self.complete_jobs
69
+ responses = JSON.parse @@client["complete-jobs"].get
70
+ start = Time.now
71
+ jobs = responses["jobs"].collect{|response| Sauce::Job.find(response["id"])}
72
+ lapsed = Time.now - start
73
+ puts "Took #{lapsed} seconds"
74
+ return jobs
75
+ end
76
+
77
+ def self.in_progress_jobs
78
+ responses = JSON.parse @@client["in-progress-jobs"].get
79
+ return [] if responses == []
80
+ start = Time.now
81
+ jobs = responses["jobs"].collect{|response| Sauce::Job.find(response["id"])}
82
+ lapsed = Time.now - start
83
+ puts "Took #{lapsed} seconds"
84
+ return jobs
85
+ end
86
+
87
+ # Creates an instance representing a job.
88
+ def initialize(options)
89
+ build!(options)
90
+ end
91
+
92
+ # Retrieves the latest information on this job from the Sauce Labs' server
93
+ def refresh!
94
+ response = JSON.parse @@client["jobs/#{@id}"].get
95
+ puts "\tjob refresh with: #{response.inspect}"
96
+ build! response
97
+ self
98
+ end
99
+
100
+ protected
101
+
102
+ # Sets all internal variables from a hash
103
+ def build!(options)
104
+ #puts "\tBuild with #{options.inspect}"
105
+
106
+ @owner = options["Owner"]
107
+ @id = options["_id"]
108
+ @id = options["id"] if @id.nil? or @id.empty?
109
+ @name = options["Name"]
110
+ @_rev = options["_rev"]
111
+ @server = options["Server"]
112
+ @assigned_to = options["AssignedTo"]
113
+
114
+ @sauce_type = options["Type"]
115
+ @interactive = options["Interactive"]
116
+ @status = options["Status"]
117
+ @tags = options["Tags"]
118
+ @result_id = options["ResultId"]
119
+
120
+ @os = options["OS"]
121
+ @browser = options["Browser"]
122
+ @browser_version = options["BrowserVersion"]
123
+
124
+ # TODO: Should this be created_at and updated_at? Probably.
125
+ @creation_time = options["CreationTime"]
126
+ @assignment_time = options["AssignmentTime"]
127
+ @chef_start_time = options["ChefStartTime"]
128
+ @end_time = options["EndTime"]
129
+ @modification_time = options["ModificationTime"]
130
+ @start_time = options["StartTime"]
131
+
132
+ raise NoIDError if @id.nil? or @id.empty?
133
+ end
134
+ end
135
+ end
data/lib/rest.rb CHANGED
@@ -8,7 +8,7 @@ module Sauce
8
8
  class MisconfiguredError < StandardError; end #nodoc
9
9
 
10
10
  attr_accessor :username, :access_key, :client, :ip, :api_url
11
- attr_accessor :tunnels
11
+ attr_accessor :tunnels, :jobs
12
12
 
13
13
  def initialize(options)
14
14
  @username = options[:username]
@@ -24,6 +24,12 @@ module Sauce
24
24
  @tunnels.account = {:username => @username,
25
25
  :access_key => @access_key,
26
26
  :ip => @ip}
27
+
28
+ @jobs = Sauce::Job
29
+ @jobs.client = @client
30
+ @jobs.account = {:username => @username,
31
+ :access_key => @access_key,
32
+ :ip => @ip}
27
33
  end
28
34
  end
29
35
  end
data/lib/sauce.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  require 'tunnel'
2
+ require 'job'
2
3
  require 'rest'
3
4
 
data/lib/tunnel.rb CHANGED
@@ -53,7 +53,7 @@ module Sauce
53
53
  return responses.collect{|response| Sauce::Tunnel.new(response)}
54
54
  end
55
55
 
56
- def self.destroy
56
+ def self.destroy_all
57
57
  self.all.each { |tunnel| tunnel.destroy }
58
58
  end
59
59
 
data/test/test_jobs.rb ADDED
@@ -0,0 +1,58 @@
1
+ require 'helper'
2
+ require 'json'
3
+
4
+ class TestSauce < Test::Unit::TestCase
5
+ context "A jobs instance" do
6
+ setup do
7
+ # Create this file and put in your details to run the tests
8
+ account = YAML.load_file "live_account.yml"
9
+ @username = account["username"]
10
+ @access_key = account["access_key"]
11
+ @ip = account["ip"]
12
+ @client = Sauce::Client.new(:username => @username,
13
+ :access_key => @access_key)
14
+ end
15
+
16
+ should "initialize with passed variables" do
17
+ job_json = JSON.parse '{"BrowserVersion": "3.", "Name": "example_job/name.rb", "_rev": "5-228269313", "CreationTime": 1266698090, "AssignmentTime": 1266698097, "Server": "192.168.0.1:4443", "AssignedTo": "f663372ba04444ce8cb3e6f61503f304", "ChefStartTime": 1266698101, "EndTime": 1266698139, "Type": "job", "Interactive": "true", "Status": "complete", "SeleniumServerLogUploadRequest": {"bucket": "sauce-userdata", "key": "sgrove/6337fe576deba0ba278dc1b5dfceac5f/selenium-server.log"}, "Tags": ["tag_1", "tag_2"], "ResultId": "6337fe576deba0ba278dc1b5dfceac5f", "AttachmentRequests": {}, "ModificationTime": 1266698139, "Browser": "firefox", "StartTime": 1266698101, "Owner": "sgrove", "_id": "01fc48caba6d15b46fad79e1b0562bbe", "OS": "Linux", "VideoUploadRequest": {"bucket": "sauce-userdata", "key": "sgrove/6337fe576deba0ba278dc1b5dfceac5f/video.flv"}}'
18
+
19
+ client = Sauce::Client.new(:username => "test_user",
20
+ :access_key => "abc123")
21
+
22
+ job = client.jobs.new(job_json)
23
+
24
+ assert_equal "sgrove", job.owner
25
+ assert_equal "01fc48caba6d15b46fad79e1b0562bbe", job.id
26
+ assert_equal "example_job/name.rb", job.name
27
+ assert_equal "5-228269313", job._rev
28
+ assert_equal "192.168.0.1:4443", job.server
29
+ assert_equal "f663372ba04444ce8cb3e6f61503f304", job.assigned_to
30
+
31
+ assert_equal "job", job.sauce_type
32
+ assert_equal "true", job.interactive
33
+ assert_equal "complete", job.status
34
+ assert_equal ["tag_1", "tag_2"], job.tags
35
+ assert_equal "6337fe576deba0ba278dc1b5dfceac5f", job.result_id
36
+
37
+ # TODO: Buckets
38
+ #assert_equal , job.selenium_server_log_upload_request
39
+ #assert_equal , job.attachment_requests
40
+ #assert_equal , job.videoupload_request
41
+
42
+ assert_equal "Linux", job.os
43
+ assert_equal "firefox", job.browser
44
+ assert_equal "3.", job.browser_version
45
+
46
+ assert_equal 1266698090, job.creation_time
47
+ assert_equal 1266698097, job.assignment_time
48
+ assert_equal 1266698101, job.chef_start_time
49
+ assert_equal 1266698139, job.end_time
50
+ assert_equal 1266698139, job.modification_time
51
+ assert_equal 1266698101, job.start_time
52
+ end
53
+
54
+ def teardown
55
+ @client.tunnels.destroy
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,83 @@
1
+ require 'helper'
2
+
3
+ class TestSauce < Test::Unit::TestCase
4
+ context "A Client instance" do
5
+ setup do
6
+ # Create this file and put in your details to run the tests
7
+ account = YAML.load_file "live_account.yml"
8
+ @username = account["username"]
9
+ @access_key = account["access_key"]
10
+ @ip = account["ip"]
11
+ @client = Sauce::Client.new(:username => @username,
12
+ :access_key => @access_key)
13
+ @client.tunnels.destroy_all
14
+ end
15
+
16
+ should "initialize with passed variables" do
17
+ client = Sauce::Client.new(:username => "test_user",
18
+ :access_key => "abc123")
19
+ assert_equal client.api_url, "https://test_user:abc123@saucelabs.com/rest/test_user/"
20
+ end
21
+
22
+ should "create a tunnel with the current user" do
23
+ tunnel = @client.tunnels.create('DomainNames' => ["192.168.0.110"])
24
+ tunnel.refresh!
25
+ assert_not_nil tunnel
26
+ assert_equal @username, tunnel.owner
27
+ end
28
+
29
+ should "list current tunnels" do
30
+ @client.tunnels.create('DomainNames' => ["192.168.0.111"])
31
+ @client.tunnels.create('DomainNames' => ["192.168.0.112"])
32
+ @client.tunnels.create('DomainNames' => ["192.168.0.113"])
33
+
34
+ tunnels = @client.tunnels.all
35
+ assert_equal 3, tunnels.select{|t| t.status != "halting"}.count
36
+ end
37
+
38
+ should "destroy a tunnel" do
39
+ tunnel = @client.tunnels.create('DomainNames' => ["192.168.0.114"])
40
+ tunnel.destroy
41
+ assert_equal "halting", tunnel.status
42
+ end
43
+
44
+ should "destroy all tunnels" do
45
+ tunnel = @client.tunnels.create('DomainNames' => ["192.168.0.115"])
46
+ tunnel = @client.tunnels.create('DomainNames' => ["192.168.0.116"])
47
+ tunnel = @client.tunnels.create('DomainNames' => ["192.168.0.117"])
48
+
49
+ @client.tunnels.destroy_all
50
+
51
+ @client.tunnels.all.each do |tunnel|
52
+ assert_equal "halting", tunnel.status
53
+ end
54
+ end
55
+
56
+ should "say hello on port 1025 if healthy" do
57
+ tunnel = @client.tunnels.create('DomainNames' => [@ip])
58
+
59
+ max_retries = 30
60
+ retries = 0
61
+ until tunnel.status == "running" or retries >= max_retries
62
+ sleep 5
63
+ retries += 1
64
+ tunnel.refresh!
65
+ end
66
+
67
+ assert_equal true, tunnel.says_hello?
68
+
69
+ tunnel.destroy # cleanup
70
+ end
71
+
72
+ should "not attempt to telnet if status is not running" do
73
+ tunnel = @client.tunnels.create('DomainNames' => [@ip])
74
+
75
+ tunnel.status = "booting"
76
+ assert_equal false, tunnel.says_hello?
77
+ end
78
+
79
+ def teardown
80
+ @client.tunnels.destroy_all
81
+ end
82
+ end
83
+ end
File without changes
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: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Grove
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-02-22 00:00:00 -08:00
12
+ date: 2010-02-26 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -48,11 +48,13 @@ files:
48
48
  - README.markdown
49
49
  - Rakefile
50
50
  - VERSION
51
+ - lib/job.rb
51
52
  - lib/rest.rb
52
53
  - lib/sauce.rb
53
54
  - lib/tunnel.rb
54
55
  - test/helper.rb
55
- - test/test_sauce.rb
56
+ - test/test_jobs.rb
57
+ - test/test_tunnels.rb
56
58
  has_rdoc: true
57
59
  homepage: http://github.com/sgrove/sauce
58
60
  licenses: []
@@ -85,4 +87,6 @@ test_files:
85
87
  - test/debug.rb
86
88
  - test/helper.rb
87
89
  - test/irb_boot.rb
88
- - test/test_sauce.rb
90
+ - test/test_jobs.rb
91
+ - test/test_tunnels.rb
92
+ - test/test_videos.rb