testdroid-api-client 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,126 +1,169 @@
1
1
  module TestdroidAPI
2
2
 
3
- class Client
4
- attr_reader :config
5
- attr_accessor :logger
6
- attr_reader :token
7
-
8
- API_VERSION = 'api/v2'
9
- CLOUD_ENDPOINT='https://cloud.testdroid.com'
10
- ACCEPT_HEADERS={'Accept' => 'application/json'}
11
-
12
- def initialize(username, password, cloud_url = CLOUD_ENDPOINT, logger = nil)
13
- # Instance variables
14
- @username = username
15
- @password = password
16
- @cloud_url = cloud_url
17
- @logger = logger
18
-
19
- if @logger.nil?
20
- @logger = Logger.new(STDOUT)
21
- @logger.info("Logger is not defined => output to STDOUT")
22
- end
23
- end
24
- def label_groups
25
- label_groups = TestdroidAPI::LabelGroups.new( "/#{API_VERSION}/label-groups", self )
26
- label_groups.list
27
- label_groups
28
- end
29
- def devices
30
- devices = TestdroidAPI::Devices.new( "/#{API_VERSION}/devices", self )
31
- devices.list
32
- devices
33
- end
34
- def authorize
35
-
36
- @client = OAuth2::Client.new('testdroid-cloud-api', nil, :site => @cloud_url, :authorize_url => 'oauth/authorize',
37
- :token_url => 'oauth/token', :headers => ACCEPT_HEADERS) do |faraday|
38
- faraday.request :multipart
39
- faraday.request :url_encoded
40
- faraday.response :logger, @logger
41
- faraday.adapter Faraday.default_adapter
42
- end
43
-
44
- @token = @client.password.get_token(@username, @password, :headers => ACCEPT_HEADERS)
45
-
46
- if (@cloud_user.nil?)
47
- @cloud_user = TestdroidAPI::User.new( "/#{API_VERSION}/me", self ).refresh
48
- @cloud_user = TestdroidAPI::User.new( "/#{API_VERSION}/users/#{@cloud_user.id}", self ).refresh
49
-
50
- end
51
- @cloud_user
52
- end
53
- def upload(uri, filename, file_type)
54
- begin
55
- @token = @token.refresh!(:headers => ACCEPT_HEADERS) if @token.expired?
56
- connection = @token.client.connection
57
- payload = {:file => Faraday::UploadIO.new(filename, file_type) }
58
- headers = ACCEPT_HEADERS.merge(@token.headers)
59
- response = connection.post(@cloud_url+"#{uri}",payload, headers)
60
- rescue => e
61
- @logger.error e
62
- return nil
63
- end
64
- JSON.parse(response.body)
65
- end
66
- def post(uri, params)
67
-
68
- @token = @token.refresh!(:headers => ACCEPT_HEADERS) if @token.expired?
69
-
70
- begin
71
- resp = @token.post("#{@cloud_url}#{uri}", params.merge(:headers => ACCEPT_HEADERS))
72
- rescue => e
73
- @logger.error "Failed to post resource #{uri} #{e}"
74
- return nil
75
- end
76
-
77
- if resp.body.nil? || resp.body.length == 0
78
- return nil
79
- end
80
-
81
- JSON.parse(resp.body)
82
- end
83
- def get(uri, params={})
84
-
85
- @token = @token.refresh!(:headers => ACCEPT_HEADERS) if @token.expired?
86
-
87
- begin
88
- resp = @token.get(@cloud_url+"#{uri}", params.merge(:headers => ACCEPT_HEADERS))
89
- rescue => e
90
- @logger.error "Failed to get resource #{uri} #{e}"
91
- return nil
92
- end
93
- JSON.parse(resp.body)
94
- end
95
- def delete(uri)
96
-
97
- @token = @token.refresh!(:headers => ACCEPT_HEADERS) if @token.expired?
98
-
99
- begin
100
- resp = @token.delete(@cloud_url+"#{uri}", :headers => ACCEPT_HEADERS )
101
- rescue => e
102
- @logger.error "Failed to delete resource #{uri} #{e}"
103
- return nil
104
- end
105
-
106
- if (resp.status != 204)
107
- @logger.error "Failed to delete resource #{uri} #{e}"
108
- return nil
109
- else
110
- @logger.info "response: #{resp.status}"
111
- end
112
- end
113
- def download(uri, file_name)
114
- begin
115
- @token = @token.refresh!(:headers => ACCEPT_HEADERS) if @token.expired?
116
- File.open(file_name, "w+b") do |file|
117
- resp = @token.get("#{@cloud_url}/#{uri}", :headers => ACCEPT_HEADERS)
118
- file.write(resp.body)
119
- end
120
- rescue => e
121
- @logger.error "Failed to get resource #{uri} #{e}"
122
- return nil
123
- end
124
- end
125
- end
3
+ class Client
4
+ attr_reader :config
5
+ attr_accessor :logger
6
+ attr_reader :token
7
+
8
+ API_VERSION = 'api/v2'
9
+ CLOUD_ENDPOINT='https://cloud.testdroid.com'
10
+ ACCEPT_HEADERS={'Accept' => 'application/json'}
11
+
12
+ def initialize(username, password, cloud_url = CLOUD_ENDPOINT, logger = nil)
13
+ # Instance variables
14
+ @username = username
15
+ @password = password
16
+ @cloud_url = cloud_url
17
+ @logger = logger
18
+
19
+ if @logger.nil?
20
+ @logger = Logger.new(STDOUT)
21
+ @logger.info("Logger is not defined => output to STDOUT")
22
+ end
23
+ end
24
+ def label_groups
25
+ label_groups = TestdroidAPI::LabelGroups.new( "/#{API_VERSION}/label-groups", self )
26
+ label_groups.list
27
+ label_groups
28
+ end
29
+ def devices
30
+ devices = TestdroidAPI::Devices.new( "/#{API_VERSION}/devices", self )
31
+ devices.list
32
+ devices
33
+ end
34
+ def authorize
35
+
36
+ @client = OAuth2::Client.new('testdroid-cloud-api', nil, :site => @cloud_url, :authorize_url => 'oauth/authorize',
37
+ :token_url => 'oauth/token', :headers => ACCEPT_HEADERS) do |faraday|
38
+ faraday.request :multipart
39
+ faraday.request :url_encoded
40
+ faraday.response :logger, @logger
41
+ faraday.adapter Faraday.default_adapter
42
+ end
43
+
44
+ @token = @client.password.get_token(@username, @password, :headers => ACCEPT_HEADERS)
45
+
46
+ if (@cloud_user.nil?)
47
+ @cloud_user = TestdroidAPI::User.new( "/#{API_VERSION}/me", self ).refresh
48
+ @cloud_user = TestdroidAPI::User.new( "/#{API_VERSION}/users/#{@cloud_user.id}", self ).refresh
49
+
50
+ end
51
+ @cloud_user
52
+ end
53
+
54
+ def mime_for(path)
55
+ mime = MIME::Types.type_for path
56
+ mime.empty? ? 'text/plain' : mime[0].content_type
57
+ end
58
+
59
+ def upload(uri, filename)
60
+ begin
61
+ @token = @token.refresh!(:headers => ACCEPT_HEADERS) if @token.expired?
62
+ connection = @token.client.connection
63
+ payload = {:file => Faraday::UploadIO.new(filename, mime_for(filename)) }
64
+ headers = ACCEPT_HEADERS.merge(@token.headers)
65
+ response = connection.post(@cloud_url+"#{uri}",payload, headers)
66
+ rescue => e
67
+ @logger.error e
68
+ return nil
69
+ end
70
+ JSON.parse(response.body)
71
+ end
72
+ def post(uri, params)
73
+
74
+ @token = @token.refresh!(:headers => ACCEPT_HEADERS) if @token.expired?
75
+
76
+ begin
77
+ resp = @token.post("#{@cloud_url}#{uri}", params.merge(:headers => ACCEPT_HEADERS))
78
+ rescue => e
79
+ @logger.error "Failed to post resource #{uri} #{e}"
80
+ return nil
81
+ end
82
+
83
+ if resp.body.nil? || resp.body.length == 0
84
+ return nil
85
+ end
86
+
87
+ JSON.parse(resp.body)
88
+ end
89
+ def get(uri, params={})
90
+
91
+ @token = @token.refresh!(:headers => ACCEPT_HEADERS) if @token.expired?
92
+
93
+ begin
94
+ resp = @token.get(@cloud_url+"#{uri}", params.merge(:headers => ACCEPT_HEADERS))
95
+ rescue => e
96
+ @logger.error "Failed to get resource #{uri} #{e}"
97
+ return nil
98
+ end
99
+ JSON.parse(resp.body)
100
+ end
101
+ def delete(uri)
102
+
103
+ @token = @token.refresh!(:headers => ACCEPT_HEADERS) if @token.expired?
104
+
105
+ begin
106
+ resp = @token.delete(@cloud_url+"#{uri}", :headers => ACCEPT_HEADERS )
107
+ rescue => e
108
+ @logger.error "Failed to delete resource #{uri} #{e}"
109
+ return nil
110
+ end
111
+
112
+ if (resp.status != 204)
113
+ @logger.error "Failed to delete resource #{uri} #{e}"
114
+ return nil
115
+ else
116
+ @logger.info "response: #{resp.status}"
117
+ end
118
+ end
119
+ def download(uri, file_name)
120
+ begin
121
+ @token = @token.refresh!(:headers => ACCEPT_HEADERS) if @token.expired?
122
+ File.open(file_name, "w+b") do |file|
123
+ resp = @token.get("#{@cloud_url}/#{uri}", :headers => ACCEPT_HEADERS)
124
+ file.write(resp.body)
125
+ end
126
+ rescue => e
127
+ @logger.error "Failed to get resource #{uri} #{e}"
128
+ return nil
129
+ end
130
+ end
131
+
132
+ # Resources
133
+
134
+ # public read-only
135
+
136
+ def info
137
+ TestdroidAPI::CloudResource.new("/#{API_VERSION}/info", self, "info")
138
+ end
139
+
140
+ def devices
141
+ TestdroidAPI::Devices.new("/#{API_VERSION}/devices", self)
142
+ end
143
+
144
+ def label_groups
145
+ TestdroidAPI::LabelGroups.new("/#{API_VERSION}/label-groups", self)
146
+ end
147
+
148
+ # user read-write
149
+
150
+ def me
151
+ TestdroidAPI::User.new("/#{API_VERSION}/me", self).load
152
+ end
153
+
154
+ def properties
155
+ TestdroidAPI::Properties.new("/#{API_VERSION}/properties", self)
156
+ end
157
+
158
+ def device_session_connections
159
+ TestdroidAPI::DeviceSessionConnections.new("/#{API_VERSION}/device-session-connections", self)
160
+ end
161
+
162
+ # admin only
163
+
164
+ def admin
165
+ TestdroidAPI::Admin.new("/#{API_VERSION}/admin", self)
166
+ end
167
+
168
+ end
126
169
  end
@@ -1,83 +1,86 @@
1
-
2
1
  module TestdroidAPI
3
- class CloudListResource
2
+ class CloudListResource
3
+
4
+ def initialize(uri, client, instance_class=nil)
5
+ @uri, @client = uri, client
6
+ resource_name = self.class.name.split('::')[-1]
7
+ @instance_class = TestdroidAPI.const_get( instance_class.nil? ? resource_name.chop : instance_class )
8
+ @list_key, @instance_id_key = resource_name.gsub!(/\b\w/) { $&.downcase }, 'id'
9
+ end
10
+
11
+ def get(resource_id)
12
+ @instance_class.new("#{@uri}/#{resource_id}", @client)
13
+ end
14
+
15
+ def total
16
+
17
+ @client.get(@uri)['total']
18
+ end
4
19
 
5
- def initialize(uri, client)
6
- @uri, @client = uri, client
7
- resource_name = self.class.name.split('::')[-1]
8
- @instance_class = TestdroidAPI.const_get resource_name.chop
9
- @list_key, @instance_id_key = resource_name.gsub!(/\b\w/) { $&.downcase } , 'id'
10
- end
11
- def get(resource_id)
12
- @instance_class.new( "#{@uri}/#{resource_id}", @client)
13
- end
14
- def total
20
+ def create(params={}, http_params={})
21
+ raise "Can't create a resource without a REST Client" unless @client
22
+ response = @client.post @uri, params
23
+ @instance_class.new "#{@uri}/#{response[@instance_id_key]}", @client,
24
+ response
25
+ end
15
26
 
16
- @client.get(@uri)['total']
17
- end
18
- def create(params={})
19
- raise "Can't create a resource without a REST Client" unless @client
20
- response = @client.post @uri, params
21
- @instance_class.new "#{@uri}/#{response[@instance_id_key]}", @client,
22
- response
23
- end
24
- def list_all()
25
- raise "Can't get a resource list without a REST Client" unless @client
27
+ def list_all()
28
+ raise "Can't get a resource list without a REST Client" unless @client
26
29
 
27
- response = @client.get("#{@uri}?limit=355043550", {})
30
+ response = @client.get(@uri, {:limit => 0})
28
31
 
29
- if response['data'].is_a?(Array)
30
- client = @client
31
- class_list = []
32
- list_class = self.class
33
- instance_uri = @uri
34
- response['data'].each do |val|
32
+ if response['data'].is_a?(Array)
33
+ class_list = []
34
+ instance_uri = @uri
35
+ response['data'].each do |val|
36
+ class_list << @instance_class.new("#{instance_uri}/#{val[@instance_id_key]}", @client, val)
37
+ end
38
+ end
39
+ class_list
40
+ end
35
41
 
36
- class_list << @instance_class.new( "#{instance_uri}/#{val[@instance_id_key]}", @client, val)
37
- end
38
- end
39
- class_list
40
- end
41
- def list(params={}, full_uri=false)
42
- raise "Can't get a resource list without a REST Client" unless @client
43
- @uri = full_uri ? @uri.split(@client.instance_variable_get(:@cloud_url))[1] : @uri
42
+ def list(params={}, full_uri=false)
43
+ raise "Can't get a resource list without a REST Client" unless @client
44
+ @uri = full_uri ? @uri.split(@client.instance_variable_get(:@cloud_url))[1] : @uri
44
45
 
45
- response = @client.get(@uri, params)
46
+ response = @client.get(@uri, params)
46
47
 
47
- if response['data'].is_a?(Array)
48
- client = @client
49
- class_list = []
50
- list_class = self.class
51
- instance_uri = full_uri ? @uri.split('?')[0] : @uri
52
- response['data'].each do |val|
48
+ if response['data'].is_a?(Array)
49
+ client = @client
50
+ class_list = []
51
+ list_class = self.class
52
+ instance_uri = full_uri ? @uri.split('?')[0] : @uri
53
+ response['data'].each do |val|
53
54
 
54
- class_list << @instance_class.new( "#{instance_uri}/#{val[@instance_id_key]}", @client, val)
55
- end
56
- class_list.instance_eval do
57
- eigenclass = class << self; self; end
55
+ class_list << @instance_class.new("#{instance_uri}/#{val[@instance_id_key]}", @client, val)
56
+ end
57
+ class_list.instance_eval do
58
+ eigenclass = class << self;
59
+ self;
60
+ end
58
61
 
59
- eigenclass.send :define_method, :offset, &lambda {response['offset']}
60
- eigenclass.send :define_method, :limit, &lambda {response['limit']}
61
- eigenclass.send :define_method, :total, &lambda {response['total']}
62
- eigenclass.send :define_method, :next_page, &lambda {
63
- if response['next']
62
+ eigenclass.send :define_method, :offset, &lambda { response['offset'] }
63
+ eigenclass.send :define_method, :limit, &lambda { response['limit'] }
64
+ eigenclass.send :define_method, :total, &lambda { response['total'] }
65
+ eigenclass.send :define_method, :next_page, &lambda {
66
+ if response['next']
64
67
 
65
- list_class.new(response['next'], client).list({}, true)
66
- else
67
- []
68
- end
69
- }
70
- eigenclass.send :define_method, :previous_page, &lambda {
71
- if response['previous']
68
+ list_class.new(response['next'], client).list({}, true)
69
+ else
70
+ []
71
+ end
72
+ }
73
+ eigenclass.send :define_method, :previous_page, &lambda {
74
+ if response['previous']
72
75
 
73
- list_class.new(response['previous'], client).list({}, true)
74
- else
75
- []
76
- end
77
- }
78
- end
79
- end
80
- class_list
81
- end
82
- end
76
+ list_class.new(response['previous'], client).list({}, true)
77
+ else
78
+ []
79
+ end
80
+ }
81
+ end
82
+ end
83
+ class_list
84
+ end
85
+ end
83
86
  end
@@ -1,77 +1,89 @@
1
-
2
1
  module TestdroidAPI
3
- class CloudResource
4
- def initialize(uri, client, resource_name=nil, params= {})
2
+ class CloudResource
3
+ def initialize(uri, client, resource_name=nil, params= {})
4
+
5
+ @uri, @client, @resource_name = uri, client, resource_name
6
+ set_up_properties_from(params)
7
+ end
8
+
9
+ def inspect # :nodoc:
10
+ "<#{self.class} @uri=#{@uri}>"
11
+ end
12
+
13
+ def sub_items(*items)
14
+ items.each do |item|
15
+ resource = camel_case_it item
16
+ uri = "#{@uri}/#{item.to_s.gsub('_', '-') }"
17
+ resource_class = TestdroidAPI.const_get resource
18
+ new_class = resource_class.new(uri, @client)
19
+ instance_variable_set("@#{item}", new_class)
20
+ end
21
+ self.class.instance_eval { attr_reader *items }
22
+ end
23
+
24
+ def method_missing(method, *args)
25
+ super if @updated
26
+ set_up_properties_from(@client.get(@uri))
27
+ self.send method, *args
28
+ end
29
+
30
+ def update(params = {})
31
+ raise "Can't update a resource without a REST Client" unless @client
32
+ set_up_properties_from(@client.post(@uri, params))
33
+ self
34
+ end
35
+
36
+ def set_up_properties_from(hash)
37
+
38
+ eigenclass = class << self;
39
+ self;
40
+ end
41
+ hash.each do |p, v|
42
+ property = snake_case_it p
43
+
44
+ unless ['uri', 'client', 'updated'].include? property
45
+ eigenclass.send :define_method, property.to_sym, &lambda { v }
46
+ end
47
+ end
48
+ @updated = !hash.keys.empty?
49
+ end
50
+
51
+ def refresh
52
+ raise "Can't refresh a resource without a REST Client" unless @client
53
+ @updated = false
54
+ set_up_properties_from(@client.get(@uri))
55
+ self
56
+ end
57
+
58
+ alias_method :load, :refresh
5
59
 
6
- @uri, @client, @resource_name = uri, client, resource_name
7
- set_up_properties_from( params )
8
- end
9
- def inspect # :nodoc:
10
- "<#{self.class} @uri=#{@uri}>"
11
- end
12
- def sub_items(*items)
13
- items.each do |item|
14
- resource = camel_case_it item
15
- uri = "#{@uri}/#{item.to_s.gsub('_', '-') }"
16
- resource_class = TestdroidAPI.const_get resource
17
- new_class = resource_class.new(uri, @client)
18
- instance_variable_set( "@#{item}", new_class )
19
- end
20
- self.class.instance_eval {attr_reader *items}
21
- end
22
- def method_missing(method, *args)
23
- super if @updated
24
- set_up_properties_from(@client.get(@uri))
25
- self.send method, *args
26
- end
27
- def update(params = {})
28
- raise "Can't update a resource without a REST Client" unless @client
29
- set_up_properties_from(@client.post(@uri, params))
30
- self
31
- end
32
- def set_up_properties_from(hash)
60
+ def download_file(file_resource_name, target_file_name=nil)
61
+ raise "Can't refresh a resource without a REST Client" unless @client
62
+ target_file_name = file_resource_name unless target_file_name
63
+ @client.download("#{@uri}/#{file_resource_name}", target_file_name)
64
+ end
33
65
 
34
- eigenclass = class << self; self; end
35
- hash.each do |p,v|
36
- property = snake_case_it p
66
+ def camel_case_it(something)
67
+ if something.is_a? Hash
68
+ Hash[*something.to_a.map { |a| [camel_case_it(a[0]).to_sym, a[1]] }.flatten]
69
+ else
70
+ something.to_s.split('_').map do |s|
71
+ [s[0, 1].capitalize, s[1..-1]].join
72
+ end.join
73
+ end
74
+ end
37
75
 
38
- unless ['uri', 'client', 'updated'].include? property
39
- eigenclass.send :define_method, property.to_sym, &lambda {v}
40
- end
41
- end
42
- @updated = !hash.keys.empty?
43
- end
76
+ def snake_case_it(something)
77
+ if something.is_a? Hash
78
+ Hash[*something.to_a.map { |pair| [snake_case_it(pair[0]).to_sym, pair[1]] }.flatten]
79
+ else
80
+ something.to_s.gsub(/[A-Z][a-z]*/) { |s| "_#{s.downcase}" }.gsub(/^_/, '')
81
+ end
82
+ end
44
83
 
45
- def refresh
46
- raise "Can't refresh a resource without a REST Client" unless @client
47
- @updated = false
48
- set_up_properties_from(@client.get(@uri))
49
- self
50
- end
51
- def download_file(file_resource_name, target_file_name=nil)
52
- raise "Can't refresh a resource without a REST Client" unless @client
53
- target_file_name = file_resource_name unless target_file_name
54
- @client.download("#{@uri}/#{file_resource_name}", target_file_name)
55
- end
56
- def camel_case_it(something)
57
- if something.is_a? Hash
58
- Hash[*something.to_a.map {|a| [camel_case_it(a[0]).to_sym, a[1]]}.flatten]
59
- else
60
- something.to_s.split('_').map do |s|
61
- [s[0,1].capitalize, s[1..-1]].join
62
- end.join
63
- end
64
- end
65
- def snake_case_it(something)
66
- if something.is_a? Hash
67
- Hash[*something.to_a.map {|pair| [snake_case_it(pair[0]).to_sym, pair[1]]}.flatten]
68
- else
69
- something.to_s.gsub(/[A-Z][a-z]*/) {|s| "_#{s.downcase}"}.gsub(/^_/, '')
70
- end
71
- end
72
- def delete
73
- raise "Can't delete a resource without a REST Client" unless @client
74
- @client.delete(@uri)
75
- end
76
- end
84
+ def delete
85
+ raise "Can't delete a resource without a REST Client" unless @client
86
+ @client.delete(@uri)
87
+ end
88
+ end
77
89
  end