jira-ruby 1.2.0 → 1.3.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 +4 -4
- data/README.md +391 -0
- data/jira-ruby.gemspec +2 -1
- data/lib/jira/base.rb +1 -1
- data/lib/jira/base_factory.rb +2 -2
- data/lib/jira/client.rb +7 -4
- data/lib/jira/http_client.rb +11 -3
- data/lib/jira/oauth_client.rb +7 -0
- data/lib/jira/resource/agile.rb +17 -4
- data/lib/jira/resource/attachment.rb +30 -1
- data/lib/jira/resource/issue.rb +17 -0
- data/lib/jira/version.rb +1 -1
- data/spec/integration/attachment_spec.rb +11 -1
- data/spec/jira/client_spec.rb +169 -164
- data/spec/jira/http_client_spec.rb +57 -0
- data/spec/jira/resource/agile_spec.rb +81 -0
- data/spec/jira/resource/attachment_spec.rb +60 -4
- data/spec/mock_responses/board/1.json +33 -0
- data/spec/mock_responses/{attachment → issue/10002/attachment}/10000.json +0 -0
- data/spec/mock_responses/sprint/1_issues.json +125 -0
- metadata +26 -5
- data/README.rdoc +0 -333
data/lib/jira/client.rb
CHANGED
@@ -23,9 +23,10 @@ module JIRA
|
|
23
23
|
# :use_ssl => true,
|
24
24
|
# :username => nil,
|
25
25
|
# :password => nil,
|
26
|
-
# :auth_type => :oauth
|
27
|
-
# :proxy_address => nil
|
28
|
-
# :proxy_port => nil
|
26
|
+
# :auth_type => :oauth,
|
27
|
+
# :proxy_address => nil,
|
28
|
+
# :proxy_port => nil,
|
29
|
+
# :additional_cookies => nil
|
29
30
|
#
|
30
31
|
# See the JIRA::Base class methods for all of the available methods on these accessor
|
31
32
|
# objects.
|
@@ -43,7 +44,7 @@ module JIRA
|
|
43
44
|
# The configuration options for this client instance
|
44
45
|
attr_reader :options
|
45
46
|
|
46
|
-
def_delegators :@request_client, :init_access_token, :set_access_token, :set_request_token, :request_token, :access_token
|
47
|
+
def_delegators :@request_client, :init_access_token, :set_access_token, :set_request_token, :request_token, :access_token, :authenticated?
|
47
48
|
|
48
49
|
DEFAULT_OPTIONS = {
|
49
50
|
:site => 'http://localhost:2990',
|
@@ -71,6 +72,8 @@ module JIRA
|
|
71
72
|
@options[:use_cookies] = true
|
72
73
|
@request_client = HttpClient.new(@options)
|
73
74
|
@request_client.make_cookie_auth_request
|
75
|
+
@options.delete(:username)
|
76
|
+
@options.delete(:password)
|
74
77
|
else
|
75
78
|
raise ArgumentError, 'Options: ":auth_type" must be ":oauth", ":cookie" or ":basic"'
|
76
79
|
end
|
data/lib/jira/http_client.rb
CHANGED
@@ -19,15 +19,18 @@ module JIRA
|
|
19
19
|
|
20
20
|
def make_cookie_auth_request
|
21
21
|
body = { :username => @options[:username], :password => @options[:password] }.to_json
|
22
|
-
|
22
|
+
@options.delete(:username)
|
23
|
+
@options.delete(:password)
|
24
|
+
make_request(:post, @options[:context_path] + '/rest/auth/1/session', body, {'Content-Type' => 'application/json'})
|
23
25
|
end
|
24
26
|
|
25
27
|
def make_request(http_method, path, body='', headers={})
|
26
28
|
request = Net::HTTP.const_get(http_method.to_s.capitalize).new(path, headers)
|
27
29
|
request.body = body unless body.nil?
|
28
30
|
add_cookies(request) if options[:use_cookies]
|
29
|
-
request.basic_auth(@options[:username], @options[:password])
|
31
|
+
request.basic_auth(@options[:username], @options[:password]) if @options[:username] && @options[:password]
|
30
32
|
response = basic_auth_http_conn.request(request)
|
33
|
+
@authenticated = response.is_a? Net::HTTPOK
|
31
34
|
store_cookies(response) if options[:use_cookies]
|
32
35
|
response
|
33
36
|
end
|
@@ -53,6 +56,10 @@ module JIRA
|
|
53
56
|
uri = URI.parse(@options[:site])
|
54
57
|
end
|
55
58
|
|
59
|
+
def authenticated?
|
60
|
+
@authenticated
|
61
|
+
end
|
62
|
+
|
56
63
|
private
|
57
64
|
|
58
65
|
def store_cookies(response)
|
@@ -67,7 +74,8 @@ module JIRA
|
|
67
74
|
end
|
68
75
|
|
69
76
|
def add_cookies(request)
|
70
|
-
cookie_array = @cookies.values.map { |cookie| cookie.
|
77
|
+
cookie_array = @cookies.values.map { |cookie| "#{cookie.name}=#{cookie.value[0]}" }
|
78
|
+
cookie_array += Array(@options[:additional_cookies]) if @options.key?(:additional_cookies)
|
71
79
|
request.add_field('Cookie', cookie_array.join('; ')) if cookie_array.any?
|
72
80
|
request
|
73
81
|
end
|
data/lib/jira/oauth_client.rb
CHANGED
@@ -62,6 +62,8 @@ module JIRA
|
|
62
62
|
# Sets the access token from a preexisting token and secret.
|
63
63
|
def set_access_token(token, secret)
|
64
64
|
@access_token = OAuth::AccessToken.new(@consumer, token, secret)
|
65
|
+
@authenticated = true
|
66
|
+
@access_token
|
65
67
|
end
|
66
68
|
|
67
69
|
# Returns the current access token. Raises an
|
@@ -78,7 +80,12 @@ module JIRA
|
|
78
80
|
when :post, :put
|
79
81
|
response = access_token.send http_method, path, body, headers
|
80
82
|
end
|
83
|
+
@authenticated = true
|
81
84
|
response
|
82
85
|
end
|
86
|
+
|
87
|
+
def authenticated?
|
88
|
+
@authenticated
|
89
|
+
end
|
83
90
|
end
|
84
91
|
end
|
data/lib/jira/resource/agile.rb
CHANGED
@@ -15,19 +15,33 @@ module JIRA
|
|
15
15
|
|
16
16
|
def self.get_backlog_issues(client, board_id, options = {})
|
17
17
|
options[:maxResults] ||= 100
|
18
|
-
response = client.get("/
|
18
|
+
response = client.get(path_base(client) + "/board/#{board_id}/backlog?#{hash_to_query_string(options)}")
|
19
19
|
parse_json(response.body)
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.get_sprints(client, board_id, options = {})
|
23
23
|
options[:maxResults] ||= 100
|
24
|
-
response = client.get("/
|
24
|
+
response = client.get(path_base(client) + "/board/#{board_id}/sprint?#{hash_to_query_string(options)}")
|
25
25
|
parse_json(response.body)
|
26
26
|
end
|
27
27
|
|
28
28
|
def self.get_sprint_issues(client, sprint_id, options = {})
|
29
29
|
options[:maxResults] ||= 100
|
30
|
-
response = client.get("/
|
30
|
+
response = client.get(path_base(client) + "/sprint/#{sprint_id}/issue?#{hash_to_query_string(options)}")
|
31
|
+
parse_json(response.body)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.get_projects_full(client, board_id, options = {})
|
35
|
+
response = client.get(path_base(client) + "/board/#{board_id}/project/full")
|
36
|
+
parse_json(response.body)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.get_projects(client, board_id, options = {})
|
40
|
+
options[:maxResults] ||= 100
|
41
|
+
create_meta_url = path_base(client) + "/board/#{board_id}/project"
|
42
|
+
params = hash_to_query_string(options)
|
43
|
+
|
44
|
+
response = client.get("#{create_meta_url}?#{params}")
|
31
45
|
parse_json(response.body)
|
32
46
|
end
|
33
47
|
|
@@ -47,7 +61,6 @@ module JIRA
|
|
47
61
|
def path_base(client)
|
48
62
|
self.class.path_base(client)
|
49
63
|
end
|
50
|
-
|
51
64
|
end
|
52
65
|
|
53
66
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'net/http/post/multipart'
|
2
|
+
|
1
3
|
module JIRA
|
2
4
|
module Resource
|
3
5
|
|
@@ -5,8 +7,35 @@ module JIRA
|
|
5
7
|
end
|
6
8
|
|
7
9
|
class Attachment < JIRA::Base
|
10
|
+
belongs_to :issue
|
8
11
|
has_one :author, :class => JIRA::Resource::User
|
9
|
-
end
|
10
12
|
|
13
|
+
def self.meta(client)
|
14
|
+
response = client.get(client.options[:rest_base_path] + '/attachment/meta')
|
15
|
+
parse_json(response.body)
|
16
|
+
end
|
17
|
+
|
18
|
+
def save!(attrs)
|
19
|
+
headers = { 'X-Atlassian-Token' => 'nocheck' }
|
20
|
+
data = { 'file' => UploadIO.new(attrs['file'], 'application/binary', attrs['file']) }
|
21
|
+
|
22
|
+
request = Net::HTTP::Post::Multipart.new url, data, headers
|
23
|
+
request.basic_auth(client.request_client.options[:username],
|
24
|
+
client.request_client.options[:password])
|
25
|
+
|
26
|
+
response = client.request_client.basic_auth_http_conn.request(request)
|
27
|
+
|
28
|
+
set_attrs(attrs, false)
|
29
|
+
unless response.body.nil? || response.body.length < 2
|
30
|
+
json = self.class.parse_json(response.body)
|
31
|
+
attachment = json[0]
|
32
|
+
|
33
|
+
set_attrs(attachment)
|
34
|
+
end
|
35
|
+
|
36
|
+
@expanded = false
|
37
|
+
true
|
38
|
+
end
|
39
|
+
end
|
11
40
|
end
|
12
41
|
end
|
data/lib/jira/resource/issue.rb
CHANGED
@@ -71,6 +71,23 @@ module JIRA
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
# Fetches the attributes for the specified resource from JIRA unless
|
75
|
+
# the resource is already expanded and the optional force reload flag
|
76
|
+
# is not set
|
77
|
+
def fetch(reload = false, query_params = {})
|
78
|
+
return if expanded? && !reload
|
79
|
+
response = client.get(url_with_query_params(url, query_params))
|
80
|
+
set_attrs_from_response(response)
|
81
|
+
if @attrs and @attrs['fields'] and @attrs['fields']['worklog'] and @attrs['fields']['worklog']['total'] > @attrs['fields']['worklog']['maxResults']
|
82
|
+
worklog_url = client.options[:rest_base_path] + "/#{self.class.endpoint_name}/#{id}/worklog"
|
83
|
+
response = client.get(worklog_url)
|
84
|
+
unless response.body.nil? or response.body.length < 2
|
85
|
+
set_attrs({'fields' => { 'worklog' => self.class.parse_json(response.body) }}, false)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
@expanded = true
|
89
|
+
end
|
90
|
+
|
74
91
|
def editmeta
|
75
92
|
editmeta_url = client.options[:rest_base_path] + "/#{self.class.endpoint_name}/#{key}/editmeta"
|
76
93
|
|
data/lib/jira/version.rb
CHANGED
@@ -8,6 +8,8 @@ describe JIRA::Resource::Attachment do
|
|
8
8
|
|
9
9
|
let(:key) { "10000" }
|
10
10
|
|
11
|
+
let(:target) { JIRA::Resource::Attachment.new(client, :attrs => {'id' => '99999'}, :issue_id => '10002') }
|
12
|
+
|
11
13
|
let(:expected_attributes) do
|
12
14
|
{
|
13
15
|
'self' => "http://localhost:2990/jira/rest/api/2/attachment/10000",
|
@@ -16,7 +18,15 @@ describe JIRA::Resource::Attachment do
|
|
16
18
|
}
|
17
19
|
end
|
18
20
|
|
19
|
-
|
21
|
+
let(:belongs_to) {
|
22
|
+
JIRA::Resource::Issue.new(client, :attrs => {
|
23
|
+
'id' => '10002',
|
24
|
+
'fields' => {
|
25
|
+
'attachment' => {'attachments' => []}
|
26
|
+
}
|
27
|
+
})
|
28
|
+
}
|
29
|
+
|
20
30
|
it_should_behave_like "a resource with a singular GET endpoint"
|
21
31
|
it_should_behave_like "a resource with a DELETE endpoint"
|
22
32
|
end
|
data/spec/jira/client_spec.rb
CHANGED
@@ -1,223 +1,228 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
# We have three forms of authentication with two clases to represent the client for those different authentications.
|
4
|
+
# Some behaviours are shared across all three types of authentication. these are captured here.
|
5
|
+
RSpec.shared_examples 'Client Common Tests' do
|
6
|
+
it { is_expected.to be_a JIRA::Client }
|
7
|
+
|
8
|
+
it 'freezes the options once initialised' do
|
9
|
+
expect(subject.options).to be_frozen
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'prepends context path to rest base_path' do
|
13
|
+
options = [:rest_base_path]
|
14
|
+
defaults = JIRA::Client::DEFAULT_OPTIONS
|
15
|
+
options.each { |key| expect(subject.options[key]).to eq(defaults[:context_path] + defaults[key]) }
|
7
16
|
end
|
8
17
|
|
9
|
-
|
10
|
-
|
18
|
+
it 'merges headers' do
|
19
|
+
expect(subject.send(:merge_default_headers, {})).to eq({'Accept' => 'application/json'})
|
11
20
|
end
|
12
21
|
|
13
|
-
|
14
|
-
|
22
|
+
describe 'http methods' do
|
23
|
+
it 'merges default headers' do
|
24
|
+
# stubbed response for generic client request method
|
25
|
+
expect(subject).to receive(:request).exactly(5).times.and_return(successful_response)
|
26
|
+
|
27
|
+
# response for merging headers for http methods with no body
|
28
|
+
expect(subject).to receive(:merge_default_headers).exactly(3).times.with({})
|
29
|
+
|
30
|
+
# response for merging headers for http methods with body
|
31
|
+
expect(subject).to receive(:merge_default_headers).exactly(2).times.with(content_type_header)
|
32
|
+
|
33
|
+
[:delete, :get, :head].each { |method| subject.send(method, '/path', {}) }
|
34
|
+
[:post, :put].each {|method| subject.send(method, '/path', '', content_type_header)}
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'calls the generic request method' do
|
38
|
+
[:delete, :get, :head].each do |method|
|
39
|
+
expect(subject).to receive(:request).with(method, '/path', nil, headers).and_return(successful_response)
|
40
|
+
subject.send(method, '/path', {})
|
41
|
+
end
|
42
|
+
|
43
|
+
[:post, :put].each do |method|
|
44
|
+
expect(subject).to receive(:request).with(method, '/path', '', merged_headers)
|
45
|
+
subject.send(method, '/path', '', {})
|
46
|
+
end
|
47
|
+
end
|
15
48
|
end
|
16
49
|
|
17
|
-
|
18
|
-
|
50
|
+
describe 'Resource Factories' do
|
51
|
+
it 'gets all projects' do
|
52
|
+
expect(JIRA::Resource::Project).to receive(:all).with(subject).and_return([])
|
53
|
+
expect(subject.Project.all).to eq([])
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'finds a single project' do
|
57
|
+
find_result = double
|
58
|
+
expect(JIRA::Resource::Project).to receive(:find).with(subject, '123').and_return(find_result)
|
59
|
+
expect(subject.Project.find('123')).to eq(find_result)
|
60
|
+
end
|
19
61
|
end
|
62
|
+
end
|
20
63
|
|
21
|
-
|
64
|
+
RSpec.shared_examples 'HttpClient tests' do
|
65
|
+
it 'makes a valid request' do
|
66
|
+
[:delete, :get, :head].each do |method|
|
67
|
+
expect(subject.request_client).to receive(:make_request).with(method, '/path', nil, headers).and_return(successful_response)
|
68
|
+
subject.send(method, '/path', headers)
|
69
|
+
end
|
70
|
+
[:post, :put].each do |method|
|
71
|
+
expect(subject.request_client).to receive(:make_request).with(method, '/path', '', merged_headers).and_return(successful_response)
|
72
|
+
subject.send(method, '/path', '', headers)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
22
76
|
|
23
|
-
|
24
|
-
|
77
|
+
describe JIRA::Client do
|
78
|
+
let(:request) { subject.request_client.class }
|
79
|
+
let(:successful_response) do
|
80
|
+
response = double('response')
|
25
81
|
allow(response).to receive(:kind_of?).with(Net::HTTPSuccess).and_return(true)
|
26
82
|
response
|
27
83
|
end
|
28
|
-
|
29
|
-
let(:headers) { {'Accept' => 'application/json'} }
|
30
84
|
let(:content_type_header) { {'Content-Type' => 'application/json'} }
|
85
|
+
let(:headers) { {'Accept' => 'application/json'} }
|
31
86
|
let(:merged_headers) { headers.merge(content_type_header) }
|
32
87
|
|
33
|
-
|
34
|
-
|
88
|
+
context 'behaviour that applies to all client classes irrespective of authentication method' do
|
89
|
+
it 'allows the overriding of some options' do
|
90
|
+
client = JIRA::Client.new({:consumer_key => 'foo', :consumer_secret => 'bar', :site => 'http://foo.com/'})
|
91
|
+
expect(client.options[:site]).to eq('http://foo.com/')
|
92
|
+
expect(JIRA::Client::DEFAULT_OPTIONS[:site]).not_to eq('http://foo.com/')
|
93
|
+
end
|
35
94
|
end
|
36
95
|
|
37
|
-
|
38
|
-
|
39
|
-
expect(client.options[:site]).to eq('http://foo.com/')
|
40
|
-
expect(JIRA::Client::DEFAULT_OPTIONS[:site]).not_to eq('http://foo.com/')
|
41
|
-
end
|
96
|
+
context 'with basic http authentication' do
|
97
|
+
subject { JIRA::Client.new(username: 'foo', password: 'bar', auth_type: :basic) }
|
42
98
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
99
|
+
before(:each) do
|
100
|
+
stub_request(:get, 'https://foo:bar@localhost:2990/jira/rest/api/2/project')
|
101
|
+
.to_return(status: 200, body: '[]', headers: {} )
|
102
|
+
|
103
|
+
stub_request(:get, 'https://foo:badpassword@localhost:2990/jira/rest/api/2/project').
|
104
|
+
to_return(status: 401, headers: {} )
|
48
105
|
end
|
49
|
-
end
|
50
106
|
|
51
|
-
|
52
|
-
|
53
|
-
it "freezes the options" do
|
54
|
-
clients.each { |client| expect(client.options).to be_frozen }
|
55
|
-
end
|
107
|
+
include_examples 'Client Common Tests'
|
108
|
+
include_examples 'HttpClient tests'
|
56
109
|
|
57
|
-
|
58
|
-
clients.each { |client| expect(client.send(:merge_default_headers, {})).to eq({'Accept' => 'application/json'}) }
|
59
|
-
end
|
110
|
+
specify { expect(subject.request_client).to be_a JIRA::HttpClient }
|
60
111
|
|
61
|
-
|
62
|
-
|
63
|
-
expect(
|
64
|
-
expect(basic_client.request_client.class).to eq(JIRA::HttpClient)
|
65
|
-
expect(cookie_client.request_client.class).to eq(JIRA::HttpClient)
|
112
|
+
it 'sets the username and password' do
|
113
|
+
expect(subject.options[:username]).to eq('foo')
|
114
|
+
expect(subject.options[:password]).to eq('bar')
|
66
115
|
end
|
67
116
|
|
68
|
-
|
69
|
-
|
70
|
-
expect(
|
71
|
-
expect
|
117
|
+
it 'fails with wrong user name and password' do
|
118
|
+
bad_login = JIRA::Client.new(username: 'foo', password: 'badpassword', auth_type: :basic)
|
119
|
+
expect(bad_login.authenticated?).to be_falsey
|
120
|
+
expect{bad_login.Project.all}.to raise_error JIRA::HTTPError
|
72
121
|
end
|
73
122
|
|
74
|
-
|
123
|
+
it 'only returns a true for #authenticated? once we have requested some data' do
|
124
|
+
expect(subject.authenticated?).to be_falsey
|
125
|
+
expect(subject.Project.all).to be_empty
|
126
|
+
expect(subject.authenticated?).to be_truthy
|
127
|
+
end
|
75
128
|
|
76
|
-
|
77
|
-
token = double()
|
78
|
-
expect(OAuth::AccessToken).to receive(:new).with(oauth_client.consumer, 'foo', 'bar').and_return(token)
|
79
|
-
access_token = oauth_client.set_access_token('foo', 'bar')
|
129
|
+
end
|
80
130
|
|
81
|
-
|
82
|
-
|
83
|
-
|
131
|
+
context 'with cookie authentication' do
|
132
|
+
subject { JIRA::Client.new(username: 'foo', password: 'bar', auth_type: :cookie) }
|
133
|
+
|
134
|
+
let(:session_cookie) { '6E3487971234567896704A9EB4AE501F' }
|
135
|
+
let(:session_body) do
|
136
|
+
{
|
137
|
+
'session': {'name' => "JSESSIONID", 'value' => session_cookie },
|
138
|
+
'loginInfo': {'failedLoginCount' => 1, 'loginCount' => 2,
|
139
|
+
'lastFailedLoginTime' => (DateTime.now - 2).iso8601,
|
140
|
+
'previousLoginTime' => (DateTime.now - 5).iso8601 }
|
141
|
+
}
|
142
|
+
end
|
84
143
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
expect(request_token).to receive(:get_access_token).with(:oauth_verifier => 'abc123').and_return(mock_access_token)
|
90
|
-
oauth_client.init_access_token(:oauth_verifier => 'abc123')
|
91
|
-
expect(oauth_client.access_token).to eq(mock_access_token)
|
92
|
-
end
|
144
|
+
before(:each) do
|
145
|
+
# General case of API call with no authentication, or wrong authentication
|
146
|
+
stub_request(:post, 'https://localhost:2990/jira/rest/auth/1/session').
|
147
|
+
to_return(status: 401, headers: {} )
|
93
148
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
149
|
+
# Now special case of API with correct authentication. This gets checked first by RSpec.
|
150
|
+
stub_request(:post, 'https://localhost:2990/jira/rest/auth/1/session')
|
151
|
+
.with(body: '{"username":"foo","password":"bar"}')
|
152
|
+
.to_return(status: 200, body: session_body.to_json,
|
153
|
+
headers: { 'Set-Cookie': "JSESSIONID=#{session_cookie}; Path=/; HttpOnly"})
|
154
|
+
|
155
|
+
stub_request(:get, 'https://localhost:2990/jira/rest/api/2/project')
|
156
|
+
.with(headers: { cookie: "JSESSIONID=#{session_cookie}" } )
|
157
|
+
.to_return(status: 200, body: '[]', headers: {} )
|
100
158
|
end
|
101
159
|
|
102
|
-
|
103
|
-
|
104
|
-
expect(basic_client.options[:username]).to eq('foo')
|
105
|
-
expect(basic_client.options[:password]).to eq('bar')
|
160
|
+
include_examples 'Client Common Tests'
|
161
|
+
include_examples 'HttpClient tests'
|
106
162
|
|
107
|
-
|
108
|
-
|
109
|
-
|
163
|
+
specify { expect(subject.request_client).to be_a JIRA::HttpClient }
|
164
|
+
|
165
|
+
it 'authenticates with a correct username and password' do
|
166
|
+
expect(subject).to be_authenticated
|
167
|
+
expect(subject.Project.all).to be_empty
|
110
168
|
end
|
111
169
|
|
112
|
-
|
170
|
+
it 'does not authenticate with an incorrect username and password' do
|
171
|
+
bad_client = JIRA::Client.new(username: 'foo', password: 'bad_password', auth_type: :cookie)
|
172
|
+
expect(bad_client).not_to be_authenticated
|
173
|
+
end
|
113
174
|
|
114
|
-
|
115
|
-
|
116
|
-
|
175
|
+
it 'destroys the username and password once authenticated' do
|
176
|
+
expect(subject.options[:username]).to be_nil
|
177
|
+
expect(subject.options[:password]).to be_nil
|
117
178
|
end
|
179
|
+
end
|
118
180
|
|
119
|
-
|
120
|
-
|
121
|
-
expect(oauth_client).to receive(:request).exactly(5).times.and_return(response)
|
122
|
-
expect(basic_client).to receive(:request).exactly(5).times.and_return(response)
|
123
|
-
expect(cookie_client).to receive(:request).exactly(5).times.and_return(response)
|
181
|
+
context 'oath2 authentication' do
|
182
|
+
subject { JIRA::Client.new(consumer_key: 'foo', consumer_secret: 'bar') }
|
124
183
|
|
125
|
-
|
126
|
-
expect(oauth_client).to receive(:merge_default_headers).exactly(3).times.with({})
|
127
|
-
expect(basic_client).to receive(:merge_default_headers).exactly(3).times.with({})
|
128
|
-
expect(cookie_client).to receive(:merge_default_headers).exactly(3).times.with({})
|
184
|
+
include_examples 'Client Common Tests'
|
129
185
|
|
130
|
-
|
131
|
-
expect(oauth_client).to receive(:merge_default_headers).exactly(2).times.with(content_type_header)
|
132
|
-
expect(basic_client).to receive(:merge_default_headers).exactly(2).times.with(content_type_header)
|
133
|
-
expect(cookie_client).to receive(:merge_default_headers).exactly(2).times.with(content_type_header)
|
186
|
+
specify { expect(subject.request_client).to be_a JIRA::OauthClient }
|
134
187
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
cookie_client.send(method, '/path', {})
|
139
|
-
end
|
188
|
+
it 'allows setting an access token' do
|
189
|
+
token = double
|
190
|
+
expect(OAuth::AccessToken).to receive(:new).with(subject.consumer, 'foo', 'bar').and_return(token)
|
140
191
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
192
|
+
expect(subject.authenticated?).to be_falsey
|
193
|
+
access_token = subject.set_access_token('foo', 'bar')
|
194
|
+
expect(access_token).to eq(token)
|
195
|
+
expect(subject.access_token).to eq(token)
|
196
|
+
expect(subject.authenticated?).to be_truthy
|
146
197
|
end
|
147
198
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
cookie_client.send(method, '/path', {})
|
156
|
-
end
|
157
|
-
|
158
|
-
[:post, :put].each do |method|
|
159
|
-
expect(oauth_client).to receive(:request).with(method, '/path', '', merged_headers)
|
160
|
-
expect(basic_client).to receive(:request).with(method, '/path', '', merged_headers)
|
161
|
-
expect(cookie_client).to receive(:request).with(method, '/path', '', merged_headers)
|
162
|
-
oauth_client.send(method, '/path', '', {})
|
163
|
-
basic_client.send(method, '/path', '', {})
|
164
|
-
cookie_client.send(method, '/path', '', {})
|
165
|
-
end
|
199
|
+
it 'allows initializing the access token' do
|
200
|
+
request_token = OAuth::RequestToken.new(subject.consumer)
|
201
|
+
allow(subject.consumer).to receive(:get_request_token).and_return(request_token)
|
202
|
+
mock_access_token = double
|
203
|
+
expect(request_token).to receive(:get_access_token).with(:oauth_verifier => 'abc123').and_return(mock_access_token)
|
204
|
+
subject.init_access_token(:oauth_verifier => 'abc123')
|
205
|
+
expect(subject.access_token).to eq(mock_access_token)
|
166
206
|
end
|
167
207
|
|
168
|
-
|
169
|
-
|
170
|
-
[
|
171
|
-
expect(oauth_client.request_client).to receive(:make_request).with(method, '/path', nil, headers).and_return(response)
|
172
|
-
oauth_client.send(method, '/path', {})
|
173
|
-
end
|
174
|
-
[:post, :put].each do |method|
|
175
|
-
expect(oauth_client.request_client).to receive(:make_request).with(method, '/path', '', merged_headers).and_return(response)
|
176
|
-
oauth_client.send(method, '/path', '', {})
|
177
|
-
end
|
208
|
+
specify 'that has specific default options' do
|
209
|
+
[:signature_method, :private_key_file].each do |key|
|
210
|
+
expect(subject.options[key]).to eq(JIRA::Client::DEFAULT_OPTIONS[key])
|
178
211
|
end
|
179
212
|
end
|
180
213
|
|
181
|
-
describe
|
182
|
-
|
214
|
+
describe 'that call a oauth client' do
|
215
|
+
specify 'which makes a request' do
|
183
216
|
[:delete, :get, :head].each do |method|
|
184
|
-
expect(
|
185
|
-
|
186
|
-
|
187
|
-
expect(cookie_client.request_client).to receive(:make_request).with(method, '/path', nil, headers).and_return(response)
|
188
|
-
cookie_client.send(method, '/path', headers)
|
217
|
+
expect(subject.request_client).to receive(:make_request).with(method, '/path', nil, headers).and_return(successful_response)
|
218
|
+
subject.send(method, '/path', {})
|
189
219
|
end
|
190
220
|
[:post, :put].each do |method|
|
191
|
-
expect(
|
192
|
-
|
193
|
-
|
194
|
-
expect(cookie_client.request_client).to receive(:make_request).with(method, '/path', '', merged_headers).and_return(response)
|
195
|
-
cookie_client.send(method, '/path', '', headers)
|
221
|
+
expect(subject.request_client).to receive(:make_request).with(method, '/path', '', merged_headers).and_return(successful_response)
|
222
|
+
subject.send(method, '/path', '', {})
|
196
223
|
end
|
197
224
|
end
|
198
225
|
end
|
199
226
|
end
|
200
|
-
|
201
|
-
describe "Resource Factories" do
|
202
|
-
it "gets all projects" do
|
203
|
-
expect(JIRA::Resource::Project).to receive(:all).with(oauth_client).and_return([])
|
204
|
-
expect(JIRA::Resource::Project).to receive(:all).with(basic_client).and_return([])
|
205
|
-
expect(JIRA::Resource::Project).to receive(:all).with(cookie_client).and_return([])
|
206
|
-
|
207
|
-
expect(oauth_client.Project.all).to eq([])
|
208
|
-
expect(basic_client.Project.all).to eq([])
|
209
|
-
expect(cookie_client.Project.all).to eq([])
|
210
|
-
end
|
211
|
-
|
212
|
-
it "finds a single project" do
|
213
|
-
find_result = double()
|
214
|
-
expect(JIRA::Resource::Project).to receive(:find).with(oauth_client, '123').and_return(find_result)
|
215
|
-
expect(JIRA::Resource::Project).to receive(:find).with(basic_client, '123').and_return(find_result)
|
216
|
-
expect(JIRA::Resource::Project).to receive(:find).with(cookie_client, '123').and_return(find_result)
|
217
|
-
|
218
|
-
expect(oauth_client.Project.find('123')).to eq(find_result)
|
219
|
-
expect(basic_client.Project.find('123')).to eq(find_result)
|
220
|
-
expect(cookie_client.Project.find('123')).to eq(find_result)
|
221
|
-
end
|
222
|
-
end
|
223
227
|
end
|
228
|
+
|