sauce 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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