jira-ruby 1.7.1 → 2.1.2
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 +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +3 -2
- data/README.md +3 -3
- data/lib/jira-ruby.rb +1 -0
- data/lib/jira/base.rb +1 -1
- data/lib/jira/client.rb +57 -5
- data/lib/jira/http_client.rb +26 -11
- data/lib/jira/http_error.rb +1 -1
- data/lib/jira/jwt_client.rb +10 -9
- data/lib/jira/oauth_client.rb +15 -5
- data/lib/jira/request_client.rb +15 -3
- data/lib/jira/resource/attachment.rb +19 -14
- data/lib/jira/resource/board.rb +7 -0
- data/lib/jira/resource/board_configuration.rb +9 -0
- data/lib/jira/resource/sprint.rb +12 -8
- data/lib/jira/resource/watcher.rb +7 -0
- data/lib/jira/version.rb +1 -1
- data/spec/integration/watcher_spec.rb +15 -6
- data/spec/jira/base_spec.rb +12 -0
- data/spec/jira/client_spec.rb +9 -0
- data/spec/jira/http_client_spec.rb +130 -6
- data/spec/jira/oauth_client_spec.rb +27 -10
- data/spec/jira/request_client_spec.rb +37 -10
- data/spec/jira/resource/attachment_spec.rb +79 -22
- data/spec/jira/resource/board_spec.rb +49 -0
- data/spec/jira/resource/sprint_spec.rb +23 -11
- metadata +28 -28
data/lib/jira/resource/sprint.rb
CHANGED
@@ -5,7 +5,7 @@ module JIRA
|
|
5
5
|
|
6
6
|
class Sprint < JIRA::Base
|
7
7
|
def self.find(client, key)
|
8
|
-
response = client.get(
|
8
|
+
response = client.get(agile_path(client, key))
|
9
9
|
json = parse_json(response.body)
|
10
10
|
client.Sprint.build(json)
|
11
11
|
end
|
@@ -19,7 +19,7 @@ module JIRA
|
|
19
19
|
|
20
20
|
def add_issue(issue)
|
21
21
|
request_body = { issues: [issue.id] }.to_json
|
22
|
-
response = client.post(
|
22
|
+
response = client.post("#{agile_path}/issue", request_body)
|
23
23
|
true
|
24
24
|
end
|
25
25
|
|
@@ -47,8 +47,8 @@ module JIRA
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def get_sprint_details
|
50
|
-
search_url =
|
51
|
-
|
50
|
+
search_url =
|
51
|
+
"#{client.options[:site]}#{client.options[:client_path]}/rest/greenhopper/1.0/rapid/charts/sprintreport?rapidViewId=#{rapidview_id}&sprintId=#{id}"
|
52
52
|
begin
|
53
53
|
response = client.get(search_url)
|
54
54
|
rescue StandardError
|
@@ -76,12 +76,12 @@ module JIRA
|
|
76
76
|
|
77
77
|
def save(attrs = {}, _path = nil)
|
78
78
|
attrs = @attrs if attrs.empty?
|
79
|
-
super(attrs,
|
79
|
+
super(attrs, agile_path)
|
80
80
|
end
|
81
81
|
|
82
82
|
def save!(attrs = {}, _path = nil)
|
83
83
|
attrs = @attrs if attrs.empty?
|
84
|
-
super(attrs,
|
84
|
+
super(attrs, agile_path)
|
85
85
|
end
|
86
86
|
|
87
87
|
# WORK IN PROGRESS
|
@@ -93,8 +93,12 @@ module JIRA
|
|
93
93
|
|
94
94
|
private
|
95
95
|
|
96
|
-
def
|
97
|
-
|
96
|
+
def agile_path
|
97
|
+
self.class.agile_path(client, id)
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.agile_path(client, key)
|
101
|
+
"#{client.options[:context_path]}/rest/agile/1.0/sprint/#{key}"
|
98
102
|
end
|
99
103
|
end
|
100
104
|
end
|
data/lib/jira/version.rb
CHANGED
@@ -33,21 +33,30 @@ describe JIRA::Resource::Watcher do
|
|
33
33
|
end
|
34
34
|
|
35
35
|
describe 'watchers' do
|
36
|
-
|
37
|
-
stub_request(:get,
|
38
|
-
site_url + '/jira/rest/api/2/issue/10002')
|
36
|
+
before(:each) do
|
37
|
+
stub_request(:get, site_url + '/jira/rest/api/2/issue/10002')
|
39
38
|
.to_return(status: 200, body: get_mock_response('issue/10002.json'))
|
40
39
|
|
41
|
-
stub_request(:get,
|
42
|
-
site_url + '/jira/rest/api/2/issue/10002/watchers')
|
40
|
+
stub_request(:get, site_url + '/jira/rest/api/2/issue/10002/watchers')
|
43
41
|
.to_return(status: 200, body: get_mock_response('issue/10002/watchers.json'))
|
44
42
|
|
43
|
+
stub_request(:post, site_url + '/jira/rest/api/2/issue/10002/watchers')
|
44
|
+
.to_return(status: 204, body: nil)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should returns all the watchers' do
|
45
48
|
issue = client.Issue.find('10002')
|
46
49
|
watchers = client.Watcher.all(options = { issue: issue })
|
47
50
|
expect(watchers.length).to eq(1)
|
48
51
|
end
|
52
|
+
|
53
|
+
it 'should add a watcher' do
|
54
|
+
issue = client.Issue.find('10002')
|
55
|
+
watcher = JIRA::Resource::Watcher.new(client, issue: issue)
|
56
|
+
user_id = "tester"
|
57
|
+
watcher.save!(user_id)
|
58
|
+
end
|
49
59
|
end
|
50
60
|
|
51
|
-
it_should_behave_like 'a resource'
|
52
61
|
end
|
53
62
|
end
|
data/spec/jira/base_spec.rb
CHANGED
@@ -369,6 +369,18 @@ describe JIRA::Base do
|
|
369
369
|
expect(subject.url).to eq('http://foo/bar')
|
370
370
|
end
|
371
371
|
|
372
|
+
it 'returns path as the URL if set and site options is specified' do
|
373
|
+
allow(client).to receive(:options) { { site: 'http://foo' } }
|
374
|
+
attrs['self'] = 'http://foo/bar'
|
375
|
+
expect(subject.url).to eq('/bar')
|
376
|
+
end
|
377
|
+
|
378
|
+
it 'returns path as the URL if set and site options is specified and ends with a slash' do
|
379
|
+
allow(client).to receive(:options) { { site: 'http://foo/' } }
|
380
|
+
attrs['self'] = 'http://foo/bar'
|
381
|
+
expect(subject.url).to eq('/bar')
|
382
|
+
end
|
383
|
+
|
372
384
|
it 'generates the URL from id if self not set' do
|
373
385
|
attrs['self'] = nil
|
374
386
|
attrs['id'] = '98765'
|
data/spec/jira/client_spec.rb
CHANGED
@@ -266,4 +266,13 @@ describe JIRA::Client do
|
|
266
266
|
|
267
267
|
include_examples 'OAuth Common Tests'
|
268
268
|
end
|
269
|
+
|
270
|
+
context 'with unknown options' do
|
271
|
+
let(:options) { { 'username' => 'foo', 'password' => 'bar', auth_type: :basic } }
|
272
|
+
subject { JIRA::Client.new(options) }
|
273
|
+
|
274
|
+
it 'raises an ArgumentError' do
|
275
|
+
expect { subject }.to raise_exception(ArgumentError, 'Unknown option(s) given: ["username", "password"]')
|
276
|
+
end
|
277
|
+
end
|
269
278
|
end
|
@@ -2,12 +2,22 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe JIRA::HttpClient do
|
4
4
|
let(:basic_client) do
|
5
|
-
options = JIRA::Client::DEFAULT_OPTIONS
|
5
|
+
options = JIRA::Client::DEFAULT_OPTIONS
|
6
|
+
.merge(JIRA::HttpClient::DEFAULT_OPTIONS)
|
7
|
+
.merge(basic_auth_credentials)
|
6
8
|
JIRA::HttpClient.new(options)
|
7
9
|
end
|
8
10
|
|
9
11
|
let(:basic_cookie_client) do
|
10
|
-
options = JIRA::Client::DEFAULT_OPTIONS
|
12
|
+
options = JIRA::Client::DEFAULT_OPTIONS
|
13
|
+
.merge(JIRA::HttpClient::DEFAULT_OPTIONS)
|
14
|
+
.merge(use_cookies: true)
|
15
|
+
.merge(basic_auth_credentials)
|
16
|
+
JIRA::HttpClient.new(options)
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:custom_ssl_version_client) do
|
20
|
+
options = JIRA::Client::DEFAULT_OPTIONS.merge(JIRA::HttpClient::DEFAULT_OPTIONS).merge(ssl_version: :TLSv1_2)
|
11
21
|
JIRA::HttpClient.new(options)
|
12
22
|
end
|
13
23
|
|
@@ -20,10 +30,13 @@ describe JIRA::HttpClient do
|
|
20
30
|
end
|
21
31
|
|
22
32
|
let(:basic_cookie_client_with_additional_cookies) do
|
23
|
-
options = JIRA::Client::DEFAULT_OPTIONS
|
24
|
-
|
25
|
-
|
26
|
-
|
33
|
+
options = JIRA::Client::DEFAULT_OPTIONS
|
34
|
+
.merge(JIRA::HttpClient::DEFAULT_OPTIONS)
|
35
|
+
.merge(
|
36
|
+
use_cookies: true,
|
37
|
+
additional_cookies: ['sessionToken=abc123', 'internal=true']
|
38
|
+
)
|
39
|
+
.merge(basic_auth_credentials)
|
27
40
|
JIRA::HttpClient.new(options)
|
28
41
|
end
|
29
42
|
|
@@ -36,6 +49,26 @@ describe JIRA::HttpClient do
|
|
36
49
|
JIRA::HttpClient.new(options)
|
37
50
|
end
|
38
51
|
|
52
|
+
let(:basic_client_with_no_auth_credentials) do
|
53
|
+
options = JIRA::Client::DEFAULT_OPTIONS
|
54
|
+
.merge(JIRA::HttpClient::DEFAULT_OPTIONS)
|
55
|
+
JIRA::HttpClient.new(options)
|
56
|
+
end
|
57
|
+
|
58
|
+
let(:basic_auth_credentials) do
|
59
|
+
{ username: 'donaldduck', password: 'supersecret' }
|
60
|
+
end
|
61
|
+
|
62
|
+
let(:proxy_client) do
|
63
|
+
options = JIRA::Client::DEFAULT_OPTIONS.merge(JIRA::HttpClient::DEFAULT_OPTIONS).merge(
|
64
|
+
proxy_address: 'proxyAddress',
|
65
|
+
proxy_port: 42,
|
66
|
+
proxy_username: 'proxyUsername',
|
67
|
+
proxy_password: 'proxyPassword'
|
68
|
+
)
|
69
|
+
JIRA::HttpClient.new(options)
|
70
|
+
end
|
71
|
+
|
39
72
|
let(:response) do
|
40
73
|
response = double('response')
|
41
74
|
allow(response).to receive(:kind_of?).with(Net::HTTPSuccess).and_return(true)
|
@@ -159,6 +192,19 @@ describe JIRA::HttpClient do
|
|
159
192
|
basic_client.make_request(:get, 'http://mydomain.com/foo', body, headers)
|
160
193
|
end
|
161
194
|
|
195
|
+
it 'does not try to use basic auth if the credentials are not set' do
|
196
|
+
body = nil
|
197
|
+
headers = double
|
198
|
+
basic_auth_http_conn = double
|
199
|
+
http_request = double
|
200
|
+
expect(Net::HTTP::Get).to receive(:new).with('/foo', headers).and_return(http_request)
|
201
|
+
|
202
|
+
expect(basic_auth_http_conn).to receive(:request).with(http_request).and_return(response)
|
203
|
+
expect(http_request).not_to receive(:basic_auth)
|
204
|
+
allow(basic_client_with_no_auth_credentials).to receive(:basic_auth_http_conn).and_return(basic_auth_http_conn)
|
205
|
+
basic_client_with_no_auth_credentials.make_request(:get, '/foo', body, headers)
|
206
|
+
end
|
207
|
+
|
162
208
|
it 'returns a URI' do
|
163
209
|
uri = URI.parse(basic_client.options[:site])
|
164
210
|
expect(basic_client.uri).to eq(uri)
|
@@ -178,6 +224,51 @@ describe JIRA::HttpClient do
|
|
178
224
|
expect(basic_client.http_conn(uri)).to eq(http_conn)
|
179
225
|
end
|
180
226
|
|
227
|
+
it 'sets the SSL version when one is provided' do
|
228
|
+
http_conn = double
|
229
|
+
uri = double
|
230
|
+
host = double
|
231
|
+
port = double
|
232
|
+
expect(uri).to receive(:host).and_return(host)
|
233
|
+
expect(uri).to receive(:port).and_return(port)
|
234
|
+
expect(Net::HTTP).to receive(:new).with(host, port).and_return(http_conn)
|
235
|
+
expect(http_conn).to receive(:use_ssl=).with(basic_client.options[:use_ssl]).and_return(http_conn)
|
236
|
+
expect(http_conn).to receive(:verify_mode=).with(basic_client.options[:ssl_verify_mode]).and_return(http_conn)
|
237
|
+
expect(http_conn).to receive(:ssl_version=).with(custom_ssl_version_client.options[:ssl_version]).and_return(http_conn)
|
238
|
+
expect(http_conn).to receive(:read_timeout=).with(basic_client.options[:read_timeout]).and_return(http_conn)
|
239
|
+
expect(custom_ssl_version_client.http_conn(uri)).to eq(http_conn)
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'sets up a non-proxied http connection by default' do
|
243
|
+
uri = double
|
244
|
+
host = double
|
245
|
+
port = double
|
246
|
+
|
247
|
+
expect(uri).to receive(:host).and_return(host)
|
248
|
+
expect(uri).to receive(:port).and_return(port)
|
249
|
+
|
250
|
+
proxy_configuration = basic_client.http_conn(uri).class
|
251
|
+
expect(proxy_configuration.proxy_address).to be_nil
|
252
|
+
expect(proxy_configuration.proxy_port).to be_nil
|
253
|
+
expect(proxy_configuration.proxy_user).to be_nil
|
254
|
+
expect(proxy_configuration.proxy_pass).to be_nil
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'sets up a proxied http connection when using proxy options' do
|
258
|
+
uri = double
|
259
|
+
host = double
|
260
|
+
port = double
|
261
|
+
|
262
|
+
expect(uri).to receive(:host).and_return(host)
|
263
|
+
expect(uri).to receive(:port).and_return(port)
|
264
|
+
|
265
|
+
proxy_configuration = proxy_client.http_conn(uri).class
|
266
|
+
expect(proxy_configuration.proxy_address).to eq(proxy_client.options[:proxy_address])
|
267
|
+
expect(proxy_configuration.proxy_port).to eq(proxy_client.options[:proxy_port])
|
268
|
+
expect(proxy_configuration.proxy_user).to eq(proxy_client.options[:proxy_username])
|
269
|
+
expect(proxy_configuration.proxy_pass).to eq(proxy_client.options[:proxy_password])
|
270
|
+
end
|
271
|
+
|
181
272
|
it 'can use client certificates' do
|
182
273
|
http_conn = double
|
183
274
|
uri = double
|
@@ -201,4 +292,37 @@ describe JIRA::HttpClient do
|
|
201
292
|
expect(basic_client).to receive(:http_conn).and_return(http_conn)
|
202
293
|
expect(basic_client.basic_auth_http_conn).to eq(http_conn)
|
203
294
|
end
|
295
|
+
|
296
|
+
describe '#make_multipart_request' do
|
297
|
+
subject do
|
298
|
+
basic_client.make_multipart_request(path, data, headers)
|
299
|
+
end
|
300
|
+
|
301
|
+
let(:path) { '/foo' }
|
302
|
+
let(:data) { {} }
|
303
|
+
let(:headers) { { 'X-Atlassian-Token' => 'no-check' } }
|
304
|
+
let(:basic_auth_http_conn) { double }
|
305
|
+
let(:request) { double('Http Request', path: path) }
|
306
|
+
let(:response) { double('response') }
|
307
|
+
|
308
|
+
before do
|
309
|
+
allow(request).to receive(:basic_auth)
|
310
|
+
allow(Net::HTTP::Post::Multipart).to receive(:new).with(path, data, headers).and_return(request)
|
311
|
+
allow(basic_client).to receive(:basic_auth_http_conn).and_return(basic_auth_http_conn)
|
312
|
+
allow(basic_auth_http_conn).to receive(:request).with(request).and_return(response)
|
313
|
+
end
|
314
|
+
|
315
|
+
it 'performs a basic http client request' do
|
316
|
+
expect(request).to receive(:basic_auth).with(basic_client.options[:username], basic_client.options[:password]).and_return(request)
|
317
|
+
|
318
|
+
subject
|
319
|
+
end
|
320
|
+
|
321
|
+
it 'makes a correct HTTP request' do
|
322
|
+
expect(basic_auth_http_conn).to receive(:request).with(request).and_return(response)
|
323
|
+
expect(response).to receive(:is_a?).with(Net::HTTPOK)
|
324
|
+
|
325
|
+
subject
|
326
|
+
end
|
327
|
+
end
|
204
328
|
end
|
@@ -82,28 +82,45 @@ describe JIRA::OauthClient do
|
|
82
82
|
end
|
83
83
|
|
84
84
|
describe 'http' do
|
85
|
+
let(:headers) { double }
|
86
|
+
let(:access_token) { double }
|
87
|
+
let(:body) { nil }
|
88
|
+
|
89
|
+
before do
|
90
|
+
allow(oauth_client).to receive(:access_token).and_return(access_token)
|
91
|
+
end
|
92
|
+
|
85
93
|
it 'responds to the http methods' do
|
86
|
-
headers = double
|
87
|
-
mock_access_token = double
|
88
|
-
allow(oauth_client).to receive(:access_token).and_return(mock_access_token)
|
89
94
|
%i[delete get head].each do |method|
|
90
|
-
expect(
|
95
|
+
expect(access_token).to receive(method).with('/path', headers).and_return(response)
|
91
96
|
oauth_client.make_request(method, '/path', '', headers)
|
92
97
|
end
|
93
98
|
%i[post put].each do |method|
|
94
|
-
expect(
|
99
|
+
expect(access_token).to receive(method).with('/path', '', headers).and_return(response)
|
95
100
|
oauth_client.make_request(method, '/path', '', headers)
|
96
101
|
end
|
97
102
|
end
|
98
103
|
|
99
104
|
it 'performs a request' do
|
100
|
-
body = nil
|
101
|
-
headers = double
|
102
|
-
access_token = double
|
103
105
|
expect(access_token).to receive(:send).with(:get, '/foo', headers).and_return(response)
|
104
|
-
|
106
|
+
|
107
|
+
|
105
108
|
oauth_client.request(:get, '/foo', body, headers)
|
106
109
|
end
|
110
|
+
|
111
|
+
context 'for a multipart request' do
|
112
|
+
subject { oauth_client.make_multipart_request('/path', data, headers) }
|
113
|
+
|
114
|
+
let(:data) { {} }
|
115
|
+
let(:headers) { {} }
|
116
|
+
|
117
|
+
it 'signs the access_token and performs the request' do
|
118
|
+
expect(access_token).to receive(:sign!).with(an_instance_of(Net::HTTP::Post::Multipart))
|
119
|
+
expect(oauth_client.consumer).to receive_message_chain(:http, :request).with(an_instance_of(Net::HTTP::Post::Multipart))
|
120
|
+
|
121
|
+
subject
|
122
|
+
end
|
123
|
+
end
|
107
124
|
end
|
108
125
|
|
109
126
|
describe 'auth type is oauth_2legged' do
|
@@ -142,4 +159,4 @@ describe JIRA::OauthClient do
|
|
142
159
|
end
|
143
160
|
end
|
144
161
|
end
|
145
|
-
end
|
162
|
+
end
|
@@ -1,14 +1,41 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe JIRA::RequestClient do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
4
|
+
let(:request_client) { JIRA::RequestClient.new }
|
5
|
+
|
6
|
+
describe '#request' do
|
7
|
+
subject(:request) { request_client.request(:get, '/foo', '', {}) }
|
8
|
+
|
9
|
+
context 'when doing a request fails' do
|
10
|
+
let(:response) { double }
|
11
|
+
|
12
|
+
before do
|
13
|
+
allow(response).to receive(:kind_of?).with(Net::HTTPSuccess).and_return(false)
|
14
|
+
allow(request_client).to receive(:make_request).with(:get, '/foo', '', {}).and_return(response)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'raises an exception' do
|
18
|
+
expect{ subject }.to raise_exception(JIRA::HTTPError)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#request_multipart' do
|
24
|
+
subject(:request) { request_client.request_multipart('/foo', data, {}) }
|
25
|
+
|
26
|
+
let(:data) { double }
|
27
|
+
|
28
|
+
context 'when doing a request fails' do
|
29
|
+
let(:response) { double }
|
30
|
+
|
31
|
+
before do
|
32
|
+
allow(response).to receive(:kind_of?).with(Net::HTTPSuccess).and_return(false)
|
33
|
+
allow(request_client).to receive(:make_multipart_request).with('/foo', data, {}).and_return(response)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'raises an exception' do
|
37
|
+
expect{ subject }.to raise_exception(JIRA::HTTPError)
|
38
|
+
end
|
39
|
+
end
|
13
40
|
end
|
14
|
-
end
|
41
|
+
end
|