jira-ruby 3.0.0.beta1 → 3.0.0.beta2
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 +1 -69
- 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 +64 -4
- data/lib/jira/resource/issue_picker_suggestions.rb +1 -1
- data/lib/jira/resource/issuelink.rb +4 -3
- 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/project_spec.rb +1 -1
- data/spec/integration/rapidview_spec.rb +1 -1
- 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 +20 -18
- 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 +2 -2
- 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/issue_spec.rb +18 -18
- data/spec/jira/resource/project_spec.rb +6 -6
- data/spec/jira/resource/sprint_spec.rb +20 -8
- 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/support/clients_helper.rb +2 -2
- data/spec/support/mock_client.rb +9 -0
- data/spec/support/mock_response.rb +8 -0
- metadata +9 -10
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
|
@@ -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/')
|
@@ -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
|
|
@@ -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,13 +277,13 @@ 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
|
include_examples 'OAuth Common Tests'
|
@@ -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
|
@@ -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
|
|
@@ -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
|
@@ -4,11 +4,13 @@ describe JIRA::Resource::Attachment do
|
|
4
4
|
subject(:attachment) do
|
5
5
|
described_class.new(
|
6
6
|
client,
|
7
|
-
issue: JIRA::Resource::Issue.new(client),
|
8
|
-
attrs: { 'author' => { 'foo' => 'bar' } }
|
7
|
+
issue: JIRA::Resource::Issue.new(client, attrs: { 'id' => issue_id }),
|
8
|
+
attrs: { 'author' => { 'foo' => 'bar' }, 'id' => attachment_id }
|
9
9
|
)
|
10
10
|
end
|
11
11
|
|
12
|
+
let(:issue_id) { 27_676 }
|
13
|
+
let(:attachment_id) { 30_076 }
|
12
14
|
let(:client) do
|
13
15
|
double(
|
14
16
|
'client',
|
@@ -44,13 +46,17 @@ describe JIRA::Resource::Attachment do
|
|
44
46
|
)
|
45
47
|
end
|
46
48
|
|
47
|
-
|
48
|
-
|
49
|
+
context 'when returning meta information' do
|
50
|
+
it 'returns meta information about attachment upload' do
|
51
|
+
expect(client).to receive(:get).with('/jira/rest/api/2/attachment/meta').and_return(response)
|
49
52
|
|
50
|
-
|
53
|
+
result = subject
|
54
|
+
|
55
|
+
expect(result).to be_a(Hash)
|
56
|
+
end
|
51
57
|
end
|
52
58
|
|
53
|
-
context 'the factory delegates correctly' do
|
59
|
+
context 'when the factory delegates correctly' do
|
54
60
|
subject { JIRA::Resource::AttachmentFactory.new(client) }
|
55
61
|
|
56
62
|
it 'delegates #meta to to target class' do
|
@@ -59,7 +65,7 @@ describe JIRA::Resource::Attachment do
|
|
59
65
|
end
|
60
66
|
end
|
61
67
|
|
62
|
-
context 'there is an attachment on an issue' do
|
68
|
+
context 'when there is an attachment on an issue' do
|
63
69
|
subject(:attachment) do
|
64
70
|
described_class.new(
|
65
71
|
client,
|
@@ -68,22 +74,26 @@ describe JIRA::Resource::Attachment do
|
|
68
74
|
)
|
69
75
|
end
|
70
76
|
|
77
|
+
let(:attachment_url) { 'https://localhost:2990/secure/attachment/32323/myfile.txt' }
|
71
78
|
let(:client) do
|
72
79
|
JIRA::Client.new(username: 'username', password: 'password', auth_type: :basic, use_ssl: false)
|
73
80
|
end
|
74
81
|
let(:attachment_file_contents) { 'file contents' }
|
75
|
-
let(:
|
82
|
+
let(:issue_id) { 3232 }
|
83
|
+
let(:issue) { JIRA::Resource::Issue.new(client, attrs: { 'id' => issue_id }) }
|
76
84
|
|
77
85
|
before do
|
78
86
|
stub_request(:get, attachment_url).to_return(body: attachment_file_contents)
|
79
87
|
end
|
80
88
|
|
81
89
|
describe '.download_file' do
|
82
|
-
|
83
|
-
|
90
|
+
context 'when passing file object to block' do
|
91
|
+
it 'passes file object to block' do
|
92
|
+
expect(URI).to receive(:parse).with(attachment_url).and_call_original
|
84
93
|
|
85
|
-
|
86
|
-
|
94
|
+
attachment.download_file do |file|
|
95
|
+
expect(file.read).to eq(attachment_file_contents)
|
96
|
+
end
|
87
97
|
end
|
88
98
|
end
|
89
99
|
end
|
@@ -91,6 +101,7 @@ describe JIRA::Resource::Attachment do
|
|
91
101
|
describe '.download_contents' do
|
92
102
|
it 'downloads the file contents as a string' do
|
93
103
|
expect(URI).to receive(:parse).with(attachment_url).and_call_original
|
104
|
+
|
94
105
|
expect(attachment.download_contents).to eq(attachment_file_contents)
|
95
106
|
end
|
96
107
|
end
|
@@ -115,7 +126,7 @@ describe JIRA::Resource::Attachment do
|
|
115
126
|
].to_json
|
116
127
|
)
|
117
128
|
end
|
118
|
-
let(:issue) { JIRA::Resource::Issue.new(client) }
|
129
|
+
let(:issue) { JIRA::Resource::Issue.new(client, attrs: { 'id' => issue_id }) }
|
119
130
|
|
120
131
|
describe '#save' do
|
121
132
|
subject { attachment.save('file' => path_to_file) }
|
@@ -125,6 +136,8 @@ describe JIRA::Resource::Attachment do
|
|
125
136
|
end
|
126
137
|
|
127
138
|
it 'successfully update the attachment' do
|
139
|
+
expect(client).to receive(:post_multipart).and_return(response).with("/jira/rest/api/2/issue/#{issue.id}/attachments/#{attachment.id}", anything, anything)
|
140
|
+
|
128
141
|
subject
|
129
142
|
|
130
143
|
expect(attachment.filename).to eq file_name
|
@@ -225,4 +238,14 @@ describe JIRA::Resource::Attachment do
|
|
225
238
|
end
|
226
239
|
end
|
227
240
|
end
|
241
|
+
|
242
|
+
context 'when an attachment is on an issue' do
|
243
|
+
describe '#delete' do
|
244
|
+
it 'removes the attachment' do
|
245
|
+
expect(client).to receive(:delete).with("/jira/rest/api/2/issue/#{issue_id}/attachments/#{attachment_id}")
|
246
|
+
|
247
|
+
attachment.delete
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
228
251
|
end
|
@@ -107,7 +107,7 @@ EOS
|
|
107
107
|
|
108
108
|
context 'when there are multiple pages of results' do
|
109
109
|
let(:result_1) do
|
110
|
-
|
110
|
+
double(body: {
|
111
111
|
'startAt' => 0,
|
112
112
|
'maxResults' => 1,
|
113
113
|
'total' => 2,
|
@@ -115,7 +115,7 @@ EOS
|
|
115
115
|
}.to_json)
|
116
116
|
end
|
117
117
|
let(:result_2) do
|
118
|
-
|
118
|
+
double(body: {
|
119
119
|
'startAt' => 1,
|
120
120
|
'maxResults' => 1,
|
121
121
|
'total' => 2,
|
@@ -132,7 +132,7 @@ EOS
|
|
132
132
|
|
133
133
|
context 'when there is only one page of results' do
|
134
134
|
let(:result_1) do
|
135
|
-
|
135
|
+
double(body: {
|
136
136
|
'startAt' => 0,
|
137
137
|
'maxResults' => 2,
|
138
138
|
'total' => 2,
|
@@ -166,7 +166,7 @@ EOS
|
|
166
166
|
}
|
167
167
|
]
|
168
168
|
}
|
169
|
-
EOS
|
169
|
+
EOS
|
170
170
|
allow(response).to receive(:body).and_return(api_json)
|
171
171
|
allow(board).to receive(:id).and_return(84)
|
172
172
|
expect(client).to receive(:get).with('/rest/agile/1.0/board/84/sprint?').and_return(response)
|
@@ -215,7 +215,7 @@ EOS
|
|
215
215
|
"rankCustomFieldId":10011
|
216
216
|
}
|
217
217
|
}
|
218
|
-
EOS
|
218
|
+
EOS
|
219
219
|
allow(response).to receive(:body).and_return(api_json)
|
220
220
|
allow(board).to receive(:id).and_return(84)
|
221
221
|
expect(client).to receive(:get).with('/rest/agile/1.0/board/84/configuration').and_return(response)
|