testdroid-api 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,79 @@
1
+ module TestdroidApi
2
+ class Client
3
+ class Project
4
+ class TestRun
5
+
6
+ attr_reader :project_id, :id, :name, :state
7
+ def initialize(client, project, config)
8
+ @client = client
9
+ @project_id = project.id
10
+
11
+ update(config)
12
+ end
13
+
14
+ # Updates test_run information
15
+ def update!
16
+ res_name = "run"
17
+ endpoint = "projects/#{@project_id}/runs/#{id}"
18
+
19
+ config = @client.get_api_request(endpoint, res_name)
20
+
21
+ update(config)
22
+ end
23
+
24
+ def results
25
+ raise NotImplementedError
26
+ end
27
+
28
+ # Returns devices that the run was executed on.
29
+ # @return [Array<TestdroidApi::Client::TestRun::DeviceRun>]
30
+ def device_runs
31
+ res_name = "deviceRuns"
32
+ endpoint = "projects/#{@project_id}/runs/#{id}/device-runs"
33
+
34
+ results = @client.get_api_request(endpoint, res_name)
35
+ results.map{|device_run|
36
+ TestdroidApi::Client::Project::TestRun::DeviceRun.new(@client, self, device_run)
37
+ }
38
+ end
39
+
40
+ # Get test run's screenshots as a zip file.
41
+ def screenshots_zip
42
+ res_name = 'screenshots.zip'
43
+ endpoint = "projects/#{@project_id}/runs/#{id}/screenshots.zip"
44
+
45
+ @client.get_file(endpoint, res_name)
46
+ end
47
+
48
+ # Get test run's junit results as a zip file
49
+ def junit_results_zip
50
+ res_name = 'junits.zip'
51
+ endpoint = "projects/#{@project_id}/runs/#{id}/junits.zip"
52
+
53
+ @client.get_file(endpoint, res_name)
54
+ end
55
+
56
+ # Get test run's logs as a zip file.
57
+ def logs_zip
58
+ res_name = 'logs.zip'
59
+ endpoint = "projects/#{@project_id}/runs/#{id}/logs.zip"
60
+
61
+ @client.get_file(endpoint, res_name)
62
+ end
63
+
64
+ # Did test run finish
65
+ # @return [Boolean]
66
+ def finished?
67
+ state == 'FINISHED'
68
+ end
69
+
70
+ private
71
+ def update(config)
72
+ @id = config['id']
73
+ @name = config['displayName']
74
+ @state = config['groupState']
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,94 @@
1
+ module TestdroidApi
2
+ class Client
3
+ class Project
4
+ class TestRun
5
+ class DeviceRun
6
+
7
+ attr_reader :id, :device_id, :fail_message, :name, :state, :finished
8
+ attr_reader :screenshots_url, :junit_url, :logs_url
9
+
10
+ def initialize(client, run, config)
11
+ @client = client
12
+ @project_id = run.project_id
13
+ @run_id = run.id
14
+
15
+ update(config)
16
+ end
17
+
18
+ # Updates device run information
19
+ def update!
20
+ res_name = 'deviceRun'
21
+ endpoint = "projects/#{@project_id}/runs/#{@run_id}/device-runs/#{id}"
22
+
23
+ config = @client.get_api_request(endpoint, res_name)
24
+
25
+ update(config)
26
+ end
27
+
28
+ # Get device run's test results as JUnit XML
29
+ def junit_results
30
+ res_name = 'junit XML'
31
+ endpoint = "projects/#{@project_id}/runs/#{@run_id}/device-runs/#{id}_junit.xml"
32
+
33
+ @client.get_file(endpoint, res_name)
34
+ end
35
+
36
+ #Get device run's logs
37
+ def logs
38
+ res_name = 'log'
39
+ endpoint = "projects/#{@project_id}/runs/#{@run_id}/device-runs/#{id}_log.txt"
40
+
41
+ @client.get_file(endpoint, res_name)
42
+ end
43
+
44
+ # Get device run's screenshots as a zip file.
45
+ def screenshots_zip
46
+ res_name = 'screenshots.zip'
47
+ endpoint = "projects/#{@project_id}/runs/#{@run_id}/device-runs/#{id}/screenshots.zip"
48
+
49
+ @client.get_file(endpoint, res_name)
50
+ end
51
+
52
+ # Returns screenshots' ids for device run.
53
+ def screenshots
54
+ res_name = 'deviceRunScreenshots'
55
+ endpoint = "projects/#{@project_id}/runs/#{@run_id}/device-runs/#{id}/screenshots"
56
+
57
+ @client.get_api_request(endpoint, res_name)
58
+ end
59
+
60
+ # Get device's run screenshot.
61
+ # @param screenshot_id [Integer] screenshot id
62
+ def screenshot(screenshot_id)
63
+ res_name = 'screenshot'
64
+ endpoint = "projects/#{@project_id}/runs/#{@run_id}/device-runs/#{id}/screenshots/#{screenshot_id}"
65
+
66
+ @client.get_file(endpoint, res_name)
67
+ end
68
+
69
+ # Did test run finish
70
+ def finished?
71
+ finished
72
+ end
73
+
74
+ def results
75
+ raise NotImplementedError
76
+ end
77
+
78
+ private
79
+ def update(config)
80
+ @id = config['id']
81
+ @device_id = config['deviceId']
82
+ @fail_message = config['customerFailureMessage']
83
+ @name = config['deviceName']
84
+ @state = config['groupState']
85
+ @finished = config['finished']
86
+ @screenshots_url = config['screenshotsURI']
87
+ @junit_url = config['junitURI']
88
+ @logs_url = config['logURI']
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,3 @@
1
+ module TestdroidApi
2
+ VERSION = "1.0.1"
3
+ end
@@ -0,0 +1,134 @@
1
+ require 'spec_helper'
2
+
3
+ describe TestdroidApi::Client do
4
+ let(:client_class) { described_class }
5
+ let(:client) {client_class.new("user", "password")}
6
+
7
+ let(:auth_url) {"http://users.testdroid.com/api/v1/authorize"}
8
+ before do
9
+ stub_request(:post, auth_url).
10
+ to_return(:status => 200, :body => {"secretApiKey" => "1"}.to_json, :headers => {})
11
+ end
12
+
13
+ describe '#authenticate' do
14
+ it 'sends the right request' do
15
+ client.authenticate!
16
+
17
+ a_request(:post, auth_url).
18
+ with(:body => {:email => "user", :password => "password" }).
19
+ should have_been_made
20
+ end
21
+
22
+ context 'when successful' do
23
+ it 'stores apiKey' do
24
+ client.authenticate!
25
+
26
+ client.instance_variable_get('@api_key').should == '1'
27
+ end
28
+ end
29
+
30
+ context 'when fails' do
31
+ it 'throws exception' do
32
+ stub_request(:post, "http://users.testdroid.com/api/v1/authorize").
33
+ to_return(:status => 200, :body => {}.to_json, :headers => {})
34
+
35
+ expect { client.authenticate! }.
36
+ to raise_error(RuntimeError, "Could not authenticate, are you sure you have the right credentials?")
37
+ end
38
+ end
39
+ end
40
+
41
+ context 'when authenticated' do
42
+ before do
43
+ client.authenticate!
44
+ end
45
+
46
+ describe '#projects' do
47
+ let(:url) {"https://cloud.testdroid.com/api/v1/projects"}
48
+ let(:response_body) {File.new(File.dirname(__FILE__) + "/fixtures/projects.json").read}
49
+
50
+ before do
51
+ stub_request(:get, url).
52
+ to_return(:body => JSON.parse(response_body).to_json)
53
+ end
54
+
55
+ it 'sends the right request' do
56
+ client.projects
57
+
58
+ a_request(:get, url).should have_been_made
59
+ end
60
+
61
+ context 'without any params' do
62
+ it 'should return array of projects' do
63
+ TestdroidApi::Client::Project.stub(:new).with(any_args).and_return(true)
64
+
65
+ client.projects.should == [true, true]
66
+ end
67
+ end
68
+
69
+ context 'with project names' do
70
+ it 'finds the matching projects' do
71
+ client.projects('Project 1').first.name.should == "Project 1"
72
+ end
73
+ it 'removes unmatched projects' do
74
+ client.projects('Project 1').count.should == 1
75
+ end
76
+ end
77
+ end
78
+
79
+ describe '#create_project' do
80
+ let(:url) {"https://cloud.testdroid.com/api/v1/projects"}
81
+ let(:response_body) {File.new(File.dirname(__FILE__) + "/fixtures/new_project.json").read}
82
+ before do
83
+ stub_request(:post, url).
84
+ to_return(:status => 200, :body => JSON.parse(response_body).to_json, :headers => {})
85
+ end
86
+
87
+ it 'sends the right request' do
88
+ client.create_project("Name", "Description" )
89
+
90
+ a_request(:post, url).
91
+ with(:body => {:name => "Name", :description => "Description"} ).
92
+ should have_been_made
93
+ end
94
+
95
+ it 'returns new project' do
96
+ client.create_project(nil, nil).name.should == "New project name"
97
+ end
98
+ end
99
+
100
+ describe '#device groups' do
101
+ let(:url) {url = "https://cloud.testdroid.com/api/v1/clusters"}
102
+ let(:response_body) {File.new(File.dirname(__FILE__) + "/fixtures/devices.json").read}
103
+ before do
104
+ stub_request(:get, url).
105
+ to_return(:status => 200, :body => JSON.parse(response_body).to_json, :headers => {})
106
+ end
107
+
108
+ it 'sends the right request' do
109
+ client.device_groups
110
+
111
+ a_request(:get, url).
112
+ should have_been_made
113
+ end
114
+
115
+ context 'without params' do
116
+ it 'returns all device groups' do
117
+ client.device_groups("Test devices").first.display_name.should == "Test devices"
118
+ end
119
+
120
+ it 'removes unmatched projects' do
121
+ client.device_groups("Test devices").count.should == 1
122
+ end
123
+ end
124
+
125
+ end
126
+ end
127
+
128
+ context 'when not authenticated' do
129
+ it 'does not allow to fetch projects' do
130
+ expect{client.projects}.
131
+ to raise_error(RuntimeError, "Are you sure you've authenticated?")
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+
3
+ describe TestdroidApi::Client::Project::TestRun::DeviceRun do
4
+
5
+ let(:auth_url) { "http://users.testdroid.com/api/v1/authorize" }
6
+ let(:client) { TestdroidApi::Client.new('username', 'password') }
7
+ let(:run) { double(TestdroidApi::Client::Project::TestRun) }
8
+ let(:config) { JSON.parse(File.new(File.dirname(__FILE__) + "/fixtures/device_run.json").read)}
9
+ before do
10
+ stub_request(:post, auth_url).
11
+ to_return(:status => 200, :body => {"secretApiKey" => "1"}.to_json, :headers => {})
12
+ client.authenticate!
13
+
14
+ run.stub(:project_id).and_return(1)
15
+ run.stub(:id).and_return(100)
16
+ end
17
+
18
+ context 'when authenticated' do
19
+ let(:device_run) { described_class.new(client, run, config) }
20
+
21
+ describe '#update!' do
22
+ let(:url) { "https://cloud.testdroid.com/api/v1/projects/1/runs/100/device-runs/1000" }
23
+ let(:response_body) {File.new(File.dirname(__FILE__) + "/fixtures/waiting_device_run.json").read}
24
+ before do
25
+ stub_request(:get, url).
26
+ to_return(:status => 200, :body => JSON.parse(response_body).to_json, :headers => {})
27
+ end
28
+
29
+ it 'sends the right request' do
30
+ device_run.update!
31
+
32
+ a_request(:get, url).
33
+ should have_been_made
34
+ end
35
+
36
+ it 'updates run state' do
37
+ device_run.update!
38
+ device_run.state.should == "WAITING"
39
+ end
40
+ end
41
+
42
+
43
+ describe '#finished' do
44
+ let(:url) { "https://cloud.testdroid.com/api/v1/projects/1/runs/100/device-runs/1000" }
45
+ let(:response_body) {File.new(File.dirname(__FILE__) + "/fixtures/waiting_device_run.json").read}
46
+ before do
47
+ stub_request(:get, url).
48
+ to_return(:status => 200, :body => JSON.parse(response_body).to_json, :headers => {})
49
+ end
50
+
51
+ it 'returns true when run is finished' do
52
+ device_run.should be_finished
53
+ end
54
+
55
+ it 'returns false when run it not finished' do
56
+ device_run.update!
57
+ device_run.should_not be_finished
58
+ end
59
+ end
60
+
61
+ describe '#logs_zip' do
62
+ let(:url) { "https://cloud.testdroid.com/api/v1/projects/1/runs/100/device-runs/1000_log.txt" }
63
+ let(:response_body) {File.new(File.dirname(__FILE__) + "/fixtures/logs.txt")}
64
+ before do
65
+ stub_request(:get, url).
66
+ to_return(:status => 200, :body => response_body, :headers => {})
67
+ end
68
+
69
+ it 'sends the right request' do
70
+ device_run.logs
71
+
72
+ a_request(:get, url).should have_been_made
73
+ end
74
+
75
+ end
76
+
77
+ describe '#screenshots_zip' do
78
+ let(:url) { "https://cloud.testdroid.com/api/v1/projects/1/runs/100/device-runs/1000/screenshots/1000" }
79
+
80
+ before do
81
+ stub_request(:get, url).
82
+ to_return(:status => 200, :body => "", :headers => {})
83
+ end
84
+
85
+ it 'sends the right request' do
86
+ device_run.screenshot(1000)
87
+
88
+ a_request(:get, url).should have_been_made
89
+ end
90
+
91
+ end
92
+
93
+ describe '#junit_results' do
94
+ let(:url) { "https://cloud.testdroid.com/api/v1/projects/1/runs/100/device-runs/1000_junit.xml" }
95
+ let(:response_body) {File.new(File.dirname(__FILE__) + "/fixtures/junit.xml")}
96
+ before do
97
+ stub_request(:get, url).
98
+ to_return(:status => 200, :body => response_body, :headers => {})
99
+ end
100
+
101
+ it 'sends the right request' do
102
+ device_run.junit_results
103
+
104
+ a_request(:get, url).should have_been_made
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,96 @@
1
+ {
2
+ "address": "",
3
+ "name": "User Surname",
4
+ "id": 1333333,
5
+ "state": "",
6
+ "country": "DE",
7
+ "displayCountry": "Germany",
8
+ "timeZone": "GMT",
9
+ "username": "132254",
10
+ "displayname": "User user",
11
+ "enabled": true,
12
+ "active": true,
13
+ "code": "",
14
+ "email": "user@soundcloud.com",
15
+ "googleId": null,
16
+ "billing": false,
17
+ "organization": {
18
+ "name": "",
19
+ "id": 1
20
+ },
21
+ "countryDisplayname": "Germany",
22
+ "city": "",
23
+ "phone": "",
24
+ "secretApiKey": "xxxxxxxxxxxxxxxxx",
25
+ "Organization role": "Other",
26
+ "vatID": "",
27
+ "accessible": true,
28
+ "activeRoles": [
29
+ {
30
+ "name": "TEST_RUN_SCREENSHOTS",
31
+ "active": true,
32
+ "timeLimitUsed": false,
33
+ "useLimit": 100,
34
+ "useLimited": true
35
+ },
36
+ {
37
+ "name": "FREE_RUN",
38
+ "active": true,
39
+ "timeLimitUsed": false,
40
+ "useLimit": 115,
41
+ "useLimited": true
42
+ },
43
+ {
44
+ "name": "PRIORITY_GOLD",
45
+ "active": true,
46
+ "timeLimitUsed": true,
47
+ "useLimit": 0,
48
+ "useLimited": false
49
+ },
50
+ {
51
+ "name": "PAID_RUN",
52
+ "active": true,
53
+ "timeLimitUsed": true,
54
+ "useLimit": 0,
55
+ "useLimited": false
56
+ },
57
+ {
58
+ "name": "API_CLIENT",
59
+ "active": true,
60
+ "timeLimitUsed": true,
61
+ "useLimit": 0,
62
+ "useLimited": false
63
+ }
64
+ ],
65
+ "lastLoginTime": 1380651077429,
66
+ "registrationIP": null,
67
+ "purchasedUserServices": [
68
+
69
+ ],
70
+ "creditsLeft": "10000",
71
+ "Heard from": "Other",
72
+ "availableHearFromValues": [
73
+ "COWORKER",
74
+ "EMAIL_CAMPAIGN",
75
+ "EVENT",
76
+ "ONLINE_COMMUNITY",
77
+ "SOCIAL_NETWORK",
78
+ "WEB_SEARCH",
79
+ "OTHER"
80
+ ],
81
+ "availableOrganizationRoleValues": [
82
+ "CEO_OR_OWNER",
83
+ "VP",
84
+ "MANAGER",
85
+ "INDIVIDUAL",
86
+ "QUALITY_ASSURANCE",
87
+ "DEVELOPER",
88
+ "MARKETING",
89
+ "CONSULTANT",
90
+ "OTHER"
91
+ ],
92
+ "admin": false,
93
+ "accountNonExpired": true,
94
+ "accountNonLocked": true,
95
+ "credentialsNonExpired": true
96
+ }