testrail 0.0.1
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/.document +5 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +48 -0
- data/LICENSE.txt +20 -0
- data/README.md +55 -0
- data/Rakefile +54 -0
- data/lib/testrail.rb +9 -0
- data/lib/testrail/client.rb +169 -0
- data/lib/testrail/command_helper.rb +17 -0
- data/lib/testrail/config.rb +31 -0
- data/lib/testrail/request.rb +68 -0
- data/lib/testrail/response.rb +35 -0
- data/lib/testrail/version.rb +3 -0
- data/spec/lib/testrail/client_spec.rb +367 -0
- data/spec/lib/testrail/command_helper_spec.rb +43 -0
- data/spec/lib/testrail/config_spec.rb +127 -0
- data/spec/lib/testrail/request_spec.rb +172 -0
- data/spec/lib/testrail/response_spec.rb +119 -0
- data/spec/lib/testrail/version_spec.rb +7 -0
- data/spec/lib/testrail_spec.rb +12 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/http_values.rb +40 -0
- data/testrail.gemspec +82 -0
- metadata +188 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module Testrail
|
4
|
+
class Request
|
5
|
+
include HTTParty
|
6
|
+
extend Testrail::CommandHelper
|
7
|
+
|
8
|
+
base_uri Testrail.config.server
|
9
|
+
format :json
|
10
|
+
|
11
|
+
def self.get(*args)
|
12
|
+
command, ids, opts = parse_args(*args)
|
13
|
+
url = build_command(command, ids)
|
14
|
+
attempts = 0
|
15
|
+
begin
|
16
|
+
attempts += 1
|
17
|
+
response = Testrail::Response.new(super(url, opts))
|
18
|
+
rescue TimeoutError => error
|
19
|
+
retry if attempts < 3
|
20
|
+
unless Testrail.logger.nil?
|
21
|
+
Testrail.logger.error "Timeout connecting to GET #{url}"
|
22
|
+
Testrail.logger.error error
|
23
|
+
end
|
24
|
+
raise error
|
25
|
+
rescue Exception => error
|
26
|
+
unless Testrail.logger.nil?
|
27
|
+
Testrail.logger.error "Unexpected exception intercepted calling TestRail"
|
28
|
+
Testrail.logger.error error
|
29
|
+
end
|
30
|
+
raise error
|
31
|
+
end
|
32
|
+
response
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.post(*args)
|
36
|
+
command, ids, opts = parse_args(*args)
|
37
|
+
url = build_command(command, ids)
|
38
|
+
attempts = 0
|
39
|
+
begin
|
40
|
+
attempts += 1
|
41
|
+
response = Testrail::Response.new(super(url, opts))
|
42
|
+
rescue TimeoutError => error
|
43
|
+
retry if attempts < 3
|
44
|
+
unless Testrail.logger.nil?
|
45
|
+
Testrail.logger.error "Timeout connecting to POST #{url}"
|
46
|
+
Testrail.logger.error error
|
47
|
+
end
|
48
|
+
raise error
|
49
|
+
rescue Exception => error
|
50
|
+
unless Testrail.logger.nil?
|
51
|
+
Testrail.logger.error "Unexpected exception intercepted calling TestRail"
|
52
|
+
Testrail.logger.error error
|
53
|
+
end
|
54
|
+
raise error
|
55
|
+
end
|
56
|
+
response
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
def self.parse_args(*args)
|
61
|
+
opts = args.last.instance_of?(Hash) ? args.pop : {}
|
62
|
+
opts[:headers] = opts[:headers] ? Testrail.config.headers.merge(opts[:headers]) : Testrail.config.headers
|
63
|
+
command = args.shift
|
64
|
+
ids = args.empty? ? nil : args
|
65
|
+
[command, ids, opts]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Testrail
|
5
|
+
class Response
|
6
|
+
attr_reader :http_response
|
7
|
+
attr_accessor :success, :payload, :error
|
8
|
+
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
def_delegators :http_response, :request, :response, :code
|
12
|
+
|
13
|
+
def initialize(http_response = nil)
|
14
|
+
@http_response = http_response
|
15
|
+
parse_payload if http_response.respond_to?(:body) && !http_response.body.nil?
|
16
|
+
parse_error if Integer(http_response.code) >= 400
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def parse_payload
|
21
|
+
result_body = JSON.parse(http_response.body)
|
22
|
+
@success = result_body.key?('result') ? result_body.delete('result') : nil
|
23
|
+
@payload = @success ? result_body : nil
|
24
|
+
@error = result_body.key?('error') ? result_body.delete('error') : nil
|
25
|
+
rescue JSON::ParserError
|
26
|
+
@success = false
|
27
|
+
@error = "Malformed JSON response.\n Received #{http_response.body}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def parse_error
|
31
|
+
@success = false
|
32
|
+
@error = ::Net::HTTPResponse::CODE_TO_OBJ[http_response.code.to_s].name.gsub!(/Net::HTTP/, '')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,367 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Testrail::Client do
|
4
|
+
subject { Testrail::Client.new }
|
5
|
+
|
6
|
+
describe "initialize" do
|
7
|
+
it "assigns Testrail::Request to @request" do
|
8
|
+
subject.request.should eq(Testrail::Request)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
shared_examples_for "an api call" do
|
13
|
+
before do
|
14
|
+
@parsed_ids = ids.empty? ? '' : '/' + [ids].flatten.join('/')
|
15
|
+
stub_request(expected_method, url_prefix(command.to_s) + @parsed_ids + key).
|
16
|
+
with(body: opts[:body],
|
17
|
+
headers: opts[:headers]).
|
18
|
+
to_return(status: 200, body: JSON.generate({result: true, an_object: 'abc'}, headers: {}))
|
19
|
+
args = []
|
20
|
+
args << ids unless ids.empty?
|
21
|
+
args << opts unless opts.empty?
|
22
|
+
@response = subject.send(command, *args.flatten)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "returns a Testrail::Response object" do
|
26
|
+
@response.should be_instance_of(Testrail::Response)
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
context "successful interaction" do
|
31
|
+
it "calls WebMock with the appropriate method " do
|
32
|
+
WebMock.should have_requested(expected_method, url_prefix(command.to_s) + @parsed_ids + key).with(opts)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return Testrail::Response with success set to true" do
|
36
|
+
@response.success.should be_true
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should return Testrail::Response with a nil @error" do
|
40
|
+
@response.error.should be_nil
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should return Testrail::Response with a valid body hash" do
|
44
|
+
@response.payload.should eq({"an_object" => "abc"})
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#add_result" do
|
50
|
+
describe "shared behavior" do
|
51
|
+
it_should_behave_like "an api call" do
|
52
|
+
let(:command) { :add_result }
|
53
|
+
let(:ids) { 'test_id' }
|
54
|
+
let(:opts) { post_options }
|
55
|
+
let(:expected_method) { :post }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "#add_result_for_case" do
|
61
|
+
describe "shared behavior" do
|
62
|
+
it_should_behave_like "an api call" do
|
63
|
+
let(:command) { :add_result_for_case }
|
64
|
+
let(:ids) { ['run_id', 'case_id'] }
|
65
|
+
let(:opts) { post_options }
|
66
|
+
let(:expected_method) { :post }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#get_test" do
|
72
|
+
describe "shared behavior" do
|
73
|
+
it_should_behave_like "an api call" do
|
74
|
+
let(:command) { :get_test }
|
75
|
+
let(:ids) { 'test_id' }
|
76
|
+
let(:opts) { get_options }
|
77
|
+
let(:expected_method) { :get }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#get_tests" do
|
83
|
+
describe "shared behavior" do
|
84
|
+
it_should_behave_like "an api call" do
|
85
|
+
let(:command) { :get_tests }
|
86
|
+
let(:ids) { 'run_id' }
|
87
|
+
let(:opts) { get_options }
|
88
|
+
let(:expected_method) { :get }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "#get_case" do
|
94
|
+
describe "shared behavior" do
|
95
|
+
it_should_behave_like "an api call" do
|
96
|
+
let(:command) { :get_case }
|
97
|
+
let(:ids) { 'case_id' }
|
98
|
+
let(:opts) { get_options }
|
99
|
+
let(:expected_method) { :get }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "#get_cases" do
|
105
|
+
describe "shared behavior" do
|
106
|
+
it_should_behave_like "an api call" do
|
107
|
+
let(:command) { :get_cases }
|
108
|
+
let(:ids) { ['suite_id', 'section_id'] }
|
109
|
+
let(:opts) { get_options }
|
110
|
+
let(:expected_method) { :get }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "#add_case" do
|
116
|
+
describe "shared behavior" do
|
117
|
+
it_should_behave_like "an api call" do
|
118
|
+
let(:command) { :add_case }
|
119
|
+
let(:ids) { 'section_id' }
|
120
|
+
let(:opts) { post_options }
|
121
|
+
let(:expected_method) { :post }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "#update_case" do
|
127
|
+
describe "shared behavior" do
|
128
|
+
it_should_behave_like "an api call" do
|
129
|
+
let(:command) { :update_case }
|
130
|
+
let(:ids) { 'case_id' }
|
131
|
+
let(:opts) { post_options }
|
132
|
+
let(:expected_method) { :post }
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "#delete_case" do
|
138
|
+
describe "shared behavior" do
|
139
|
+
it_should_behave_like "an api call" do
|
140
|
+
let(:command) { :delete_case }
|
141
|
+
let(:ids) { 'case_id' }
|
142
|
+
let(:opts) { get_options }
|
143
|
+
let(:expected_method) { :post }
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "#get_suite" do
|
149
|
+
describe "shared behavior" do
|
150
|
+
it_should_behave_like "an api call" do
|
151
|
+
let(:command) { :get_suite }
|
152
|
+
let(:ids) { 'suite_id' }
|
153
|
+
let(:opts) { get_options }
|
154
|
+
let(:expected_method) { :get }
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe "#get_suites" do
|
160
|
+
describe "shared behavior" do
|
161
|
+
it_should_behave_like "an api call" do
|
162
|
+
let(:command) { :get_suites }
|
163
|
+
let(:ids) { 'project_id' }
|
164
|
+
let(:opts) { get_options }
|
165
|
+
let(:expected_method) { :get }
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe "#get_section" do
|
171
|
+
describe "shared behavior" do
|
172
|
+
it_should_behave_like "an api call" do
|
173
|
+
let(:command) { :get_section }
|
174
|
+
let(:ids) { 'section_id' }
|
175
|
+
let(:opts) { get_options }
|
176
|
+
let(:expected_method) { :get }
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "#get_sections" do
|
182
|
+
describe "shared behavior" do
|
183
|
+
it_should_behave_like "an api call" do
|
184
|
+
let(:command) { :get_sections }
|
185
|
+
let(:ids) { 'suite_id' }
|
186
|
+
let(:opts) { get_options }
|
187
|
+
let(:expected_method) { :get }
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
describe "#add_suite" do
|
193
|
+
describe "shared behavior" do
|
194
|
+
it_should_behave_like "an api call" do
|
195
|
+
let(:command) { :add_suite }
|
196
|
+
let(:ids) { 'project_id' }
|
197
|
+
let(:opts) { post_options }
|
198
|
+
let(:expected_method) { :post }
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe "#add_section" do
|
204
|
+
describe "shared behavior" do
|
205
|
+
it_should_behave_like "an api call" do
|
206
|
+
let(:command) { :add_section }
|
207
|
+
let(:ids) { 'suite_id' }
|
208
|
+
let(:opts) { post_options }
|
209
|
+
let(:expected_method) { :post }
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
describe "#get_run" do
|
215
|
+
describe "shared behavior" do
|
216
|
+
it_should_behave_like "an api call" do
|
217
|
+
let(:command) { :get_run }
|
218
|
+
let(:ids) { 'run_id' }
|
219
|
+
let(:opts) { get_options }
|
220
|
+
let(:expected_method) { :get }
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
describe "#get_runs" do
|
226
|
+
describe "shared behavior" do
|
227
|
+
it_should_behave_like "an api call" do
|
228
|
+
let(:command) { :get_runs }
|
229
|
+
let(:ids) { ['project_id', 'plan_id'] }
|
230
|
+
let(:opts) { get_options }
|
231
|
+
let(:expected_method) { :get }
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
describe "#add_run" do
|
237
|
+
describe "shared behavior" do
|
238
|
+
it_should_behave_like "an api call" do
|
239
|
+
let(:command) { :add_run }
|
240
|
+
let(:ids) { 'suite_id' }
|
241
|
+
let(:opts) { post_options }
|
242
|
+
let(:expected_method) { :post }
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
describe "#close_run" do
|
248
|
+
describe "shared behavior" do
|
249
|
+
it_should_behave_like "an api call" do
|
250
|
+
let(:command) { :close_run }
|
251
|
+
let(:ids) { 'run_id' }
|
252
|
+
let(:opts) { get_options }
|
253
|
+
let(:expected_method) { :post }
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
describe "#get_plan" do
|
259
|
+
describe "shared behavior" do
|
260
|
+
it_should_behave_like "an api call" do
|
261
|
+
let(:command) { :get_plan }
|
262
|
+
let(:ids) { 'plan_id' }
|
263
|
+
let(:opts) { get_options }
|
264
|
+
let(:expected_method) { :get }
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
describe "#get_plans" do
|
270
|
+
describe "shared behavior" do
|
271
|
+
it_should_behave_like "an api call" do
|
272
|
+
let(:command) { :get_plans }
|
273
|
+
let(:ids) { 'project_id' }
|
274
|
+
let(:opts) { get_options }
|
275
|
+
let(:expected_method) { :get }
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
describe "#add_plan" do
|
281
|
+
describe "shared behavior" do
|
282
|
+
it_should_behave_like "an api call" do
|
283
|
+
let(:command) { :add_plan }
|
284
|
+
let(:ids) { 'project_id' }
|
285
|
+
let(:opts) { post_options }
|
286
|
+
let(:expected_method) { :post }
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
describe "#add_plan_entries" do
|
292
|
+
describe "shared behavior" do
|
293
|
+
it_should_behave_like "an api call" do
|
294
|
+
let(:command) { :add_plan_entries }
|
295
|
+
let(:ids) { 'plan_id' }
|
296
|
+
let(:opts) { post_options }
|
297
|
+
let(:expected_method) { :post }
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
describe "#close_plan" do
|
303
|
+
describe "shared behavior" do
|
304
|
+
it_should_behave_like "an api call" do
|
305
|
+
let(:command) { :close_plan }
|
306
|
+
let(:ids) { 'plan_id' }
|
307
|
+
let(:opts) { get_options }
|
308
|
+
let(:expected_method) { :post }
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
describe "#get_milestone" do
|
314
|
+
describe "shared behavior" do
|
315
|
+
it_should_behave_like "an api call" do
|
316
|
+
let(:command) { :get_milestone }
|
317
|
+
let(:ids) { 'milestone_id' }
|
318
|
+
let(:opts) { get_options }
|
319
|
+
let(:expected_method) { :get }
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
describe "#get_milestones" do
|
325
|
+
describe "shared behavior" do
|
326
|
+
it_should_behave_like "an api call" do
|
327
|
+
let(:command) { :get_milestones }
|
328
|
+
let(:ids) { 'project_id' }
|
329
|
+
let(:opts) { get_options }
|
330
|
+
let(:expected_method) { :get }
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
describe "#add_milestone" do
|
336
|
+
describe "shared behavior" do
|
337
|
+
it_should_behave_like "an api call" do
|
338
|
+
let(:command) { :add_milestone }
|
339
|
+
let(:ids) { 'project_id' }
|
340
|
+
let(:opts) { post_options }
|
341
|
+
let(:expected_method) { :post }
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
describe "#get_project" do
|
347
|
+
describe "shared behavior" do
|
348
|
+
it_should_behave_like "an api call" do
|
349
|
+
let(:command) { :get_project }
|
350
|
+
let(:ids) { 'project_id' }
|
351
|
+
let(:opts) { get_options }
|
352
|
+
let(:expected_method) { :get }
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
describe "#get_projects" do
|
358
|
+
describe "shared behavior" do
|
359
|
+
it_should_behave_like "an api call" do
|
360
|
+
let(:command) { :get_projects }
|
361
|
+
let(:ids) { '' }
|
362
|
+
let(:opts) { get_options }
|
363
|
+
let(:expected_method) { :get }
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|