jira-ruby 3.0.0.beta1 → 3.0.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/.github/workflows/CI.yml +1 -0
- data/.github/workflows/codeql.yml +0 -4
- data/.gitignore +3 -1
- data/.rubocop.yml +5 -70
- data/.yardopts +4 -0
- data/lib/jira/base.rb +5 -13
- data/lib/jira/client.rb +59 -4
- data/lib/jira/has_many_proxy.rb +30 -28
- data/lib/jira/http_client.rb +64 -1
- data/lib/jira/oauth_client.rb +62 -0
- data/lib/jira/request_client.rb +26 -1
- data/lib/jira/resource/attachment.rb +88 -3
- data/lib/jira/resource/field.rb +4 -8
- data/lib/jira/resource/issue.rb +80 -11
- data/lib/jira/resource/issue_picker_suggestions.rb +1 -1
- data/lib/jira/resource/issuelink.rb +4 -3
- data/lib/jira/resource/project.rb +1 -1
- data/lib/jira/resource/sprint.rb +2 -2
- data/lib/jira/resource/watcher.rb +1 -1
- data/lib/jira/resource/webhook.rb +5 -1
- data/lib/jira/version.rb +1 -1
- data/lib/tasks/generate.rake +1 -1
- data/spec/integration/issue_spec.rb +2 -2
- data/spec/integration/project_spec.rb +2 -2
- data/spec/integration/rapidview_spec.rb +3 -3
- data/spec/integration/user_spec.rb +12 -3
- data/spec/integration/watcher_spec.rb +6 -2
- data/spec/integration/{webhook.rb → webhook_spec.rb} +8 -1
- data/spec/jira/base_factory_spec.rb +11 -2
- data/spec/jira/base_spec.rb +80 -57
- data/spec/jira/client_spec.rb +29 -27
- data/spec/jira/http_client_spec.rb +2 -2
- data/spec/jira/oauth_client_spec.rb +8 -4
- data/spec/jira/resource/agile_spec.rb +4 -4
- data/spec/jira/resource/attachment_spec.rb +36 -13
- data/spec/jira/resource/board_spec.rb +5 -5
- data/spec/jira/resource/field_spec.rb +23 -24
- data/spec/jira/resource/filter_spec.rb +3 -2
- data/spec/jira/resource/issue_spec.rb +103 -81
- data/spec/jira/resource/project_spec.rb +8 -8
- data/spec/jira/resource/sprint_spec.rb +23 -11
- data/spec/jira/resource/status_spec.rb +1 -1
- data/spec/jira/resource/user_factory_spec.rb +2 -2
- data/spec/jira/resource/worklog_spec.rb +1 -1
- data/spec/mock_responses/board/1_issues.json +2 -1
- data/spec/mock_responses/issue.json +1 -0
- data/spec/mock_responses/rapidview/SAMPLEPROJECT.issues.full.json +2 -1
- data/spec/mock_responses/rapidview/SAMPLEPROJECT.issues.json +2 -1
- data/spec/support/clients_helper.rb +2 -2
- data/spec/support/mock_client.rb +9 -0
- data/spec/support/mock_response.rb +8 -0
- data/spec/support/shared_examples/integration.rb +1 -1
- metadata +9 -10
@@ -40,14 +40,23 @@ describe JIRA::Resource::User do
|
|
40
40
|
end
|
41
41
|
|
42
42
|
before do
|
43
|
+
user_factory = double('UserFactory')
|
44
|
+
|
43
45
|
allow(client).to receive(:get)
|
44
|
-
.with('/rest/api/2/users/search?username=_&maxResults=1000')
|
45
|
-
|
46
|
+
.with('/rest/api/2/users/search?username=_&maxResults=1000')
|
47
|
+
.and_return(double(body: '["User1"]'))
|
48
|
+
allow(client).to receive(:User).and_return(user_factory)
|
49
|
+
allow(user_factory).to receive(:build).with('users').and_return([])
|
46
50
|
end
|
47
51
|
|
48
52
|
it 'gets users with maxResults of 1000' do
|
53
|
+
user_factory = double('UserFactory')
|
54
|
+
|
49
55
|
expect(client).to receive(:get).with('/rest/api/2/users/search?username=_&maxResults=1000')
|
50
|
-
|
56
|
+
.and_return(double(body: '["User1"]'))
|
57
|
+
expect(client).to receive(:User).and_return(user_factory)
|
58
|
+
expect(user_factory).to receive(:build).with('User1')
|
59
|
+
|
51
60
|
described_class.all(client)
|
52
61
|
end
|
53
62
|
end
|
@@ -46,15 +46,19 @@ describe JIRA::Resource::Watcher do
|
|
46
46
|
|
47
47
|
it 'returnses all the watchers' do
|
48
48
|
issue = client.Issue.find('10002')
|
49
|
-
watchers = client.Watcher.all(
|
49
|
+
watchers = client.Watcher.all({ issue: })
|
50
50
|
expect(watchers.length).to eq(1)
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'adds a watcher' do
|
54
54
|
issue = client.Issue.find('10002')
|
55
|
-
watcher = described_class.new(client, issue:)
|
55
|
+
watcher = described_class.new(client, issue: issue)
|
56
56
|
user_id = 'tester'
|
57
|
+
|
57
58
|
watcher.save!(user_id)
|
59
|
+
|
60
|
+
expect(WebMock).to have_requested(:post, "#{site_url}/jira/rest/api/2/issue/10002/watchers")
|
61
|
+
.with(body: '"tester"')
|
58
62
|
end
|
59
63
|
end
|
60
64
|
end
|
@@ -9,7 +9,7 @@ describe JIRA::Resource::Webhook do
|
|
9
9
|
|
10
10
|
let(:expected_attributes) do
|
11
11
|
{ 'name' => 'from API', 'url' => 'http://localhost:3000/webhooks/1', 'excludeBody' => false,
|
12
|
-
'filters' => { 'issue-related-events-section' => '' }, 'events' => [], 'enabled' => true, 'self' => 'http://localhost:2990/jira/rest/webhooks/1.0/webhook/2', 'lastUpdatedUser' => 'admin', 'lastUpdatedDisplayName' => 'admin', 'lastUpdated' => 1_453_306_520_188 }
|
12
|
+
'filters' => { 'issue-related-events-section' => '' }, 'events' => [], 'enabled' => true, 'self' => 'http://localhost:2990/jira/rest/webhooks/1.0/webhook/2', 'lastUpdatedUser' => 'admin', 'lastUpdatedDisplayName' => 'admin', 'lastUpdated' => 1_453_306_520_188 }
|
13
13
|
end
|
14
14
|
|
15
15
|
let(:expected_collection_length) { 1 }
|
@@ -21,6 +21,13 @@ describe JIRA::Resource::Webhook do
|
|
21
21
|
it 'returns a collection of components' do
|
22
22
|
stub_request(:get, site_url + described_class.singular_path(client, key))
|
23
23
|
.to_return(status: 200, body: get_mock_response('webhook/webhook.json'))
|
24
|
+
|
25
|
+
webhook = client.Webhook.find(key)
|
26
|
+
|
27
|
+
expect(webhook).to be_a described_class
|
28
|
+
expect(webhook.name).to eq 'from API'
|
29
|
+
expect(webhook.url).to eq '/jira/rest/webhooks/1.0/webhook/2'
|
30
|
+
expect(webhook.enabled).to be true
|
24
31
|
end
|
25
32
|
end
|
26
33
|
end
|
@@ -1,8 +1,17 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe JIRA::BaseFactory do
|
4
|
-
|
5
|
-
|
4
|
+
module JIRA
|
5
|
+
module Resource
|
6
|
+
class FooFactory < JIRA::BaseFactory; end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module JIRA
|
11
|
+
module Resource
|
12
|
+
class Foo; end
|
13
|
+
end
|
14
|
+
end
|
6
15
|
|
7
16
|
subject { JIRA::Resource::FooFactory.new(client) }
|
8
17
|
|
data/spec/jira/base_spec.rb
CHANGED
@@ -4,32 +4,44 @@ describe JIRA::Base do
|
|
4
4
|
class JIRADelegation < SimpleDelegator # :nodoc:
|
5
5
|
end
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
7
|
+
module JIRA
|
8
|
+
module Resource
|
9
|
+
class Deadbeef < JIRA::Base # :nodoc:
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module JIRA
|
15
|
+
module Resource
|
16
|
+
class HasOneExample < JIRA::Base # :nodoc:
|
17
|
+
has_one :deadbeef
|
18
|
+
has_one :muffin, class: JIRA::Resource::Deadbeef
|
19
|
+
has_one :brunchmuffin, class: JIRA::Resource::Deadbeef,
|
20
|
+
nested_under: 'nested'
|
21
|
+
has_one :breakfastscone,
|
22
|
+
class: JIRA::Resource::Deadbeef,
|
23
|
+
nested_under: %w[nested breakfastscone]
|
24
|
+
has_one :irregularly_named_thing,
|
25
|
+
class: JIRA::Resource::Deadbeef,
|
26
|
+
attribute_key: 'irregularlyNamedThing'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module JIRA
|
32
|
+
module Resource
|
33
|
+
class HasManyExample < JIRA::Base # :nodoc:
|
34
|
+
has_many :deadbeefs
|
35
|
+
has_many :brunchmuffins, class: JIRA::Resource::Deadbeef,
|
36
|
+
nested_under: 'nested'
|
37
|
+
has_many :breakfastscones,
|
38
|
+
class: JIRA::Resource::Deadbeef,
|
39
|
+
nested_under: %w[nested breakfastscone]
|
40
|
+
has_many :irregularly_named_things,
|
41
|
+
class: JIRA::Resource::Deadbeef,
|
42
|
+
attribute_key: 'irregularlyNamedThings'
|
43
|
+
end
|
44
|
+
end
|
33
45
|
end
|
34
46
|
|
35
47
|
subject { JIRA::Resource::Deadbeef.new(client, attrs:) }
|
@@ -42,7 +54,7 @@ describe JIRA::Base do
|
|
42
54
|
describe '#respond_to?' do
|
43
55
|
describe 'when decorated using SimpleDelegator' do
|
44
56
|
it 'responds to client' do
|
45
|
-
expect(decorated.respond_to?(:client)).to
|
57
|
+
expect(decorated.respond_to?(:client)).to be(true)
|
46
58
|
end
|
47
59
|
|
48
60
|
it 'does not raise an error' do
|
@@ -69,23 +81,23 @@ describe JIRA::Base do
|
|
69
81
|
expect(first.class).to eq(JIRA::Resource::Deadbeef)
|
70
82
|
expect(first.attrs['self']).to eq('http://deadbeef/')
|
71
83
|
expect(first.attrs['id']).to eq('98765')
|
72
|
-
expect(first
|
84
|
+
expect(first).not_to be_expanded
|
73
85
|
end
|
74
86
|
|
75
87
|
it 'finds a deadbeef by id' do
|
76
|
-
response = instance_double(
|
88
|
+
response = instance_double(Response, body: '{"self":"http://deadbeef/","id":"98765"}')
|
77
89
|
expect(client).to receive(:get).with('/jira/rest/api/2/deadbeef/98765').and_return(response)
|
78
90
|
expect(JIRA::Resource::Deadbeef).to receive(:collection_path).and_return('/jira/rest/api/2/deadbeef')
|
79
91
|
deadbeef = JIRA::Resource::Deadbeef.find(client, '98765')
|
80
92
|
expect(deadbeef.client).to eq(client)
|
81
93
|
expect(deadbeef.attrs['self']).to eq('http://deadbeef/')
|
82
94
|
expect(deadbeef.attrs['id']).to eq('98765')
|
83
|
-
expect(deadbeef
|
95
|
+
expect(deadbeef).to be_expanded
|
84
96
|
end
|
85
97
|
|
86
98
|
it 'finds a deadbeef containing changelog by id' do
|
87
99
|
response = instance_double(
|
88
|
-
|
100
|
+
Response,
|
89
101
|
body: '{"self":"http://deadbeef/","id":"98765","changelog":{"histories":[]}}'
|
90
102
|
)
|
91
103
|
expect(client).to receive(:get).with('/jira/rest/api/2/deadbeef/98765?expand=changelog').and_return(response)
|
@@ -96,13 +108,13 @@ describe JIRA::Base do
|
|
96
108
|
expect(deadbeef.client).to eq(client)
|
97
109
|
expect(deadbeef.attrs['self']).to eq('http://deadbeef/')
|
98
110
|
expect(deadbeef.attrs['id']).to eq('98765')
|
99
|
-
expect(deadbeef
|
111
|
+
expect(deadbeef).to be_expanded
|
100
112
|
expect(deadbeef.attrs['changelog']['histories']).to eq([])
|
101
113
|
end
|
102
114
|
|
103
115
|
it 'builds a deadbeef' do
|
104
116
|
deadbeef = JIRA::Resource::Deadbeef.build(client, 'id' => '98765')
|
105
|
-
expect(deadbeef
|
117
|
+
expect(deadbeef).not_to be_expanded
|
106
118
|
|
107
119
|
expect(deadbeef.client).to eq(client)
|
108
120
|
expect(deadbeef.attrs['id']).to eq('98765')
|
@@ -172,19 +184,19 @@ describe JIRA::Base do
|
|
172
184
|
|
173
185
|
describe 'not cached' do
|
174
186
|
before do
|
175
|
-
response = instance_double(
|
187
|
+
response = instance_double(Response, body: '{"self":"http://deadbeef/","id":"98765"}')
|
176
188
|
expect(client).to receive(:get).with('/jira/rest/api/2/deadbeef/98765').and_return(response)
|
177
189
|
expect(JIRA::Resource::Deadbeef).to receive(:collection_path).and_return('/jira/rest/api/2/deadbeef')
|
178
190
|
end
|
179
191
|
|
180
192
|
it 'sets expanded to true after fetch' do
|
181
|
-
expect(subject
|
193
|
+
expect(subject).not_to be_expanded
|
182
194
|
subject.fetch
|
183
|
-
expect(subject
|
195
|
+
expect(subject).to be_expanded
|
184
196
|
end
|
185
197
|
|
186
198
|
it 'performs a fetch' do
|
187
|
-
expect(subject
|
199
|
+
expect(subject).not_to be_expanded
|
188
200
|
subject.fetch
|
189
201
|
expect(subject.self).to eq('http://deadbeef/')
|
190
202
|
expect(subject.id).to eq('98765')
|
@@ -193,6 +205,10 @@ describe JIRA::Base do
|
|
193
205
|
it 'performs a fetch if already fetched and force flag is true' do
|
194
206
|
subject.expanded = true
|
195
207
|
subject.fetch(true)
|
208
|
+
|
209
|
+
expect(subject.self).to eq('http://deadbeef/')
|
210
|
+
expect(subject.id).to eq('98765')
|
211
|
+
expect(subject).to be_expanded
|
196
212
|
end
|
197
213
|
end
|
198
214
|
|
@@ -207,7 +223,7 @@ describe JIRA::Base do
|
|
207
223
|
context "with expand parameter 'changelog'" do
|
208
224
|
it "fetchs changelogs '" do
|
209
225
|
response = instance_double(
|
210
|
-
|
226
|
+
Response,
|
211
227
|
body: '{"self":"http://deadbeef/","id":"98765","changelog":{"histories":[]}}'
|
212
228
|
)
|
213
229
|
expect(client).to receive(:get).with('/jira/rest/api/2/deadbeef/98765?expand=changelog').and_return(response)
|
@@ -233,7 +249,7 @@ describe JIRA::Base do
|
|
233
249
|
end
|
234
250
|
|
235
251
|
it 'POSTs a new record' do
|
236
|
-
response = instance_double(
|
252
|
+
response = instance_double(Response, body: '{"id":"123"}')
|
237
253
|
allow(subject).to receive(:new_record?).and_return(true)
|
238
254
|
expect(client).to receive(:post).with('/foo/bar', '{"foo":"bar"}').and_return(response)
|
239
255
|
expect(subject.save('foo' => 'bar')).to be_truthy
|
@@ -242,7 +258,7 @@ describe JIRA::Base do
|
|
242
258
|
end
|
243
259
|
|
244
260
|
it 'PUTs an existing record' do
|
245
|
-
response = instance_double(
|
261
|
+
response = instance_double(Response, body: nil)
|
246
262
|
allow(subject).to receive(:new_record?).and_return(false)
|
247
263
|
expect(client).to receive(:put).with('/foo/bar', '{"foo":"bar"}').and_return(response)
|
248
264
|
expect(subject.save('foo' => 'bar')).to be_truthy
|
@@ -250,7 +266,7 @@ describe JIRA::Base do
|
|
250
266
|
end
|
251
267
|
|
252
268
|
it 'merges attrs on save' do
|
253
|
-
response = instance_double(
|
269
|
+
response = instance_double(Response, body: nil)
|
254
270
|
expect(client).to receive(:post).with('/foo/bar', '{"foo":{"fum":"dum"}}').and_return(response)
|
255
271
|
subject.attrs = { 'foo' => { 'bar' => 'baz' } }
|
256
272
|
subject.save('foo' => { 'fum' => 'dum' })
|
@@ -259,7 +275,7 @@ describe JIRA::Base do
|
|
259
275
|
|
260
276
|
it 'returns false when an invalid field is set' do
|
261
277
|
# The JIRA REST API apparently ignores fields that you aren't allowed to set manually
|
262
|
-
response = instance_double(
|
278
|
+
response = instance_double(Response, body: '{"errorMessages":["blah"]}', status: 400)
|
263
279
|
allow(subject).to receive(:new_record?).and_return(false)
|
264
280
|
expect(client).to receive(:put).with('/foo/bar',
|
265
281
|
'{"invalid_field":"foobar"}').and_raise(JIRA::HTTPError.new(response))
|
@@ -268,7 +284,7 @@ describe JIRA::Base do
|
|
268
284
|
|
269
285
|
it 'returns false with exception details when non json response body (unauthorized)' do
|
270
286
|
# Unauthorized requests return a non-json body. This makes sure we can handle non-json bodies on HTTPError
|
271
|
-
response = double(
|
287
|
+
response = double(Response, body: 'totally invalid json', code: 401, message: 'Unauthorized')
|
272
288
|
expect(client).to receive(:post).with('/foo/bar', '{"foo":"bar"}').and_raise(JIRA::HTTPError.new(response))
|
273
289
|
expect(subject.save('foo' => 'bar')).to be_falsey
|
274
290
|
expect(subject.attrs['exception']['code']).to eq(401)
|
@@ -286,7 +302,7 @@ describe JIRA::Base do
|
|
286
302
|
end
|
287
303
|
|
288
304
|
it 'POSTs a new record' do
|
289
|
-
response = instance_double(
|
305
|
+
response = instance_double(Response, body: '{"id":"123"}')
|
290
306
|
allow(subject).to receive(:new_record?).and_return(true)
|
291
307
|
expect(client).to receive(:post).with('/foo/bar', '{"foo":"bar"}').and_return(response)
|
292
308
|
expect(subject.save!('foo' => 'bar')).to be_truthy
|
@@ -295,7 +311,7 @@ describe JIRA::Base do
|
|
295
311
|
end
|
296
312
|
|
297
313
|
it 'PUTs an existing record' do
|
298
|
-
response = instance_double(
|
314
|
+
response = instance_double(Response, body: nil)
|
299
315
|
allow(subject).to receive(:new_record?).and_return(false)
|
300
316
|
expect(client).to receive(:put).with('/foo/bar', '{"foo":"bar"}').and_return(response)
|
301
317
|
expect(subject.save!('foo' => 'bar')).to be_truthy
|
@@ -303,7 +319,7 @@ describe JIRA::Base do
|
|
303
319
|
end
|
304
320
|
|
305
321
|
it 'throws an exception when an invalid field is set' do
|
306
|
-
response = instance_double(
|
322
|
+
response = instance_double(Response, body: '{"errorMessages":["blah"]}', status: 400)
|
307
323
|
allow(subject).to receive(:new_record?).and_return(false)
|
308
324
|
expect(client).to receive(:put).with('/foo/bar',
|
309
325
|
'{"invalid_field":"foobar"}').and_raise(JIRA::HTTPError.new(response))
|
@@ -332,36 +348,39 @@ describe JIRA::Base do
|
|
332
348
|
end
|
333
349
|
|
334
350
|
it 'flags itself as deleted' do
|
335
|
-
expect(subject
|
351
|
+
expect(subject).not_to be_deleted
|
336
352
|
subject.delete
|
337
|
-
expect(subject
|
353
|
+
expect(subject).to be_deleted
|
338
354
|
end
|
339
355
|
|
340
356
|
it 'sends a DELETE request' do
|
341
357
|
subject.delete
|
358
|
+
|
359
|
+
expect(subject).to have_received(:url)
|
360
|
+
expect(subject).to be_deleted
|
342
361
|
end
|
343
362
|
end
|
344
363
|
|
345
364
|
describe 'new_record?' do
|
346
365
|
it 'returns true for new_record? when new object' do
|
347
366
|
subject.attrs['id'] = nil
|
348
|
-
expect(subject
|
367
|
+
expect(subject).to be_new_record
|
349
368
|
end
|
350
369
|
|
351
370
|
it 'returns false for new_record? when id is set' do
|
352
371
|
subject.attrs['id'] = '123'
|
353
|
-
expect(subject
|
372
|
+
expect(subject).not_to be_new_record
|
354
373
|
end
|
355
374
|
end
|
356
375
|
|
357
376
|
describe 'has_errors?' do
|
358
377
|
it 'returns true when the response contains errors' do
|
359
378
|
attrs['errors'] = { 'invalid' => 'Field invalid' }
|
360
|
-
expect(subject
|
379
|
+
expect(subject).to have_errors
|
361
380
|
end
|
362
381
|
|
363
382
|
it 'returns false when the response does not contain any errors' do
|
364
|
-
expect(subject
|
383
|
+
expect(subject).not_to have_errors
|
365
384
|
end
|
366
385
|
end
|
367
386
|
|
@@ -441,14 +460,14 @@ describe JIRA::Base do
|
|
441
460
|
subject { JIRA::Resource::Deadbeef.new(client, attrs: {}) }
|
442
461
|
|
443
462
|
it 'sets the attrs from a response' do
|
444
|
-
response = instance_double(
|
463
|
+
response = instance_double(Response, body: '{"foo":"bar"}')
|
445
464
|
|
446
465
|
expect(subject.set_attrs_from_response(response)).to eq('foo' => 'bar')
|
447
466
|
expect(subject.foo).to eq('bar')
|
448
467
|
end
|
449
468
|
|
450
469
|
it "doesn't clobber existing attrs not in response" do
|
451
|
-
response = instance_double(
|
470
|
+
response = instance_double(Response, body: '{"foo":"bar"}')
|
452
471
|
|
453
472
|
subject.attrs = { 'flum' => 'flar' }
|
454
473
|
expect(subject.set_attrs_from_response(response)).to eq('foo' => 'bar')
|
@@ -457,7 +476,7 @@ describe JIRA::Base do
|
|
457
476
|
end
|
458
477
|
|
459
478
|
it 'handles nil response body' do
|
460
|
-
response = instance_double(
|
479
|
+
response = instance_double(Response, body: nil)
|
461
480
|
|
462
481
|
subject.attrs = { 'flum' => 'flar' }
|
463
482
|
expect(subject.set_attrs_from_response(response)).to be_nil
|
@@ -580,8 +599,12 @@ describe JIRA::Base do
|
|
580
599
|
end
|
581
600
|
|
582
601
|
describe 'belongs_to' do
|
583
|
-
|
584
|
-
|
602
|
+
module JIRA
|
603
|
+
module Resource
|
604
|
+
class BelongsToExample < JIRA::Base
|
605
|
+
belongs_to :deadbeef
|
606
|
+
end
|
607
|
+
end
|
585
608
|
end
|
586
609
|
|
587
610
|
subject { JIRA::Resource::BelongsToExample.new(client, attrs: { 'id' => '123' }, deadbeef:) }
|
data/spec/jira/client_spec.rb
CHANGED
@@ -62,18 +62,20 @@ RSpec.shared_examples 'Client Common Tests' do
|
|
62
62
|
|
63
63
|
describe 'SSL client options' do
|
64
64
|
context 'without certificate and key' do
|
65
|
-
|
65
|
+
let(:basic_options) { { use_client_cert: true } }
|
66
66
|
|
67
|
-
|
68
|
-
|
69
|
-
it 'raises an ArgumentError' do
|
67
|
+
it 'raises an ArgumentError when cert is missing' do
|
70
68
|
expect do
|
71
|
-
|
69
|
+
JIRA::Client.new(basic_options)
|
72
70
|
end.to raise_exception(ArgumentError,
|
73
71
|
'Options: :cert_path or :ssl_client_cert must be set when :use_client_cert is true')
|
74
|
-
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'raises an ArgumentError when key is missing' do
|
75
|
+
options_with_cert = basic_options.merge(ssl_client_cert: '<cert></cert>')
|
76
|
+
|
75
77
|
expect do
|
76
|
-
|
78
|
+
JIRA::Client.new(options_with_cert)
|
77
79
|
end.to raise_exception(ArgumentError,
|
78
80
|
'Options: :key_path or :ssl_client_key must be set when :use_client_cert is true')
|
79
81
|
end
|
@@ -97,7 +99,7 @@ RSpec.shared_examples 'HttpClient tests' do
|
|
97
99
|
end
|
98
100
|
|
99
101
|
RSpec.shared_examples 'OAuth Common Tests' do
|
100
|
-
|
102
|
+
it_behaves_like 'Client Common Tests'
|
101
103
|
|
102
104
|
specify { expect(subject.request_client).to be_a JIRA::OauthClient }
|
103
105
|
|
@@ -105,11 +107,11 @@ RSpec.shared_examples 'OAuth Common Tests' do
|
|
105
107
|
token = double
|
106
108
|
expect(OAuth::AccessToken).to receive(:new).with(subject.consumer, '', '').and_return(token)
|
107
109
|
|
108
|
-
expect(subject
|
110
|
+
expect(subject).not_to be_authenticated
|
109
111
|
access_token = subject.set_access_token('', '')
|
110
112
|
expect(access_token).to eq(token)
|
111
113
|
expect(subject.access_token).to eq(token)
|
112
|
-
expect(subject
|
114
|
+
expect(subject).to be_authenticated
|
113
115
|
end
|
114
116
|
|
115
117
|
describe 'that call a oauth client' do
|
@@ -139,7 +141,7 @@ describe JIRA::Client do
|
|
139
141
|
let(:headers) { { 'Accept' => 'application/json' } }
|
140
142
|
let(:merged_headers) { headers.merge(content_type_header) }
|
141
143
|
|
142
|
-
context 'behaviour
|
144
|
+
context 'without regard to the authentication method, this behaviour applies to all client classes' do
|
143
145
|
it 'allows the overriding of some options' do
|
144
146
|
client = described_class.new(consumer_key: 'foo', consumer_secret: 'bar', site: 'http://foo.com/')
|
145
147
|
expect(client.options[:site]).to eq('http://foo.com/')
|
@@ -160,8 +162,8 @@ describe JIRA::Client do
|
|
160
162
|
.to_return(status: 401, headers: {})
|
161
163
|
end
|
162
164
|
|
163
|
-
|
164
|
-
|
165
|
+
it_behaves_like 'Client Common Tests'
|
166
|
+
it_behaves_like 'HttpClient tests'
|
165
167
|
|
166
168
|
specify { expect(subject.request_client).to be_a JIRA::HttpClient }
|
167
169
|
|
@@ -173,12 +175,12 @@ describe JIRA::Client do
|
|
173
175
|
it 'only returns a true for #authenticated? once we have requested some data' do
|
174
176
|
expect(subject.authenticated?).to be_nil
|
175
177
|
expect(subject.Project.all).to be_empty
|
176
|
-
expect(subject
|
178
|
+
expect(subject).to be_authenticated
|
177
179
|
end
|
178
180
|
|
179
181
|
it 'fails with wrong user name and password' do
|
180
182
|
bad_login = described_class.new(username: 'foo', password: 'badpassword', auth_type: :basic)
|
181
|
-
expect(bad_login
|
183
|
+
expect(bad_login).not_to be_authenticated
|
182
184
|
expect { bad_login.Project.all }.to raise_error JIRA::HTTPError
|
183
185
|
end
|
184
186
|
end
|
@@ -191,8 +193,8 @@ describe JIRA::Client do
|
|
191
193
|
{
|
192
194
|
session: { 'name' => 'JSESSIONID', 'value' => session_cookie },
|
193
195
|
loginInfo: { 'failedLoginCount' => 1, 'loginCount' => 2,
|
194
|
-
|
195
|
-
|
196
|
+
'lastFailedLoginTime' => (DateTime.now - 2).iso8601,
|
197
|
+
'previousLoginTime' => (DateTime.now - 5).iso8601 }
|
196
198
|
}
|
197
199
|
end
|
198
200
|
|
@@ -212,8 +214,8 @@ describe JIRA::Client do
|
|
212
214
|
.to_return(status: 200, body: '[]', headers: {})
|
213
215
|
end
|
214
216
|
|
215
|
-
|
216
|
-
|
217
|
+
it_behaves_like 'Client Common Tests'
|
218
|
+
it_behaves_like 'HttpClient tests'
|
217
219
|
|
218
220
|
specify { expect(subject.request_client).to be_a JIRA::HttpClient }
|
219
221
|
|
@@ -249,8 +251,8 @@ describe JIRA::Client do
|
|
249
251
|
.to_return(status: 200, body: '[]', headers: {})
|
250
252
|
end
|
251
253
|
|
252
|
-
|
253
|
-
|
254
|
+
it_behaves_like 'Client Common Tests'
|
255
|
+
it_behaves_like 'HttpClient tests'
|
254
256
|
|
255
257
|
specify { expect(subject.request_client).to be_a JIRA::JwtClient }
|
256
258
|
|
@@ -266,7 +268,7 @@ describe JIRA::Client do
|
|
266
268
|
end
|
267
269
|
|
268
270
|
it 'is not authenticated' do
|
269
|
-
expect(subject
|
271
|
+
expect(subject).not_to be_authenticated
|
270
272
|
end
|
271
273
|
|
272
274
|
it 'raises a JIRA::HTTPError when trying to fetch projects' do
|
@@ -275,22 +277,22 @@ describe JIRA::Client do
|
|
275
277
|
end
|
276
278
|
|
277
279
|
it 'only returns a true for #authenticated? once we have requested some data' do
|
278
|
-
expect(subject
|
280
|
+
expect(subject).not_to be_authenticated
|
279
281
|
expect(subject.Project.all).to be_empty
|
280
|
-
expect(subject
|
282
|
+
expect(subject).to be_authenticated
|
281
283
|
end
|
282
284
|
end
|
283
285
|
|
284
|
-
context 'oauth
|
286
|
+
context 'with oauth' do
|
285
287
|
subject { described_class.new(consumer_key: 'foo', consumer_secret: 'bar') }
|
286
288
|
|
287
|
-
|
289
|
+
it_behaves_like 'OAuth Common Tests'
|
288
290
|
end
|
289
291
|
|
290
292
|
context 'with oauth_2legged' do
|
291
293
|
subject { described_class.new(consumer_key: 'foo', consumer_secret: 'bar', auth_type: :oauth_2legged) }
|
292
294
|
|
293
|
-
|
295
|
+
it_behaves_like 'OAuth Common Tests'
|
294
296
|
end
|
295
297
|
|
296
298
|
context 'with unknown options' do
|
@@ -88,7 +88,7 @@ describe JIRA::HttpClient do
|
|
88
88
|
response
|
89
89
|
end
|
90
90
|
|
91
|
-
context 'simple client' do
|
91
|
+
context 'with a simple client' do
|
92
92
|
let(:client) do
|
93
93
|
options_local = JIRA::Client::DEFAULT_OPTIONS.merge(JIRA::HttpClient::DEFAULT_OPTIONS).merge(
|
94
94
|
proxy_address: 'proxyAddress',
|
@@ -295,7 +295,7 @@ describe JIRA::HttpClient do
|
|
295
295
|
expect(proxy_configuration.proxy_pass).to be_nil
|
296
296
|
end
|
297
297
|
|
298
|
-
context 'client has proxy settings' do
|
298
|
+
context 'when the client has proxy settings' do
|
299
299
|
subject(:proxy_conn) { proxy_client.basic_auth_http_conn }
|
300
300
|
|
301
301
|
let(:proxy_client) do
|
@@ -37,7 +37,7 @@ describe JIRA::OauthClient do
|
|
37
37
|
|
38
38
|
it 'could pre-process the response body in a block' do
|
39
39
|
response = Net::HTTPSuccess.new(1.0, '200', 'OK')
|
40
|
-
|
40
|
+
allow(oauth_client.consumer).to receive(:request).and_return(response)
|
41
41
|
allow(response).to receive(:body).and_return('&oauth_token=token&oauth_token_secret=secret&password=top_secret')
|
42
42
|
|
43
43
|
result = oauth_client.request_token do |response_body|
|
@@ -127,16 +127,20 @@ describe JIRA::OauthClient do
|
|
127
127
|
oauth_client.request(:get, '/foo', body, headers)
|
128
128
|
end
|
129
129
|
|
130
|
-
context '
|
130
|
+
context 'when a multipart request' do
|
131
131
|
subject { oauth_client.make_multipart_request('/path', data, headers) }
|
132
132
|
|
133
133
|
let(:data) { {} }
|
134
134
|
let(:headers) { {} }
|
135
135
|
|
136
136
|
it 'signs the access_token and performs the request' do
|
137
|
+
http_mock = double('HTTP')
|
138
|
+
|
139
|
+
consumer_mock = oauth_client.consumer
|
140
|
+
|
137
141
|
expect(access_token).to receive(:sign!).with(an_instance_of(Net::HTTP::Post::Multipart))
|
138
|
-
expect(
|
139
|
-
|
142
|
+
expect(consumer_mock).to receive(:http).and_return(http_mock)
|
143
|
+
expect(http_mock).to receive(:request).with(an_instance_of(Net::HTTP::Post::Multipart))
|
140
144
|
|
141
145
|
subject
|
142
146
|
end
|
@@ -31,7 +31,7 @@ describe JIRA::Resource::Agile do
|
|
31
31
|
expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/issue?').and_return(response)
|
32
32
|
expect(response).to receive(:body).and_return(get_mock_response('board/1_issues.json'))
|
33
33
|
|
34
|
-
expect(client).to receive(:get).with('/jira/rest/api/2/search?jql=id+IN%2810546%2C+10547%2C+10556%2C+10557%2C+10558%2C+10559%2C+10600%2C+10601%2C+10604%29').and_return(response)
|
34
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/search/jql?jql=id+IN%2810546%2C+10547%2C+10556%2C+10557%2C+10558%2C+10559%2C+10600%2C+10601%2C+10604%29').and_return(response)
|
35
35
|
expect(response).to receive(:body).and_return(get_mock_response('board/1_issues.json'))
|
36
36
|
|
37
37
|
issues = described_class.get_board_issues(client, 1)
|
@@ -40,7 +40,7 @@ describe JIRA::Resource::Agile do
|
|
40
40
|
|
41
41
|
issues.each do |issue|
|
42
42
|
expect(issue.class).to eq(JIRA::Resource::Issue)
|
43
|
-
expect(issue
|
43
|
+
expect(issue).not_to be_expanded
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
@@ -48,7 +48,7 @@ describe JIRA::Resource::Agile do
|
|
48
48
|
expect(client).to receive(:get).with('/jira/rest/agile/1.0/board/1/issue?startAt=50').and_return(response)
|
49
49
|
expect(response).to receive(:body).and_return(get_mock_response('board/1_issues.json'))
|
50
50
|
|
51
|
-
expect(client).to receive(:get).with('/jira/rest/api/2/search?jql=id+IN%2810546%2C+10547%2C+10556%2C+10557%2C+10558%2C+10559%2C+10600%2C+10601%2C+10604%29').and_return(response)
|
51
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/search/jql?jql=id+IN%2810546%2C+10547%2C+10556%2C+10557%2C+10558%2C+10559%2C+10600%2C+10601%2C+10604%29').and_return(response)
|
52
52
|
expect(response).to receive(:body).and_return(get_mock_response('board/1_issues.json'))
|
53
53
|
|
54
54
|
issues = described_class.get_board_issues(client, 1, startAt: 50)
|
@@ -57,7 +57,7 @@ describe JIRA::Resource::Agile do
|
|
57
57
|
|
58
58
|
issues.each do |issue|
|
59
59
|
expect(issue.class).to eq(JIRA::Resource::Issue)
|
60
|
-
expect(issue
|
60
|
+
expect(issue).not_to be_expanded
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|