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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/CI.yml +1 -0
  3. data/.github/workflows/codeql.yml +0 -4
  4. data/.gitignore +3 -1
  5. data/.rubocop.yml +1 -69
  6. data/.yardopts +4 -0
  7. data/lib/jira/base.rb +5 -13
  8. data/lib/jira/client.rb +59 -4
  9. data/lib/jira/has_many_proxy.rb +30 -28
  10. data/lib/jira/http_client.rb +64 -1
  11. data/lib/jira/oauth_client.rb +62 -0
  12. data/lib/jira/request_client.rb +26 -1
  13. data/lib/jira/resource/attachment.rb +88 -3
  14. data/lib/jira/resource/field.rb +4 -8
  15. data/lib/jira/resource/issue.rb +64 -4
  16. data/lib/jira/resource/issue_picker_suggestions.rb +1 -1
  17. data/lib/jira/resource/issuelink.rb +4 -3
  18. data/lib/jira/resource/watcher.rb +1 -1
  19. data/lib/jira/resource/webhook.rb +5 -1
  20. data/lib/jira/version.rb +1 -1
  21. data/lib/tasks/generate.rake +1 -1
  22. data/spec/integration/project_spec.rb +1 -1
  23. data/spec/integration/rapidview_spec.rb +1 -1
  24. data/spec/integration/user_spec.rb +12 -3
  25. data/spec/integration/watcher_spec.rb +6 -2
  26. data/spec/integration/{webhook.rb → webhook_spec.rb} +8 -1
  27. data/spec/jira/base_factory_spec.rb +11 -2
  28. data/spec/jira/base_spec.rb +80 -57
  29. data/spec/jira/client_spec.rb +20 -18
  30. data/spec/jira/http_client_spec.rb +2 -2
  31. data/spec/jira/oauth_client_spec.rb +8 -4
  32. data/spec/jira/resource/agile_spec.rb +2 -2
  33. data/spec/jira/resource/attachment_spec.rb +36 -13
  34. data/spec/jira/resource/board_spec.rb +5 -5
  35. data/spec/jira/resource/field_spec.rb +23 -24
  36. data/spec/jira/resource/issue_spec.rb +18 -18
  37. data/spec/jira/resource/project_spec.rb +6 -6
  38. data/spec/jira/resource/sprint_spec.rb +20 -8
  39. data/spec/jira/resource/status_spec.rb +1 -1
  40. data/spec/jira/resource/user_factory_spec.rb +2 -2
  41. data/spec/jira/resource/worklog_spec.rb +1 -1
  42. data/spec/support/clients_helper.rb +2 -2
  43. data/spec/support/mock_client.rb +9 -0
  44. data/spec/support/mock_response.rb +8 -0
  45. metadata +9 -10
@@ -4,32 +4,44 @@ describe JIRA::Base do
4
4
  class JIRADelegation < SimpleDelegator # :nodoc:
5
5
  end
6
6
 
7
- class JIRA::Resource::Deadbeef < JIRA::Base # :nodoc:
8
- end
9
-
10
- class JIRA::Resource::HasOneExample < JIRA::Base # :nodoc:
11
- has_one :deadbeef
12
- has_one :muffin, class: JIRA::Resource::Deadbeef
13
- has_one :brunchmuffin, class: JIRA::Resource::Deadbeef,
14
- nested_under: 'nested'
15
- has_one :breakfastscone,
16
- class: JIRA::Resource::Deadbeef,
17
- nested_under: %w[nested breakfastscone]
18
- has_one :irregularly_named_thing,
19
- class: JIRA::Resource::Deadbeef,
20
- attribute_key: 'irregularlyNamedThing'
21
- end
22
-
23
- class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc:
24
- has_many :deadbeefs
25
- has_many :brunchmuffins, class: JIRA::Resource::Deadbeef,
26
- nested_under: 'nested'
27
- has_many :breakfastscones,
28
- class: JIRA::Resource::Deadbeef,
29
- nested_under: %w[nested breakfastscone]
30
- has_many :irregularly_named_things,
31
- class: JIRA::Resource::Deadbeef,
32
- attribute_key: 'irregularlyNamedThings'
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 eq(true)
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.expanded?).to be_falsey
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('Response', body: '{"self":"http://deadbeef/","id":"98765"}')
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.expanded?).to be_truthy
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
- 'Response',
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.expanded?).to be_truthy
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.expanded?).to be_falsey
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('Response', body: '{"self":"http://deadbeef/","id":"98765"}')
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.expanded?).to be_falsey
193
+ expect(subject).not_to be_expanded
182
194
  subject.fetch
183
- expect(subject.expanded?).to be_truthy
195
+ expect(subject).to be_expanded
184
196
  end
185
197
 
186
198
  it 'performs a fetch' do
187
- expect(subject.expanded?).to be_falsey
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
- 'Response',
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('Response', body: '{"id":"123"}')
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('Response', body: nil)
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('Response', body: nil)
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('Response', body: '{"errorMessages":["blah"]}', status: 400)
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('Response', body: 'totally invalid json', code: 401, message: 'Unauthorized')
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('Response', body: '{"id":"123"}')
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('Response', body: nil)
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('Response', body: '{"errorMessages":["blah"]}', status: 400)
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.deleted?).to be_falsey
351
+ expect(subject).not_to be_deleted
336
352
  subject.delete
337
- expect(subject.deleted?).to be_truthy
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.new_record?).to be_truthy
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.new_record?).to be_falsey
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.has_errors?).to be_truthy
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.has_errors?).to be_falsey
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('Response', body: '{"foo":"bar"}')
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('Response', body: '{"foo":"bar"}')
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('Response', body: nil)
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
- class JIRA::Resource::BelongsToExample < JIRA::Base
584
- belongs_to :deadbeef
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:) }
@@ -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
- subject { JIRA::Client.new(options) }
65
+ let(:basic_options) { { use_client_cert: true } }
66
66
 
67
- let(:options) { { use_client_cert: true } }
68
-
69
- it 'raises an ArgumentError' do
67
+ it 'raises an ArgumentError when cert is missing' do
70
68
  expect do
71
- subject
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
- options[:ssl_client_cert] = '<cert></cert>'
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
- subject
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.authenticated?).to be_falsey
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.authenticated?).to be_truthy
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 that applies to all client classes irrespective of authentication method' do
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.authenticated?).to be_truthy
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.authenticated?).to be_falsey
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
- 'lastFailedLoginTime' => (DateTime.now - 2).iso8601,
195
- 'previousLoginTime' => (DateTime.now - 5).iso8601 }
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.authenticated?).to be_falsey
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.authenticated?).to be_falsey
280
+ expect(subject).not_to be_authenticated
279
281
  expect(subject.Project.all).to be_empty
280
- expect(subject.authenticated?).to be_truthy
282
+ expect(subject).to be_authenticated
281
283
  end
282
284
  end
283
285
 
284
- context 'oauth authentication' do
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
- allow_any_instance_of(OAuth::Consumer).to receive(:request).and_return(response)
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 'for a multipart request' do
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(oauth_client.consumer).to receive_message_chain(:http,
139
- :request).with(an_instance_of(Net::HTTP::Post::Multipart))
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.expanded?).to be_falsey
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.expanded?).to be_falsey
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
- it 'returns meta information about attachment upload' do
48
- expect(client).to receive(:get).with('/jira/rest/api/2/attachment/meta').and_return(response)
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
- subject
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(:attachment_url) { 'https://localhost:2990/secure/attachment/32323/myfile.txt' }
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
- it 'passes file object to block' do
83
- expect(URI).to receive(:parse).with(attachment_url).and_call_original
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
- attachment.download_file do |file|
86
- expect(file.read).to eq(attachment_file_contents)
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
- OpenStruct.new(body: {
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
- OpenStruct.new(body: {
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
- OpenStruct.new(body: {
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)