testdroid-api-client 0.2.2 → 0.5.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.
- checksums.yaml +5 -5
- data/.gitignore +5 -0
- data/.travis.yml +11 -0
- data/Gemfile.lock +65 -37
- data/README.md +30 -41
- data/lib/testdroid-api-client.rb +25 -9
- data/lib/testdroid-api-filter-builder.rb +145 -0
- data/lib/testdroid_api/admin.rb +25 -0
- data/lib/testdroid_api/admin_device_models.rb +10 -0
- data/lib/testdroid_api/admin_device_problems.rb +9 -0
- data/lib/testdroid_api/admin_device_statuses.rb +12 -0
- data/lib/testdroid_api/admin_devices.rb +10 -0
- data/lib/testdroid_api/apikey_client.rb +120 -0
- data/lib/testdroid_api/client.rb +158 -123
- data/lib/testdroid_api/cloud_list_resource.rb +69 -70
- data/lib/testdroid_api/cloud_resource.rb +83 -71
- data/lib/testdroid_api/device_groups.rb +9 -9
- data/lib/testdroid_api/device_session_connections.rb +10 -0
- data/lib/testdroid_api/device_sessions.rb +21 -12
- data/lib/testdroid_api/devices.rb +8 -11
- data/lib/testdroid_api/files.rb +60 -58
- data/lib/testdroid_api/frameworks.rb +11 -0
- data/lib/testdroid_api/label_groups.rb +9 -10
- data/lib/testdroid_api/labels.rb +9 -10
- data/lib/testdroid_api/projects.rb +9 -16
- data/lib/testdroid_api/properties.rb +13 -0
- data/lib/testdroid_api/runs.rb +22 -12
- data/lib/testdroid_api/services.rb +18 -0
- data/lib/testdroid_api/user.rb +11 -6
- data/sample/BitbarSampleApp.apk +0 -0
- data/sample/BitbarSampleAppTest.apk +0 -0
- data/sample/sample.rb +23 -23
- data/spec/client_spec.rb +7 -7
- data/spec/device_groups_spec.rb +30 -17
- data/spec/files_spec.rb +40 -20
- data/spec/fixtures/apk.apk +0 -0
- data/spec/fixtures/cassettes/device_groups_authorize.json +1 -0
- data/spec/fixtures/cassettes/device_groups_create.json +1 -0
- data/spec/fixtures/cassettes/device_groups_delete.json +1 -0
- data/spec/fixtures/cassettes/device_groups_get_all.json +1 -0
- data/spec/fixtures/cassettes/device_groups_get_one.json +1 -0
- data/spec/fixtures/cassettes/files_authorize.json +1 -0
- data/spec/fixtures/cassettes/files_delete.json +1 -0
- data/spec/fixtures/cassettes/files_get_all.json +1 -0
- data/spec/fixtures/cassettes/files_get_one.json +1 -0
- data/spec/fixtures/cassettes/files_upload.json +1 -0
- data/spec/fixtures/cassettes/files_upload_with_wait.json +1 -0
- data/spec/fixtures/cassettes/label_groups_authorize.json +1 -0
- data/spec/fixtures/cassettes/label_groups_create.json +1 -0
- data/spec/fixtures/cassettes/label_groups_delete.json +1 -0
- data/spec/fixtures/cassettes/label_groups_get_all.json +1 -0
- data/spec/fixtures/cassettes/label_groups_get_labels.json +1 -0
- data/spec/fixtures/cassettes/label_groups_get_one.json +1 -0
- data/spec/fixtures/cassettes/projects_authorize.json +1 -0
- data/spec/fixtures/cassettes/projects_create.json +1 -0
- data/spec/fixtures/cassettes/projects_delete.json +1 -0
- data/spec/fixtures/cassettes/projects_get_all.json +1 -0
- data/spec/fixtures/cassettes/projects_get_one.json +1 -0
- data/spec/fixtures/cassettes/runs_abort_run.json +1 -0
- data/spec/fixtures/cassettes/runs_authorize.json +1 -0
- data/spec/fixtures/cassettes/runs_get_project_runs.json +1 -0
- data/spec/fixtures/cassettes/runs_start_run.json +1 -0
- data/spec/fixtures/data.txt +1 -0
- data/spec/fixtures/data2.txt +1 -0
- data/spec/label_groups_spec.rb +35 -42
- data/spec/projects_spec.rb +41 -0
- data/spec/runs_spec.rb +41 -0
- data/spec/spec_helper.rb +3 -4
- data/testdroid-api-client.gemspec +13 -11
- metadata +92 -134
- data/lib/testdroid_api/config.rb +0 -7
- data/lib/testdroid_api/device_runs.rb +0 -20
- data/lib/testdroid_api/file_sets.rb +0 -12
- data/spec/device_runs_spec.rb +0 -25
- data/spec/file_sets_spec.rb +0 -47
- data/spec/fixtures/cassettes/dg_all_device_groups.json +0 -1
- data/spec/fixtures/cassettes/dg_device_group_4165.json +0 -1
- data/spec/fixtures/cassettes/dg_oauth2_auth_device_groups.json +0 -1
- data/spec/fixtures/cassettes/dr_all_run_171221_device_runs.json +0 -1
- data/spec/fixtures/cassettes/dr_device_run_33044722.json +0 -1
- data/spec/fixtures/cassettes/dr_oauth2_auth_device_runs.json +0 -1
- data/spec/fixtures/cassettes/dr_run_33044722_device_runs.json +0 -1
- data/spec/fixtures/cassettes/f_add_file_set.json +0 -1
- data/spec/fixtures/cassettes/f_android_app_file.json +0 -1
- data/spec/fixtures/cassettes/f_file_sets.json +0 -1
- data/spec/fixtures/cassettes/f_oauth2_auth_files.json +0 -1
- data/spec/fixtures/cassettes/f_upload_files.json +0 -1
- data/spec/fixtures/cassettes/fs_add_file_set.json +0 -1
- data/spec/fixtures/cassettes/fs_add_file_to_fileset.json +0 -1
- data/spec/fixtures/cassettes/fs_delete_file_set.json +0 -1
- data/spec/fixtures/cassettes/fs_file_sets.json +0 -1
- data/spec/fixtures/cassettes/fs_get_file_set.json +0 -1
- data/spec/fixtures/cassettes/fs_oauth2_auth_files.json +0 -1
- data/spec/fixtures/cassettes/fs_update_file_set.json +0 -1
- data/spec/fixtures/cassettes/fu_oauth2_auth_files.json +0 -1
- data/spec/fixtures/cassettes/lg_all_label_groups.json +0 -1
- data/spec/fixtures/cassettes/lg_get_resources_by_label.json +0 -1
- data/spec/fixtures/cassettes/lg_label_group_1058800.json +0 -1
- data/spec/fixtures/cassettes/lg_labels_of_group_1058800.json +0 -1
- data/spec/fixtures/cassettes/lg_oauth2_auth_label_groups.json +0 -1
- data/spec/fixtures/cassettes/p_all_projects.json +0 -1
- data/spec/fixtures/cassettes/p_create_project.json +0 -1
- data/spec/fixtures/cassettes/p_get_run_devices.json +0 -1
- data/spec/fixtures/cassettes/p_oauth2_auth.json +0 -1
- data/spec/fixtures/cassettes/p_oauth2_local.json +0 -1
- data/spec/fixtures/cassettes/p_project_id_33029366.json +0 -1
- data/spec/fixtures/cassettes/p_run_project.json +0 -1
- data/spec/fixtures/cassettes/pc_get_current.json +0 -1
- data/spec/fixtures/cassettes/pc_oauth2_auth_config.json +0 -1
- data/spec/fixtures/cassettes/pc_set_current_config.json +0 -1
- data/spec/fixtures/cassettes/pc_validate_config.json +0 -1
- data/spec/fixtures/cassettes/r_all_project_33029366_runs.json +0 -1
- data/spec/fixtures/cassettes/r_delete_test_run.json +0 -1
- data/spec/fixtures/cassettes/r_oauth2_auth_runs.json +0 -1
- data/spec/fixtures/cassettes/r_run_171221.json +0 -1
- data/spec/fixtures/cassettes/r_run_project.json +0 -1
- data/spec/fixtures/cassettes/upload_files.json +0 -1
- data/spec/fixtures/project.json +0 -8
- data/spec/project_config_spec.rb +0 -36
- data/spec/project_spec.rb +0 -56
- data/spec/run_spec.rb +0 -33
|
@@ -1,83 +1,82 @@
|
|
|
1
|
-
|
|
2
1
|
module TestdroidAPI
|
|
3
|
-
|
|
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
|
|
4
10
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
|
11
|
+
def get(resource_id)
|
|
12
|
+
@instance_class.new("#{@uri}/#{resource_id}", @client)
|
|
13
|
+
end
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
|
15
|
+
def total
|
|
16
|
+
@client.get(@uri)['total']
|
|
17
|
+
end
|
|
26
18
|
|
|
27
|
-
|
|
19
|
+
def create(params = {})
|
|
20
|
+
raise "Can't create a resource without a REST Client" unless @client
|
|
21
|
+
response = @client.post @uri, params
|
|
22
|
+
@instance_class.new "#{@uri}/#{response[@instance_id_key]}", @client, response
|
|
23
|
+
end
|
|
28
24
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class_list = []
|
|
32
|
-
list_class = self.class
|
|
33
|
-
instance_uri = @uri
|
|
34
|
-
response['data'].each do |val|
|
|
25
|
+
def list_all()
|
|
26
|
+
raise "Can't get a resource list without a REST Client" unless @client
|
|
35
27
|
|
|
36
|
-
|
|
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
|
|
28
|
+
response = @client.get(@uri, {:limit => 0})
|
|
44
29
|
|
|
45
|
-
|
|
30
|
+
class_list = []
|
|
31
|
+
if response['data'].is_a?(Array)
|
|
32
|
+
instance_uri = @uri
|
|
33
|
+
response['data'].each do |val|
|
|
34
|
+
class_list << @instance_class.new("#{instance_uri}/#{val[@instance_id_key]}", @client, val)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
class_list
|
|
38
|
+
end
|
|
46
39
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
40
|
+
def list(params = {}, full_uri = false)
|
|
41
|
+
raise "Can't get a resource list without a REST Client" unless @client
|
|
42
|
+
@uri = full_uri ? @uri.split(@client.instance_variable_get(:@cloud_url))[1] : @uri
|
|
43
|
+
response = @client.get(@uri, params)
|
|
44
|
+
class_list = []
|
|
45
|
+
if response['data'].is_a?(Array)
|
|
46
|
+
client = @client
|
|
47
|
+
list_class = self.class
|
|
48
|
+
instance_uri = full_uri ? @uri.split('?')[0] : @uri
|
|
49
|
+
response['data'].each do |val|
|
|
53
50
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
class_list << @instance_class.new("#{instance_uri}/#{val[@instance_id_key]}", @client, val)
|
|
52
|
+
end
|
|
53
|
+
class_list.instance_eval do
|
|
54
|
+
eigenclass = class << self;
|
|
55
|
+
self;
|
|
56
|
+
end
|
|
58
57
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
eigenclass.send :define_method, :offset, &lambda {response['offset']}
|
|
59
|
+
eigenclass.send :define_method, :limit, &lambda {response['limit']}
|
|
60
|
+
eigenclass.send :define_method, :total, &lambda {response['total']}
|
|
61
|
+
eigenclass.send :define_method, :next_page, &lambda {
|
|
62
|
+
if response['next']
|
|
64
63
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
64
|
+
list_class.new(response['next'], client).list({}, true)
|
|
65
|
+
else
|
|
66
|
+
[]
|
|
67
|
+
end
|
|
68
|
+
}
|
|
69
|
+
eigenclass.send :define_method, :previous_page, &lambda {
|
|
70
|
+
if response['previous']
|
|
72
71
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
72
|
+
list_class.new(response['previous'], client).list({}, true)
|
|
73
|
+
else
|
|
74
|
+
[]
|
|
75
|
+
end
|
|
76
|
+
}
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
class_list
|
|
80
|
+
end
|
|
81
|
+
end
|
|
83
82
|
end
|
|
@@ -1,77 +1,89 @@
|
|
|
1
|
-
|
|
2
1
|
module TestdroidAPI
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
|
|
2
1
|
module TestdroidAPI
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
class DeviceGroups < CloudListResource
|
|
3
|
+
end
|
|
4
|
+
class DeviceGroup < CloudResource
|
|
5
|
+
def initialize(uri, client, params = {})
|
|
6
|
+
super uri, client, "deviceGroup", params
|
|
7
|
+
@uri, @client = uri, client
|
|
8
|
+
sub_items :devices
|
|
9
|
+
end
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
end
|
|
12
12
|
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module TestdroidAPI
|
|
2
|
+
class DeviceSessionConnections < CloudListResource
|
|
3
|
+
end
|
|
4
|
+
class DeviceSessionConnection < CloudResource
|
|
5
|
+
def initialize(uri, client, params = {})
|
|
6
|
+
super uri, client, "DeviceSessionConnection", params
|
|
7
|
+
@uri, @client = uri, client
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
|
|
2
1
|
module TestdroidAPI
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
2
|
+
class DeviceSessions < CloudListResource
|
|
3
|
+
end
|
|
4
|
+
class DeviceSession < CloudResource
|
|
5
|
+
def initialize(uri, client, params = {})
|
|
6
|
+
super uri, client, "deviceSession", params
|
|
7
|
+
@uri, @client = uri, client
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def release
|
|
11
|
+
@client.post("#{@uri}/release", params = {})
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def download_all_files(path)
|
|
15
|
+
Dir.mkdir(path) unless Dir.exist?(path)
|
|
16
|
+
files = @client.get("#{@uri}/output-file-set/files")
|
|
17
|
+
files['data'].each do |file|
|
|
18
|
+
@client.download(file['directUrl'], ::File.join(path, "#{file['id']}-#{file['name']}"))
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
14
23
|
end
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
|
|
2
1
|
module TestdroidAPI
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
end
|
|
2
|
+
class Devices < CloudListResource
|
|
3
|
+
end
|
|
4
|
+
class Device < CloudResource
|
|
5
|
+
def initialize(uri, client, params = {})
|
|
6
|
+
super uri, client, "device", params
|
|
7
|
+
@uri, @client = uri, client
|
|
8
|
+
end
|
|
9
|
+
end
|
|
13
10
|
end
|
data/lib/testdroid_api/files.rb
CHANGED
|
@@ -1,60 +1,62 @@
|
|
|
1
|
-
|
|
2
1
|
module TestdroidAPI
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
2
|
+
class Files < CloudListResource
|
|
3
|
+
|
|
4
|
+
ACCEPTED_VIRUS_SCAN_STATUSES = Set['safe', 'disabled', nil]
|
|
5
|
+
|
|
6
|
+
def upload(filename, skip_scan_wait=false)
|
|
7
|
+
unless ::File.exist?(filename)
|
|
8
|
+
@client.logger.error("Invalid filename")
|
|
9
|
+
return
|
|
10
|
+
end
|
|
11
|
+
file = @client.upload("#{@uri}", filename)
|
|
12
|
+
result = File.new("#{@uri}/#{file['id']}", @client, file)
|
|
13
|
+
if !skip_scan_wait
|
|
14
|
+
wait_for_virus_scan(Array(result))
|
|
15
|
+
end
|
|
16
|
+
return result
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def wait_for_virus_scan(api_files, timeout=300)
|
|
20
|
+
all_safe = false
|
|
21
|
+
begin
|
|
22
|
+
Timeout.timeout(timeout) do
|
|
23
|
+
while !all_safe do
|
|
24
|
+
statuses = Set.new
|
|
25
|
+
api_files.each do |file|
|
|
26
|
+
current_status = get_virus_scan_status(file)
|
|
27
|
+
if ACCEPTED_VIRUS_SCAN_STATUSES.include?(current_status)
|
|
28
|
+
statuses.add(current_status)
|
|
29
|
+
else
|
|
30
|
+
sleep(1)
|
|
31
|
+
file.refresh
|
|
32
|
+
statuses.add(get_virus_scan_status(file))
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
if statuses.include?('infected')
|
|
36
|
+
raise 'File rejected by virus scan'
|
|
37
|
+
end
|
|
38
|
+
if ACCEPTED_VIRUS_SCAN_STATUSES.superset?(statuses)
|
|
39
|
+
all_safe = true
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
rescue Timeout::Error
|
|
44
|
+
@client.logger.error("Waiting for virus scan timed out")
|
|
45
|
+
raise
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def get_virus_scan_status(file)
|
|
52
|
+
return file.file_properties.find{ |item| item['key'] == "virus_scan_status" }['value']
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class File < CloudResource
|
|
57
|
+
def initialize(uri, client, params = {})
|
|
58
|
+
super uri, client, "file", params
|
|
59
|
+
@uri, @client = uri, client
|
|
60
|
+
end
|
|
61
|
+
end
|
|
60
62
|
end
|