testrailv2 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.
- checksums.yaml +15 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +20 -0
- data/README.md +59 -0
- data/Rakefile +38 -0
- data/lib/testrail.rb +10 -0
- data/lib/testrail/client.rb +212 -0
- data/lib/testrail/command_helper.rb +29 -0
- data/lib/testrail/config.rb +36 -0
- data/lib/testrail/request.rb +60 -0
- data/lib/testrail/response.rb +41 -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 +128 -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
- metadata +188 -0
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Testrail do
|
4
|
+
subject { Testrail }
|
5
|
+
|
6
|
+
describe ".config" do
|
7
|
+
it "returns a Testrail::Config object" do
|
8
|
+
subject.config.should be_instance_of(Testrail::Config)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe ".configure" do
|
13
|
+
context "without a block" do
|
14
|
+
before do
|
15
|
+
@default_config = subject.config.dup
|
16
|
+
subject.configure
|
17
|
+
@actual_config = subject.config
|
18
|
+
end
|
19
|
+
|
20
|
+
it "returns the default configuration" do
|
21
|
+
@actual_config.server.should eq(@default_config.server)
|
22
|
+
@actual_config.api_path.should eq(@default_config.api_path)
|
23
|
+
@actual_config.api_key.should eq(@default_config.api_key)
|
24
|
+
@actual_config.logger.should be_instance_of(Logger)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "with a block" do
|
29
|
+
before do
|
30
|
+
@default_config = subject.config.dup
|
31
|
+
subject.configure { |config|
|
32
|
+
config.server = 'localhost'
|
33
|
+
}
|
34
|
+
@new_config = subject.config
|
35
|
+
end
|
36
|
+
|
37
|
+
it "overrides specified settings" do
|
38
|
+
subject.config.server.should eq(@new_config.server)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "retains any default settings not overwritten" do
|
42
|
+
subject.config.api_path.should eq(@default_config.api_path)
|
43
|
+
subject.config.api_key.should eq(@default_config.api_key)
|
44
|
+
subject.config.logger.should be_instance_of(Logger)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "@server & @api_path" do
|
49
|
+
context "with default settings" do
|
50
|
+
it "points to the Cloud Server" do
|
51
|
+
subject.config.server.should eq('https://example.testrail.com')
|
52
|
+
subject.config.api_path.should eq('/index.php?/miniapi/')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "with custom settings" do
|
57
|
+
before do
|
58
|
+
@new_server = new_server = 'http://localhost'
|
59
|
+
@new_api_path = new_api_path = '/some_path/'
|
60
|
+
subject.configure do |config|
|
61
|
+
config.server = new_server
|
62
|
+
config.api_path = new_api_path
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it "points to the new server" do
|
67
|
+
subject.config.server.should eq(@new_server)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "sets the new api_path" do
|
71
|
+
subject.config.api_path.should eq(@new_api_path)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "@api_key" do
|
77
|
+
context "with default settings" do
|
78
|
+
it "is nil" do
|
79
|
+
subject.config.api_key.should be_nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "with custom settings" do
|
84
|
+
before do
|
85
|
+
@new_api_key = new_api_key = 'my_new_api_key'
|
86
|
+
subject.configure do |config|
|
87
|
+
config.api_key = new_api_key
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it "sets the new api_key" do
|
92
|
+
subject.config.api_key.should eq(@new_api_key)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "@logger" do
|
98
|
+
context "with default settings" do
|
99
|
+
it "sets the logger to a Logger instance" do
|
100
|
+
subject.config.logger.should be_instance_of Logger
|
101
|
+
end
|
102
|
+
|
103
|
+
it "sets the output to STDOUT" do
|
104
|
+
Logger.stub!(:new)
|
105
|
+
Logger.should_receive(:new).with(STDOUT)
|
106
|
+
subject.configure
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context "with custom settings" do
|
111
|
+
before do
|
112
|
+
@mock_logger = mock_logger = mock('A Different Logger')
|
113
|
+
subject.configure do |config|
|
114
|
+
config.logger = mock_logger
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
it "returns the custom log object" do
|
119
|
+
subject.config.logger.should eq(@mock_logger)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
after do
|
126
|
+
Testrail.configure
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Testrail::Request do
|
4
|
+
subject { Testrail::Request }
|
5
|
+
|
6
|
+
shared_examples_for "a valid HTTPclient request" do
|
7
|
+
describe "interface" do
|
8
|
+
context "with successful transactions" do
|
9
|
+
before do
|
10
|
+
stub_request(:any, url_prefix + key).
|
11
|
+
with(action_options).
|
12
|
+
to_return(body: JSON.generate({result: true, an_object: 'abc'}))
|
13
|
+
stub_request(:any, url_prefix + '/789' + key).
|
14
|
+
with(action_options).
|
15
|
+
to_return(body: JSON.generate({result: true, an_object: 'abc'}))
|
16
|
+
stub_request(:any, url_prefix + '/789/a4g8' + key).
|
17
|
+
with(action_options).
|
18
|
+
to_return(body: JSON.generate({result: true, an_object: 'abc'}))
|
19
|
+
end
|
20
|
+
|
21
|
+
it "returns a Testrail::Response object" do
|
22
|
+
result = subject.send(method, command, action_options)
|
23
|
+
result.should be_instance_of Testrail::Response
|
24
|
+
end
|
25
|
+
|
26
|
+
context "with no ids" do
|
27
|
+
it "should call the HTTPclient with the correct parameters" do
|
28
|
+
subject.send(method, command, action_options)
|
29
|
+
WebMock.should have_requested(method, url_prefix + key)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "with a single id" do
|
34
|
+
it "should call the HTTPclient with the correct parameters" do
|
35
|
+
subject.send(method, command, 789, action_options)
|
36
|
+
WebMock.should have_requested(method, url_prefix + '/789' + key)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "with multiple ids" do
|
41
|
+
it "should call the HTTPclient with the correct parameters" do
|
42
|
+
subject.send(method, command, [789, 'a4g8'], action_options)
|
43
|
+
WebMock.should have_requested(method, url_prefix + '/789/a4g8' + key)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'error handling' do
|
50
|
+
context "with http_error response" do
|
51
|
+
before do
|
52
|
+
stub_request(:any, server + 'return_http_response_error' + key).
|
53
|
+
with(action_options).
|
54
|
+
to_return(status: 500)
|
55
|
+
@result = subject.send(method, 'return_http_response_error', action_options)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "returns a Testrail::Response object" do
|
59
|
+
@result.should be_instance_of Testrail::Response
|
60
|
+
end
|
61
|
+
|
62
|
+
it "returns a resulting object with @success set to false" do
|
63
|
+
@result.success.should be_false
|
64
|
+
end
|
65
|
+
|
66
|
+
it "puts the HTTP error type in @error" do
|
67
|
+
@result.error.should eq("InternalServerError")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "with a timeout" do
|
72
|
+
before do
|
73
|
+
@timeout_command = 'http_timeout'
|
74
|
+
@expected_url = server + @timeout_command + key
|
75
|
+
@logger = mock('Logger', error: 'an error')
|
76
|
+
Testrail.stub!(:logger).and_return(@logger)
|
77
|
+
stub_request(:any, @expected_url).
|
78
|
+
with(action_options).
|
79
|
+
to_timeout
|
80
|
+
end
|
81
|
+
|
82
|
+
it "raises a Timeout::Error" do
|
83
|
+
lambda {
|
84
|
+
@result = subject.send(method, @timeout_command, action_options)
|
85
|
+
}.should raise_error(Timeout::Error)
|
86
|
+
end
|
87
|
+
|
88
|
+
context "with a configured logger" do
|
89
|
+
it "logs the error" do
|
90
|
+
@logger.should_receive(:error).with("Timeout connecting to #{method.to_s.upcase} #{@expected_url}")
|
91
|
+
@error = subject.send(method, @timeout_command, action_options) rescue $!
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "with a nil logger" do
|
96
|
+
before do
|
97
|
+
Testrail.configure do |config|
|
98
|
+
config.logger = nil
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it "does not log the error" do
|
103
|
+
Testrail.logger.should_not_receive(:error)
|
104
|
+
end
|
105
|
+
|
106
|
+
after do
|
107
|
+
Testrail.configure
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "with any other exception" do
|
113
|
+
before do
|
114
|
+
@exception_command = 'throw_exception'
|
115
|
+
@expected_url = server + @exception_command + key
|
116
|
+
@logger = mock('Logger', error: 'an error')
|
117
|
+
Testrail.stub!(:logger).and_return(@logger)
|
118
|
+
stub_request(:any, @expected_url).
|
119
|
+
with(action_options).
|
120
|
+
to_raise(StandardError.new('unexpected exception'))
|
121
|
+
end
|
122
|
+
|
123
|
+
it "raises the exception" do
|
124
|
+
lambda {
|
125
|
+
@result = subject.send(method, @exception_command, action_options)
|
126
|
+
}.should raise_error(StandardError, 'unexpected exception')
|
127
|
+
end
|
128
|
+
|
129
|
+
context "with a configured logger" do
|
130
|
+
it "logs the exception" do
|
131
|
+
@logger.should_receive(:error).with(/Unexpected exception/)
|
132
|
+
@error = subject.send(method, @exception_command, action_options) rescue $!
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context "with a nil logger" do
|
137
|
+
before do
|
138
|
+
Testrail.configure do |config|
|
139
|
+
config.logger = nil
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
it "does not log the error" do
|
144
|
+
Testrail.logger.should_not_receive(:error)
|
145
|
+
end
|
146
|
+
|
147
|
+
after do
|
148
|
+
Testrail.configure
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe ".get" do
|
156
|
+
describe "shared behaviors" do
|
157
|
+
it_should_behave_like "a valid HTTPclient request" do
|
158
|
+
let(:method) { :get }
|
159
|
+
let(:action_options) { get_options }
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe ".post" do
|
165
|
+
describe "shared behaviors" do
|
166
|
+
it_should_behave_like "a valid HTTPclient request" do
|
167
|
+
let(:method) { :post }
|
168
|
+
let(:action_options) { post_options }
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class TestResponse
|
4
|
+
attr_accessor :body, :code
|
5
|
+
def initialize(code, opts = nil)
|
6
|
+
@code = code
|
7
|
+
unless opts.nil?
|
8
|
+
@body = JSON.generate(opts) rescue opts
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe Testrail::Response do
|
14
|
+
subject { Testrail::Response }
|
15
|
+
|
16
|
+
describe "initialize" do
|
17
|
+
context "with unsuccessful server response" do
|
18
|
+
before do
|
19
|
+
@response1 = subject.new(TestResponse.new('500'))
|
20
|
+
@response2 = subject.new(TestResponse.new('404'))
|
21
|
+
@response3 = subject.new(TestResponse.new('401'))
|
22
|
+
@response4 = subject.new(TestResponse.new('403'))
|
23
|
+
end
|
24
|
+
|
25
|
+
it "assigns false to @success" do
|
26
|
+
@response1.success.should be_false
|
27
|
+
@response2.success.should be_false
|
28
|
+
@response3.success.should be_false
|
29
|
+
@response4.success.should be_false
|
30
|
+
end
|
31
|
+
|
32
|
+
it "assigns the code definition to @error" do
|
33
|
+
@response1.error.should eq('InternalServerError')
|
34
|
+
@response2.error.should eq('NotFound')
|
35
|
+
@response3.error.should eq('Unauthorized')
|
36
|
+
@response4.error.should eq('Forbidden')
|
37
|
+
end
|
38
|
+
|
39
|
+
it "does not assign anything to @payload" do
|
40
|
+
@response1.payload.should be_nil
|
41
|
+
@response2.payload.should be_nil
|
42
|
+
@response3.payload.should be_nil
|
43
|
+
@response4.payload.should be_nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "with successful response, but no body" do
|
48
|
+
before do
|
49
|
+
@response = subject.new(TestResponse.new(200))
|
50
|
+
end
|
51
|
+
|
52
|
+
it "does not assign anything to @success" do
|
53
|
+
@response.success.should be_nil
|
54
|
+
end
|
55
|
+
|
56
|
+
it "does not assign anything to @error" do
|
57
|
+
@response.error.should be_nil
|
58
|
+
end
|
59
|
+
|
60
|
+
it "does not assign anything to @payload" do
|
61
|
+
@response.payload.should be_nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "with successful response, including a body" do
|
66
|
+
before do
|
67
|
+
@response = subject.new(TestResponse.new(200, result: true, some_obj: {id: 1, msg: 'some_msg'}))
|
68
|
+
end
|
69
|
+
|
70
|
+
it "assigns true to @success" do
|
71
|
+
@response.success.should be_true
|
72
|
+
end
|
73
|
+
|
74
|
+
it "does not assign anything to @error" do
|
75
|
+
@response.error.should be_nil
|
76
|
+
end
|
77
|
+
|
78
|
+
it "assigns the response body object to @payload" do
|
79
|
+
@response.payload.should eq({"some_obj" => {"id" => 1, "msg" => 'some_msg'}})
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "with the server successfully sending back an error" do
|
84
|
+
before do
|
85
|
+
@response = subject.new(TestResponse.new(200, result: false, error: 'Some error'))
|
86
|
+
end
|
87
|
+
|
88
|
+
it "assigns false to @success" do
|
89
|
+
@response.success.should be_false
|
90
|
+
end
|
91
|
+
|
92
|
+
it "assigns the returned error message to @error" do
|
93
|
+
@response.error.should eq('Some error')
|
94
|
+
end
|
95
|
+
|
96
|
+
it "does not assign anything to @payload" do
|
97
|
+
@response.payload.should be_nil
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "with the server returning an invalid JSON object" do
|
102
|
+
before do
|
103
|
+
@response = subject.new(TestResponse.new(200, 'something_with_malformed_response'))
|
104
|
+
end
|
105
|
+
|
106
|
+
it "assigns false to @success" do
|
107
|
+
@response.success.should be_false
|
108
|
+
end
|
109
|
+
|
110
|
+
it "assigns a Malformed JSON error message to @error" do
|
111
|
+
@response.error.should =~ /Malformed JSON response/
|
112
|
+
end
|
113
|
+
|
114
|
+
it "does not assign anything to @payload" do
|
115
|
+
@response.payload.should be_nil
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
4
|
+
require 'rspec'
|
5
|
+
require 'testrail'
|
6
|
+
require 'webmock/rspec'
|
7
|
+
require 'json'
|
8
|
+
require 'net/http'
|
9
|
+
|
10
|
+
# Requires supporting files with custom matchers and macros, etc,
|
11
|
+
# in ./support/ and its subdirectories.
|
12
|
+
Dir[File.join(File.dirname(__FILE__), 'support', '**', '*.rb')].each { |f| require f }
|