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.
Files changed (54) 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 +5 -70
  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 +80 -11
  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/project.rb +1 -1
  19. data/lib/jira/resource/sprint.rb +2 -2
  20. data/lib/jira/resource/watcher.rb +1 -1
  21. data/lib/jira/resource/webhook.rb +5 -1
  22. data/lib/jira/version.rb +1 -1
  23. data/lib/tasks/generate.rake +1 -1
  24. data/spec/integration/issue_spec.rb +2 -2
  25. data/spec/integration/project_spec.rb +2 -2
  26. data/spec/integration/rapidview_spec.rb +3 -3
  27. data/spec/integration/user_spec.rb +12 -3
  28. data/spec/integration/watcher_spec.rb +6 -2
  29. data/spec/integration/{webhook.rb → webhook_spec.rb} +8 -1
  30. data/spec/jira/base_factory_spec.rb +11 -2
  31. data/spec/jira/base_spec.rb +80 -57
  32. data/spec/jira/client_spec.rb +29 -27
  33. data/spec/jira/http_client_spec.rb +2 -2
  34. data/spec/jira/oauth_client_spec.rb +8 -4
  35. data/spec/jira/resource/agile_spec.rb +4 -4
  36. data/spec/jira/resource/attachment_spec.rb +36 -13
  37. data/spec/jira/resource/board_spec.rb +5 -5
  38. data/spec/jira/resource/field_spec.rb +23 -24
  39. data/spec/jira/resource/filter_spec.rb +3 -2
  40. data/spec/jira/resource/issue_spec.rb +103 -81
  41. data/spec/jira/resource/project_spec.rb +8 -8
  42. data/spec/jira/resource/sprint_spec.rb +23 -11
  43. data/spec/jira/resource/status_spec.rb +1 -1
  44. data/spec/jira/resource/user_factory_spec.rb +2 -2
  45. data/spec/jira/resource/worklog_spec.rb +1 -1
  46. data/spec/mock_responses/board/1_issues.json +2 -1
  47. data/spec/mock_responses/issue.json +1 -0
  48. data/spec/mock_responses/rapidview/SAMPLEPROJECT.issues.full.json +2 -1
  49. data/spec/mock_responses/rapidview/SAMPLEPROJECT.issues.json +2 -1
  50. data/spec/support/clients_helper.rb +2 -2
  51. data/spec/support/mock_client.rb +9 -0
  52. data/spec/support/mock_response.rb +8 -0
  53. data/spec/support/shared_examples/integration.rb +1 -1
  54. 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') { OpenStruct.new(body: '["User1"]') }
45
- allow(client).to receive_message_chain(:User, :build).with('users') { [] }
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
- expect(client).to receive_message_chain(:User, :build).with('User1')
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(options = { issue: })
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
- class JIRA::Resource::FooFactory < JIRA::BaseFactory; end
5
- class JIRA::Resource::Foo; end
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
 
@@ -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
@@ -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
- include_examples 'Client Common Tests'
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.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/')
@@ -160,8 +162,8 @@ describe JIRA::Client do
160
162
  .to_return(status: 401, headers: {})
161
163
  end
162
164
 
163
- include_examples 'Client Common Tests'
164
- include_examples 'HttpClient tests'
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.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
 
@@ -212,8 +214,8 @@ describe JIRA::Client do
212
214
  .to_return(status: 200, body: '[]', headers: {})
213
215
  end
214
216
 
215
- include_examples 'Client Common Tests'
216
- include_examples 'HttpClient tests'
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
- include_examples 'Client Common Tests'
253
- include_examples 'HttpClient tests'
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.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,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.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
- include_examples 'OAuth Common Tests'
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
- include_examples 'OAuth Common Tests'
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
- 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
@@ -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.expanded?).to be_falsey
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.expanded?).to be_falsey
60
+ expect(issue).not_to be_expanded
61
61
  end
62
62
  end
63
63
  end