jira-ruby 1.5.0 → 1.6.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 (88) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +7 -1
  3. data/Guardfile +1 -1
  4. data/Rakefile +4 -5
  5. data/http-basic-example.rb +13 -12
  6. data/jira-ruby.gemspec +9 -10
  7. data/lib/jira-ruby.rb +5 -2
  8. data/lib/jira/base.rb +49 -48
  9. data/lib/jira/base_factory.rb +1 -4
  10. data/lib/jira/client.rb +29 -20
  11. data/lib/jira/has_many_proxy.rb +0 -1
  12. data/lib/jira/http_client.rb +9 -10
  13. data/lib/jira/http_error.rb +3 -5
  14. data/lib/jira/oauth_client.rb +19 -20
  15. data/lib/jira/request_client.rb +3 -4
  16. data/lib/jira/resource/agile.rb +10 -8
  17. data/lib/jira/resource/applinks.rb +5 -8
  18. data/lib/jira/resource/attachment.rb +1 -2
  19. data/lib/jira/resource/board.rb +84 -0
  20. data/lib/jira/resource/comment.rb +0 -2
  21. data/lib/jira/resource/component.rb +1 -3
  22. data/lib/jira/resource/createmeta.rb +12 -14
  23. data/lib/jira/resource/field.rb +22 -22
  24. data/lib/jira/resource/filter.rb +2 -2
  25. data/lib/jira/resource/issue.rb +41 -39
  26. data/lib/jira/resource/issuelink.rb +3 -5
  27. data/lib/jira/resource/issuelinktype.rb +0 -1
  28. data/lib/jira/resource/issuetype.rb +1 -3
  29. data/lib/jira/resource/priority.rb +1 -3
  30. data/lib/jira/resource/project.rb +5 -7
  31. data/lib/jira/resource/rapidview.rb +28 -7
  32. data/lib/jira/resource/remotelink.rb +1 -4
  33. data/lib/jira/resource/resolution.rb +2 -4
  34. data/lib/jira/resource/serverinfo.rb +1 -2
  35. data/lib/jira/resource/sprint.rb +82 -18
  36. data/lib/jira/resource/sprint_report.rb +8 -0
  37. data/lib/jira/resource/status.rb +1 -3
  38. data/lib/jira/resource/transition.rb +2 -6
  39. data/lib/jira/resource/user.rb +12 -2
  40. data/lib/jira/resource/version.rb +1 -3
  41. data/lib/jira/resource/watcher.rb +1 -5
  42. data/lib/jira/resource/webhook.rb +3 -6
  43. data/lib/jira/resource/worklog.rb +3 -5
  44. data/lib/jira/version.rb +1 -1
  45. data/lib/tasks/generate.rake +4 -4
  46. data/spec/integration/attachment_spec.rb +15 -16
  47. data/spec/integration/comment_spec.rb +31 -34
  48. data/spec/integration/component_spec.rb +21 -24
  49. data/spec/integration/field_spec.rb +15 -18
  50. data/spec/integration/issue_spec.rb +44 -48
  51. data/spec/integration/issuelinktype_spec.rb +8 -11
  52. data/spec/integration/issuetype_spec.rb +5 -7
  53. data/spec/integration/priority_spec.rb +5 -8
  54. data/spec/integration/project_spec.rb +13 -20
  55. data/spec/integration/rapidview_spec.rb +17 -10
  56. data/spec/integration/resolution_spec.rb +7 -10
  57. data/spec/integration/status_spec.rb +5 -8
  58. data/spec/integration/transition_spec.rb +17 -20
  59. data/spec/integration/user_spec.rb +24 -8
  60. data/spec/integration/version_spec.rb +21 -25
  61. data/spec/integration/watcher_spec.rb +28 -34
  62. data/spec/integration/webhook.rb +8 -17
  63. data/spec/integration/worklog_spec.rb +30 -34
  64. data/spec/jira/base_factory_spec.rb +11 -12
  65. data/spec/jira/base_spec.rb +204 -228
  66. data/spec/jira/client_spec.rb +26 -28
  67. data/spec/jira/has_many_proxy_spec.rb +11 -12
  68. data/spec/jira/http_client_spec.rb +51 -52
  69. data/spec/jira/http_error_spec.rb +7 -9
  70. data/spec/jira/oauth_client_spec.rb +44 -46
  71. data/spec/jira/request_client_spec.rb +5 -5
  72. data/spec/jira/resource/agile_spec.rb +5 -7
  73. data/spec/jira/resource/attachment_spec.rb +25 -26
  74. data/spec/jira/resource/board_spec.rb +175 -0
  75. data/spec/jira/resource/createmeta_spec.rb +29 -32
  76. data/spec/jira/resource/field_spec.rb +42 -48
  77. data/spec/jira/resource/filter_spec.rb +40 -40
  78. data/spec/jira/resource/issue_spec.rb +87 -89
  79. data/spec/jira/resource/issuelink_spec.rb +1 -1
  80. data/spec/jira/resource/project_factory_spec.rb +2 -4
  81. data/spec/jira/resource/project_spec.rb +33 -33
  82. data/spec/jira/resource/sprint_spec.rb +78 -0
  83. data/spec/jira/resource/user_factory_spec.rb +6 -8
  84. data/spec/jira/resource/worklog_spec.rb +9 -11
  85. data/spec/spec_helper.rb +8 -9
  86. data/spec/support/clients_helper.rb +4 -4
  87. data/spec/support/shared_examples/integration.rb +60 -77
  88. metadata +59 -53
@@ -1,45 +1,44 @@
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
6
 
5
- class JIRA::Resource::FooFactory < JIRA::BaseFactory ; end
6
- class JIRA::Resource::Foo ; end
7
-
8
- let(:client) { double() }
7
+ let(:client) { double }
9
8
  subject { JIRA::Resource::FooFactory.new(client) }
10
9
 
11
- it "initializes correctly" do
10
+ it 'initializes correctly' do
12
11
  expect(subject.class).to eq(JIRA::Resource::FooFactory)
13
12
  expect(subject.client).to eq(client)
14
13
  expect(subject.target_class).to eq(JIRA::Resource::Foo)
15
14
  end
16
15
 
17
- it "proxies all to the target class" do
16
+ it 'proxies all to the target class' do
18
17
  expect(JIRA::Resource::Foo).to receive(:all).with(client)
19
18
  subject.all
20
19
  end
21
20
 
22
- it "proxies find to the target class" do
21
+ it 'proxies find to the target class' do
23
22
  expect(JIRA::Resource::Foo).to receive(:find).with(client, 'FOO')
24
23
  subject.find('FOO')
25
24
  end
26
25
 
27
- it "returns the target class" do
26
+ it 'returns the target class' do
28
27
  expect(subject.target_class).to eq(JIRA::Resource::Foo)
29
28
  end
30
29
 
31
- it "proxies build to the target class" do
32
- attrs = double()
30
+ it 'proxies build to the target class' do
31
+ attrs = double
33
32
  expect(JIRA::Resource::Foo).to receive(:build).with(client, attrs)
34
33
  subject.build(attrs)
35
34
  end
36
35
 
37
- it "proxies collection path to the target class" do
36
+ it 'proxies collection path to the target class' do
38
37
  expect(JIRA::Resource::Foo).to receive(:collection_path).with(client)
39
38
  subject.collection_path
40
39
  end
41
40
 
42
- it "proxies singular path to the target class" do
41
+ it 'proxies singular path to the target class' do
43
42
  expect(JIRA::Resource::Foo).to receive(:singular_path).with(client, 'FOO')
44
43
  subject.singular_path('FOO')
45
44
  end
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe JIRA::Base do
4
-
5
4
  class JIRADelegation < SimpleDelegator # :nodoc:
6
5
  end
7
6
 
@@ -10,57 +9,56 @@ describe JIRA::Base do
10
9
 
11
10
  class JIRA::Resource::HasOneExample < JIRA::Base # :nodoc:
12
11
  has_one :deadbeef
13
- has_one :muffin, :class => JIRA::Resource::Deadbeef
14
- has_one :brunchmuffin, :class => JIRA::Resource::Deadbeef,
15
- :nested_under => 'nested'
12
+ has_one :muffin, class: JIRA::Resource::Deadbeef
13
+ has_one :brunchmuffin, class: JIRA::Resource::Deadbeef,
14
+ nested_under: 'nested'
16
15
  has_one :breakfastscone,
17
- :class => JIRA::Resource::Deadbeef,
18
- :nested_under => ['nested','breakfastscone']
16
+ class: JIRA::Resource::Deadbeef,
17
+ nested_under: %w[nested breakfastscone]
19
18
  has_one :irregularly_named_thing,
20
- :class => JIRA::Resource::Deadbeef,
21
- :attribute_key => 'irregularlyNamedThing'
19
+ class: JIRA::Resource::Deadbeef,
20
+ attribute_key: 'irregularlyNamedThing'
22
21
  end
23
22
 
24
23
  class JIRA::Resource::HasManyExample < JIRA::Base # :nodoc:
25
24
  has_many :deadbeefs
26
- has_many :brunchmuffins, :class => JIRA::Resource::Deadbeef,
27
- :nested_under => 'nested'
25
+ has_many :brunchmuffins, class: JIRA::Resource::Deadbeef,
26
+ nested_under: 'nested'
28
27
  has_many :breakfastscones,
29
- :class => JIRA::Resource::Deadbeef,
30
- :nested_under => ['nested','breakfastscone']
28
+ class: JIRA::Resource::Deadbeef,
29
+ nested_under: %w[nested breakfastscone]
31
30
  has_many :irregularly_named_things,
32
- :class => JIRA::Resource::Deadbeef,
33
- :attribute_key => 'irregularlyNamedThings'
34
-
31
+ class: JIRA::Resource::Deadbeef,
32
+ attribute_key: 'irregularlyNamedThings'
35
33
  end
36
34
 
37
- let(:client) { double("client") }
38
- let(:attrs) { Hash.new }
35
+ let(:client) { double('client') }
36
+ let(:attrs) { {} }
39
37
 
40
- subject { JIRA::Resource::Deadbeef.new(client, :attrs => attrs) }
38
+ subject { JIRA::Resource::Deadbeef.new(client, attrs: attrs) }
41
39
 
42
40
  let(:decorated) { JIRADelegation.new(subject) }
43
41
 
44
- describe "#respond_to?" do
45
- describe "when decorated using SimpleDelegator" do
46
- it "responds to client" do
42
+ describe '#respond_to?' do
43
+ describe 'when decorated using SimpleDelegator' do
44
+ it 'responds to client' do
47
45
  expect(decorated.respond_to?(:client)).to eq(true)
48
46
  end
49
- it "does not raise an error" do
50
- expect {
47
+ it 'does not raise an error' do
48
+ expect do
51
49
  decorated.respond_to?(:client)
52
- }.not_to raise_error
50
+ end.not_to raise_error
53
51
  end
54
52
  end
55
53
  end
56
54
 
57
- it "assigns the client and attrs" do
55
+ it 'assigns the client and attrs' do
58
56
  expect(subject.client).to eq(client)
59
57
  expect(subject.attrs).to eq(attrs)
60
58
  end
61
59
 
62
- it "returns all the deadbeefs" do
63
- response = double()
60
+ it 'returns all the deadbeefs' do
61
+ response = double
64
62
  expect(response).to receive(:body).and_return('[{"self":"http://deadbeef/","id":"98765"}]')
65
63
  expect(client).to receive(:get).with('/jira/rest/api/2/deadbeef').and_return(response)
66
64
  expect(JIRA::Resource::Deadbeef).to receive(:collection_path).and_return('/jira/rest/api/2/deadbeef')
@@ -73,8 +71,8 @@ describe JIRA::Base do
73
71
  expect(first.expanded?).to be_falsey
74
72
  end
75
73
 
76
- it "finds a deadbeef by id" do
77
- response = instance_double("Response", body: '{"self":"http://deadbeef/","id":"98765"}')
74
+ it 'finds a deadbeef by id' do
75
+ response = instance_double('Response', body: '{"self":"http://deadbeef/","id":"98765"}')
78
76
  expect(client).to receive(:get).with('/jira/rest/api/2/deadbeef/98765').and_return(response)
79
77
  expect(JIRA::Resource::Deadbeef).to receive(:collection_path).and_return('/jira/rest/api/2/deadbeef')
80
78
  deadbeef = JIRA::Resource::Deadbeef.find(client, '98765')
@@ -84,16 +82,16 @@ describe JIRA::Base do
84
82
  expect(deadbeef.expanded?).to be_truthy
85
83
  end
86
84
 
87
- it "finds a deadbeef containing changelog by id" do
85
+ it 'finds a deadbeef containing changelog by id' do
88
86
  response = instance_double(
89
- "Response",
87
+ 'Response',
90
88
  body: '{"self":"http://deadbeef/","id":"98765","changelog":{"histories":[]}}'
91
89
  )
92
90
  expect(client).to receive(:get).with('/jira/rest/api/2/deadbeef/98765?expand=changelog').and_return(response)
93
91
 
94
92
  expect(JIRA::Resource::Deadbeef).to receive(:collection_path).and_return('/jira/rest/api/2/deadbeef')
95
93
 
96
- deadbeef = JIRA::Resource::Deadbeef.find(client, '98765', {expand:'changelog'})
94
+ deadbeef = JIRA::Resource::Deadbeef.find(client, '98765', expand: 'changelog')
97
95
  expect(deadbeef.client).to eq(client)
98
96
  expect(deadbeef.attrs['self']).to eq('http://deadbeef/')
99
97
  expect(deadbeef.attrs['id']).to eq('98765')
@@ -101,60 +99,58 @@ describe JIRA::Base do
101
99
  expect(deadbeef.attrs['changelog']['histories']).to eq([])
102
100
  end
103
101
 
104
- it "builds a deadbeef" do
105
- deadbeef = JIRA::Resource::Deadbeef.build(client, 'id' => "98765" )
102
+ it 'builds a deadbeef' do
103
+ deadbeef = JIRA::Resource::Deadbeef.build(client, 'id' => '98765')
106
104
  expect(deadbeef.expanded?).to be_falsey
107
105
 
108
106
  expect(deadbeef.client).to eq(client)
109
107
  expect(deadbeef.attrs['id']).to eq('98765')
110
108
  end
111
109
 
112
- it "returns the endpoint name" do
110
+ it 'returns the endpoint name' do
113
111
  expect(subject.class.endpoint_name).to eq('deadbeef')
114
112
  end
115
113
 
116
- it "returns the path_component" do
114
+ it 'returns the path_component' do
117
115
  attrs['id'] = '123'
118
116
  expect(subject.path_component).to eq('/deadbeef/123')
119
117
  end
120
118
 
121
- it "returns the path component for unsaved instances" do
119
+ it 'returns the path component for unsaved instances' do
122
120
  expect(subject.path_component).to eq('/deadbeef')
123
121
  end
124
122
 
125
- it "converts to a symbol" do
123
+ it 'converts to a symbol' do
126
124
  expect(subject.to_sym).to eq(:deadbeef)
127
125
  end
128
126
 
129
- describe "collection_path" do
130
-
127
+ describe 'collection_path' do
131
128
  before(:each) do
132
- expect(client).to receive(:options).and_return(:rest_base_path => '/deadbeef/bar')
129
+ expect(client).to receive(:options).and_return(rest_base_path: '/deadbeef/bar')
133
130
  end
134
131
 
135
- it "returns the collection_path" do
132
+ it 'returns the collection_path' do
136
133
  expect(subject.collection_path).to eq('/deadbeef/bar/deadbeef')
137
134
  end
138
135
 
139
- it "returns the collection_path with a prefix" do
136
+ it 'returns the collection_path with a prefix' do
140
137
  expect(subject.collection_path('/baz/')).to eq('/deadbeef/bar/baz/deadbeef')
141
138
  end
142
139
 
143
- it "has a class method that returns the collection_path" do
140
+ it 'has a class method that returns the collection_path' do
144
141
  expect(subject.class.collection_path(client)).to eq('/deadbeef/bar/deadbeef')
145
142
  end
146
143
  end
147
144
 
148
- it "parses json" do
149
- expect(described_class.parse_json('{"foo":"bar"}')).to eq({"foo" => "bar"})
145
+ it 'parses json' do
146
+ expect(described_class.parse_json('{"foo":"bar"}')).to eq('foo' => 'bar')
150
147
  end
151
148
 
152
- describe "dynamic instance methods" do
153
-
154
- let(:attrs) { {'foo' => 'bar', 'flum' => 'goo', 'object_id' => 'dummy'} }
155
- subject { JIRA::Resource::Deadbeef.new(client, :attrs => attrs) }
149
+ describe 'dynamic instance methods' do
150
+ let(:attrs) { { 'foo' => 'bar', 'flum' => 'goo', 'object_id' => 'dummy' } }
151
+ subject { JIRA::Resource::Deadbeef.new(client, attrs: attrs) }
156
152
 
157
- it "responds to each of the top level attribute names" do
153
+ it 'responds to each of the top level attribute names' do
158
154
  expect(subject).to respond_to(:foo)
159
155
  expect(subject).to respond_to('flum')
160
156
  expect(subject).to respond_to(:object_id)
@@ -169,39 +165,36 @@ describe JIRA::Base do
169
165
  end
170
166
  end
171
167
 
172
- describe "fetch" do
173
-
174
- subject { JIRA::Resource::Deadbeef.new(client, :attrs => {'id' => '98765'}) }
175
-
176
- describe "not cached" do
168
+ describe 'fetch' do
169
+ subject { JIRA::Resource::Deadbeef.new(client, attrs: { 'id' => '98765' }) }
177
170
 
171
+ describe 'not cached' do
178
172
  before(:each) do
179
- response = instance_double("Response", body: '{"self":"http://deadbeef/","id":"98765"}')
173
+ response = instance_double('Response', body: '{"self":"http://deadbeef/","id":"98765"}')
180
174
  expect(client).to receive(:get).with('/jira/rest/api/2/deadbeef/98765').and_return(response)
181
175
  expect(JIRA::Resource::Deadbeef).to receive(:collection_path).and_return('/jira/rest/api/2/deadbeef')
182
176
  end
183
177
 
184
- it "sets expanded to true after fetch" do
178
+ it 'sets expanded to true after fetch' do
185
179
  expect(subject.expanded?).to be_falsey
186
180
  subject.fetch
187
181
  expect(subject.expanded?).to be_truthy
188
182
  end
189
183
 
190
- it "performs a fetch" do
184
+ it 'performs a fetch' do
191
185
  expect(subject.expanded?).to be_falsey
192
186
  subject.fetch
193
- expect(subject.self).to eq("http://deadbeef/")
194
- expect(subject.id).to eq("98765")
187
+ expect(subject.self).to eq('http://deadbeef/')
188
+ expect(subject.id).to eq('98765')
195
189
  end
196
190
 
197
- it "performs a fetch if already fetched and force flag is true" do
191
+ it 'performs a fetch if already fetched and force flag is true' do
198
192
  subject.expanded = true
199
193
  subject.fetch(true)
200
194
  end
201
-
202
195
  end
203
196
 
204
- describe "cached" do
197
+ describe 'cached' do
205
198
  it "doesn't perform a fetch if already fetched" do
206
199
  subject.expanded = true
207
200
  expect(client).not_to receive(:get)
@@ -212,25 +205,24 @@ describe JIRA::Base do
212
205
  context "with expand parameter 'changelog'" do
213
206
  it "fetchs changelogs '" do
214
207
  response = instance_double(
215
- "Response",
208
+ 'Response',
216
209
  body: '{"self":"http://deadbeef/","id":"98765","changelog":{"histories":[]}}'
217
210
  )
218
211
  expect(client).to receive(:get).with('/jira/rest/api/2/deadbeef/98765?expand=changelog').and_return(response)
219
212
 
220
213
  expect(JIRA::Resource::Deadbeef).to receive(:collection_path).and_return('/jira/rest/api/2/deadbeef')
221
214
 
222
- subject.fetch(false, {expand:'changelog'})
215
+ subject.fetch(false, expand: 'changelog')
223
216
 
224
- expect(subject.self).to eq("http://deadbeef/")
225
- expect(subject.id).to eq("98765")
217
+ expect(subject.self).to eq('http://deadbeef/')
218
+ expect(subject.id).to eq('98765')
226
219
  expect(subject.changelog['histories']).to eq([])
227
220
  end
228
221
  end
229
222
  end
230
223
 
231
- describe "save" do
232
-
233
- let(:response) { double() }
224
+ describe 'save' do
225
+ let(:response) { double }
234
226
 
235
227
  subject { JIRA::Resource::Deadbeef.new(client) }
236
228
 
@@ -238,49 +230,49 @@ describe JIRA::Base do
238
230
  expect(subject).to receive(:url).and_return('/foo/bar')
239
231
  end
240
232
 
241
- it "POSTs a new record" do
242
- response = instance_double("Response", body: '{"id":"123"}')
233
+ it 'POSTs a new record' do
234
+ response = instance_double('Response', body: '{"id":"123"}')
243
235
  allow(subject).to receive(:new_record?) { true }
244
- expect(client).to receive(:post).with('/foo/bar','{"foo":"bar"}').and_return(response)
245
- expect(subject.save("foo" => "bar")).to be_truthy
246
- expect(subject.id).to eq("123")
236
+ expect(client).to receive(:post).with('/foo/bar', '{"foo":"bar"}').and_return(response)
237
+ expect(subject.save('foo' => 'bar')).to be_truthy
238
+ expect(subject.id).to eq('123')
247
239
  expect(subject.expanded).to be_falsey
248
240
  end
249
241
 
250
- it "PUTs an existing record" do
251
- response = instance_double("Response", body: nil)
242
+ it 'PUTs an existing record' do
243
+ response = instance_double('Response', body: nil)
252
244
  allow(subject).to receive(:new_record?) { false }
253
- expect(client).to receive(:put).with('/foo/bar','{"foo":"bar"}').and_return(response)
254
- expect(subject.save("foo" => "bar")).to be_truthy
245
+ expect(client).to receive(:put).with('/foo/bar', '{"foo":"bar"}').and_return(response)
246
+ expect(subject.save('foo' => 'bar')).to be_truthy
255
247
  expect(subject.expanded).to be_falsey
256
248
  end
257
249
 
258
- it "merges attrs on save" do
259
- response = instance_double("Response", body: nil)
260
- expect(client).to receive(:post).with('/foo/bar','{"foo":{"fum":"dum"}}').and_return(response)
261
- subject.attrs = {"foo" => {"bar" => "baz"}}
262
- subject.save({"foo" => {"fum" => "dum"}})
263
- expect(subject.foo).to eq({"bar" => "baz", "fum" => "dum"})
250
+ it 'merges attrs on save' do
251
+ response = instance_double('Response', body: nil)
252
+ expect(client).to receive(:post).with('/foo/bar', '{"foo":{"fum":"dum"}}').and_return(response)
253
+ subject.attrs = { 'foo' => { 'bar' => 'baz' } }
254
+ subject.save('foo' => { 'fum' => 'dum' })
255
+ expect(subject.foo).to eq('bar' => 'baz', 'fum' => 'dum')
264
256
  end
265
257
 
266
- it "returns false when an invalid field is set" do # The JIRA REST API apparently ignores fields that you aren't allowed to set manually
267
- response = instance_double("Response", body: '{"errorMessages":["blah"]}', status: 400)
258
+ it 'returns false when an invalid field is set' do # The JIRA REST API apparently ignores fields that you aren't allowed to set manually
259
+ response = instance_double('Response', body: '{"errorMessages":["blah"]}', status: 400)
268
260
  allow(subject).to receive(:new_record?) { false }
269
- expect(client).to receive(:put).with('/foo/bar','{"invalid_field":"foobar"}').and_raise(JIRA::HTTPError.new(response))
270
- expect(subject.save("invalid_field" => "foobar")).to be_falsey
261
+ expect(client).to receive(:put).with('/foo/bar', '{"invalid_field":"foobar"}').and_raise(JIRA::HTTPError.new(response))
262
+ expect(subject.save('invalid_field' => 'foobar')).to be_falsey
271
263
  end
272
264
 
273
- it "returns false with exception details when non json response body (unauthorized)" do # Unauthorized requests return a non-json body. This makes sure we can handle non-json bodies on HTTPError
274
- response = double("Response", body: 'totally invalid json', code: 401, message: "Unauthorized")
275
- expect(client).to receive(:post).with('/foo/bar','{"foo":"bar"}').and_raise(JIRA::HTTPError.new(response))
276
- expect(subject.save("foo" => "bar")).to be_falsey
277
- expect(subject.attrs["exception"]["code"]).to eq(401)
278
- expect(subject.attrs["exception"]["message"]).to eq("Unauthorized")
265
+ it 'returns false with exception details when non json response body (unauthorized)' do # Unauthorized requests return a non-json body. This makes sure we can handle non-json bodies on HTTPError
266
+ response = double('Response', body: 'totally invalid json', code: 401, message: 'Unauthorized')
267
+ expect(client).to receive(:post).with('/foo/bar', '{"foo":"bar"}').and_raise(JIRA::HTTPError.new(response))
268
+ expect(subject.save('foo' => 'bar')).to be_falsey
269
+ expect(subject.attrs['exception']['code']).to eq(401)
270
+ expect(subject.attrs['exception']['message']).to eq('Unauthorized')
279
271
  end
280
272
  end
281
273
 
282
- describe "save!" do
283
- let(:response) { double() }
274
+ describe 'save!' do
275
+ let(:response) { double }
284
276
 
285
277
  subject { JIRA::Resource::Deadbeef.new(client) }
286
278
 
@@ -288,144 +280,137 @@ describe JIRA::Base do
288
280
  expect(subject).to receive(:url).and_return('/foo/bar')
289
281
  end
290
282
 
291
- it "POSTs a new record" do
292
- response = instance_double("Response", body: '{"id":"123"}')
283
+ it 'POSTs a new record' do
284
+ response = instance_double('Response', body: '{"id":"123"}')
293
285
  allow(subject).to receive(:new_record?) { true }
294
- expect(client).to receive(:post).with('/foo/bar','{"foo":"bar"}').and_return(response)
295
- expect(subject.save!("foo" => "bar")).to be_truthy
296
- expect(subject.id).to eq("123")
286
+ expect(client).to receive(:post).with('/foo/bar', '{"foo":"bar"}').and_return(response)
287
+ expect(subject.save!('foo' => 'bar')).to be_truthy
288
+ expect(subject.id).to eq('123')
297
289
  expect(subject.expanded).to be_falsey
298
290
  end
299
291
 
300
- it "PUTs an existing record" do
301
- response = instance_double("Response", body: nil)
292
+ it 'PUTs an existing record' do
293
+ response = instance_double('Response', body: nil)
302
294
  allow(subject).to receive(:new_record?) { false }
303
- expect(client).to receive(:put).with('/foo/bar','{"foo":"bar"}').and_return(response)
304
- expect(subject.save!("foo" => "bar")).to be_truthy
295
+ expect(client).to receive(:put).with('/foo/bar', '{"foo":"bar"}').and_return(response)
296
+ expect(subject.save!('foo' => 'bar')).to be_truthy
305
297
  expect(subject.expanded).to be_falsey
306
298
  end
307
299
 
308
- it "throws an exception when an invalid field is set" do
309
- response = instance_double("Response", body: '{"errorMessages":["blah"]}', status: 400)
300
+ it 'throws an exception when an invalid field is set' do
301
+ response = instance_double('Response', body: '{"errorMessages":["blah"]}', status: 400)
310
302
  allow(subject).to receive(:new_record?) { false }
311
- expect(client).to receive(:put).with('/foo/bar','{"invalid_field":"foobar"}').and_raise(JIRA::HTTPError.new(response))
312
- expect(lambda{ subject.save!("invalid_field" => "foobar") }).to raise_error(JIRA::HTTPError)
303
+ expect(client).to receive(:put).with('/foo/bar', '{"invalid_field":"foobar"}').and_raise(JIRA::HTTPError.new(response))
304
+ expect(-> { subject.save!('invalid_field' => 'foobar') }).to raise_error(JIRA::HTTPError)
313
305
  end
314
306
  end
315
307
 
316
- describe "set_attrs" do
317
- it "merges hashes correctly when clobber is true (default)" do
318
- subject.attrs = {"foo" => {"bar" => "baz"}}
319
- subject.set_attrs({"foo" => {"fum" => "dum"}})
320
- expect(subject.foo).to eq({"fum" => "dum"})
308
+ describe 'set_attrs' do
309
+ it 'merges hashes correctly when clobber is true (default)' do
310
+ subject.attrs = { 'foo' => { 'bar' => 'baz' } }
311
+ subject.set_attrs('foo' => { 'fum' => 'dum' })
312
+ expect(subject.foo).to eq('fum' => 'dum')
321
313
  end
322
314
 
323
- it "merges hashes correctly when clobber is false" do
324
- subject.attrs = {"foo" => {"bar" => "baz"}}
325
- subject.set_attrs({"foo" => {"fum" => "dum"}}, false)
326
- expect(subject.foo).to eq({"bar" => "baz", "fum" => "dum"})
315
+ it 'merges hashes correctly when clobber is false' do
316
+ subject.attrs = { 'foo' => { 'bar' => 'baz' } }
317
+ subject.set_attrs({ 'foo' => { 'fum' => 'dum' } }, false)
318
+ expect(subject.foo).to eq('bar' => 'baz', 'fum' => 'dum')
327
319
  end
328
320
  end
329
321
 
330
- describe "delete" do
331
-
322
+ describe 'delete' do
332
323
  before(:each) do
333
324
  expect(client).to receive(:delete).with('/foo/bar')
334
325
  allow(subject).to receive(:url) { '/foo/bar' }
335
326
  end
336
327
 
337
- it "flags itself as deleted" do
328
+ it 'flags itself as deleted' do
338
329
  expect(subject.deleted?).to be_falsey
339
330
  subject.delete
340
331
  expect(subject.deleted?).to be_truthy
341
332
  end
342
333
 
343
- it "sends a DELETE request" do
334
+ it 'sends a DELETE request' do
344
335
  subject.delete
345
336
  end
346
-
347
337
  end
348
338
 
349
- describe "new_record?" do
350
-
351
- it "returns true for new_record? when new object" do
339
+ describe 'new_record?' do
340
+ it 'returns true for new_record? when new object' do
352
341
  subject.attrs['id'] = nil
353
342
  expect(subject.new_record?).to be_truthy
354
343
  end
355
344
 
356
- it "returns false for new_record? when id is set" do
345
+ it 'returns false for new_record? when id is set' do
357
346
  subject.attrs['id'] = '123'
358
347
  expect(subject.new_record?).to be_falsey
359
348
  end
360
-
361
349
  end
362
350
 
363
- describe "has_errors?" do
364
-
365
- it "returns true when the response contains errors" do
366
- attrs["errors"] = {"invalid" => "Field invalid"}
351
+ describe 'has_errors?' do
352
+ it 'returns true when the response contains errors' do
353
+ attrs['errors'] = { 'invalid' => 'Field invalid' }
367
354
  expect(subject.has_errors?).to be_truthy
368
355
  end
369
356
 
370
- it "returns false when the response does not contain any errors" do
357
+ it 'returns false when the response does not contain any errors' do
371
358
  expect(subject.has_errors?).to be_falsey
372
359
  end
373
-
374
360
  end
375
361
 
376
362
  describe 'url' do
377
-
378
363
  before(:each) do
379
- allow(client).to receive(:options) { {:rest_base_path => '/foo/bar'} }
364
+ allow(client).to receive(:options) { { rest_base_path: '/foo/bar' } }
380
365
  end
381
366
 
382
- it "returns self as the URL if set" do
367
+ it 'returns self as the URL if set' do
383
368
  attrs['self'] = 'http://foo/bar'
384
- expect(subject.url).to eq("http://foo/bar")
369
+ expect(subject.url).to eq('http://foo/bar')
385
370
  end
386
371
 
387
- it "generates the URL from id if self not set" do
372
+ it 'generates the URL from id if self not set' do
388
373
  attrs['self'] = nil
389
374
  attrs['id'] = '98765'
390
- expect(subject.url).to eq("/foo/bar/deadbeef/98765")
375
+ expect(subject.url).to eq('/foo/bar/deadbeef/98765')
391
376
  end
392
377
 
393
- it "generates the URL from collection_path if self and id not set" do
378
+ it 'generates the URL from collection_path if self and id not set' do
394
379
  attrs['self'] = nil
395
- attrs['id'] = nil
396
- expect(subject.url).to eq("/foo/bar/deadbeef")
380
+ attrs['id'] = nil
381
+ expect(subject.url).to eq('/foo/bar/deadbeef')
397
382
  end
398
383
 
399
- it "has a class method for the collection path" do
400
- expect(JIRA::Resource::Deadbeef.collection_path(client)).to eq("/foo/bar/deadbeef")
401
- #Should accept an optional prefix (flum in this case)
402
- expect(JIRA::Resource::Deadbeef.collection_path(client, '/flum/')).to eq("/foo/bar/flum/deadbeef")
384
+ it 'has a class method for the collection path' do
385
+ expect(JIRA::Resource::Deadbeef.collection_path(client)).to eq('/foo/bar/deadbeef')
386
+ # Should accept an optional prefix (flum in this case)
387
+ expect(JIRA::Resource::Deadbeef.collection_path(client, '/flum/')).to eq('/foo/bar/flum/deadbeef')
403
388
  end
404
389
 
405
- it "has a class method for the singular path" do
406
- expect(JIRA::Resource::Deadbeef.singular_path(client, 'abc123')).to eq("/foo/bar/deadbeef/abc123")
407
- #Should accept an optional prefix (flum in this case)
408
- expect(JIRA::Resource::Deadbeef.singular_path(client, 'abc123', '/flum/')).to eq("/foo/bar/flum/deadbeef/abc123")
390
+ it 'has a class method for the singular path' do
391
+ expect(JIRA::Resource::Deadbeef.singular_path(client, 'abc123')).to eq('/foo/bar/deadbeef/abc123')
392
+ # Should accept an optional prefix (flum in this case)
393
+ expect(JIRA::Resource::Deadbeef.singular_path(client, 'abc123', '/flum/')).to eq('/foo/bar/flum/deadbeef/abc123')
409
394
  end
410
395
  end
411
396
 
412
- it "returns the formatted attrs from to_s" do
397
+ it 'returns the formatted attrs from to_s' do
413
398
  subject.attrs['foo'] = 'bar'
414
399
  subject.attrs['dead'] = 'beef'
415
400
 
416
401
  expect(subject.to_s).to match(/#<JIRA::Resource::Deadbeef:\d+ @attrs=#{Regexp.quote(attrs.inspect)}>/)
417
402
  end
418
403
 
419
- it "returns the key attribute" do
404
+ it 'returns the key attribute' do
420
405
  expect(subject.class.key_attribute).to eq(:id)
421
406
  end
422
407
 
423
- it "returns the key value" do
408
+ it 'returns the key value' do
424
409
  subject.attrs['id'] = '123'
425
410
  expect(subject.key_value).to eq('123')
426
411
  end
427
412
 
428
- it "converts to json" do
413
+ it 'converts to json' do
429
414
  subject.attrs = { 'foo' => 'bar', 'dead' => 'beef' }
430
415
  expect(subject.to_json).to eq(subject.attrs.to_json)
431
416
 
@@ -434,53 +419,49 @@ describe JIRA::Base do
434
419
  expect(h.to_json).to eq(h_attrs.to_json)
435
420
  end
436
421
 
437
- describe "extract attrs from response" do
438
-
439
- subject { JIRA::Resource::Deadbeef.new(client, :attrs => {}) }
422
+ describe 'extract attrs from response' do
423
+ subject { JIRA::Resource::Deadbeef.new(client, attrs: {}) }
440
424
 
441
- it "sets the attrs from a response" do
442
- response = instance_double("Response", body: '{"foo":"bar"}')
425
+ it 'sets the attrs from a response' do
426
+ response = instance_double('Response', body: '{"foo":"bar"}')
443
427
 
444
- expect(subject.set_attrs_from_response(response)).to eq({'foo' => 'bar'})
445
- expect(subject.foo).to eq("bar")
428
+ expect(subject.set_attrs_from_response(response)).to eq('foo' => 'bar')
429
+ expect(subject.foo).to eq('bar')
446
430
  end
447
431
 
448
432
  it "doesn't clobber existing attrs not in response" do
449
- response = instance_double("Response", body: '{"foo":"bar"}')
433
+ response = instance_double('Response', body: '{"foo":"bar"}')
450
434
 
451
- subject.attrs = {'flum' => 'flar'}
452
- expect(subject.set_attrs_from_response(response)).to eq({'foo' => 'bar'})
453
- expect(subject.foo).to eq("bar")
454
- expect(subject.flum).to eq("flar")
435
+ subject.attrs = { 'flum' => 'flar' }
436
+ expect(subject.set_attrs_from_response(response)).to eq('foo' => 'bar')
437
+ expect(subject.foo).to eq('bar')
438
+ expect(subject.flum).to eq('flar')
455
439
  end
456
440
 
457
- it "handles nil response body" do
458
- response = instance_double("Response", body: nil)
441
+ it 'handles nil response body' do
442
+ response = instance_double('Response', body: nil)
459
443
 
460
- subject.attrs = {'flum' => 'flar'}
444
+ subject.attrs = { 'flum' => 'flar' }
461
445
  expect(subject.set_attrs_from_response(response)).to be_nil
462
446
  expect(subject.flum).to eq('flar')
463
447
  end
464
448
  end
465
449
 
466
- describe "nesting" do
467
-
468
- it "defaults collection_attributes_are_nested to false" do
450
+ describe 'nesting' do
451
+ it 'defaults collection_attributes_are_nested to false' do
469
452
  expect(JIRA::Resource::Deadbeef.collection_attributes_are_nested).to be_falsey
470
453
  end
471
454
 
472
- it "allows collection_attributes_are_nested to be set" do
455
+ it 'allows collection_attributes_are_nested to be set' do
473
456
  JIRA::Resource::Deadbeef.nested_collections true
474
457
  expect(JIRA::Resource::Deadbeef.collection_attributes_are_nested).to be_truthy
475
458
  end
476
-
477
459
  end
478
460
 
479
- describe "has_many" do
461
+ describe 'has_many' do
462
+ subject { JIRA::Resource::HasManyExample.new(client, attrs: { 'deadbeefs' => [{ 'id' => '123' }] }) }
480
463
 
481
- subject { JIRA::Resource::HasManyExample.new(client, :attrs => {'deadbeefs' => [{'id' => '123'}]}) }
482
-
483
- it "returns a collection of instances for has_many relationships" do
464
+ it 'returns a collection of instances for has_many relationships' do
484
465
  expect(subject.deadbeefs.class).to eq(JIRA::HasManyProxy)
485
466
  expect(subject.deadbeefs.length).to eq(1)
486
467
  subject.deadbeefs.each do |deadbeef|
@@ -488,123 +469,118 @@ describe JIRA::Base do
488
469
  end
489
470
  end
490
471
 
491
- it "returns an empty collection for empty has_many relationships" do
472
+ it 'returns an empty collection for empty has_many relationships' do
492
473
  subject = JIRA::Resource::HasManyExample.new(client)
493
474
  expect(subject.deadbeefs.length).to eq(0)
494
475
  end
495
476
 
496
- it "allows the has_many attributes to be nested inside another attribute" do
497
- subject = JIRA::Resource::HasManyExample.new(client, :attrs => {'nested' => {'brunchmuffins' => [{'id' => '123'},{'id' => '456'}]}})
477
+ it 'allows the has_many attributes to be nested inside another attribute' do
478
+ subject = JIRA::Resource::HasManyExample.new(client, attrs: { 'nested' => { 'brunchmuffins' => [{ 'id' => '123' }, { 'id' => '456' }] } })
498
479
  expect(subject.brunchmuffins.length).to eq(2)
499
480
  subject.brunchmuffins.each do |brunchmuffin|
500
481
  expect(brunchmuffin.class).to eq(JIRA::Resource::Deadbeef)
501
482
  end
502
483
  end
503
484
 
504
- it "allows it to be deeply nested" do
505
- subject = JIRA::Resource::HasManyExample.new(client, :attrs => {'nested' => {
506
- 'breakfastscone' => { 'breakfastscones' => [{'id' => '123'},{'id' => '456'}] }
507
- }})
485
+ it 'allows it to be deeply nested' do
486
+ subject = JIRA::Resource::HasManyExample.new(client, attrs: { 'nested' => {
487
+ 'breakfastscone' => { 'breakfastscones' => [{ 'id' => '123' }, { 'id' => '456' }] }
488
+ } })
508
489
  expect(subject.breakfastscones.length).to eq(2)
509
490
  subject.breakfastscones.each do |breakfastscone|
510
491
  expect(breakfastscone.class).to eq(JIRA::Resource::Deadbeef)
511
492
  end
512
493
  end
513
494
 
514
- it "short circuits missing deeply nested attrs" do
515
- subject = JIRA::Resource::HasManyExample.new(client, :attrs => {
516
- 'nested' => {}
517
- })
495
+ it 'short circuits missing deeply nested attrs' do
496
+ subject = JIRA::Resource::HasManyExample.new(client, attrs: {
497
+ 'nested' => {}
498
+ })
518
499
  expect(subject.breakfastscones.length).to eq(0)
519
500
  end
520
501
 
521
- it "allows the attribute key to be specified" do
522
- subject = JIRA::Resource::HasManyExample.new(client, :attrs => {'irregularlyNamedThings' => [{'id' => '123'},{'id' => '456'}]})
502
+ it 'allows the attribute key to be specified' do
503
+ subject = JIRA::Resource::HasManyExample.new(client, attrs: { 'irregularlyNamedThings' => [{ 'id' => '123' }, { 'id' => '456' }] })
523
504
  expect(subject.irregularly_named_things.length).to eq(2)
524
505
  subject.irregularly_named_things.each do |thing|
525
506
  expect(thing.class).to eq(JIRA::Resource::Deadbeef)
526
507
  end
527
508
  end
528
509
 
529
- it "can build child instances" do
510
+ it 'can build child instances' do
530
511
  deadbeef = subject.deadbeefs.build
531
512
  expect(deadbeef.class).to eq(JIRA::Resource::Deadbeef)
532
513
  end
533
-
534
514
  end
535
515
 
536
- describe "has_one" do
537
-
538
- subject { JIRA::Resource::HasOneExample.new(client, :attrs => {'deadbeef' => {'id' => '123'}}) }
516
+ describe 'has_one' do
517
+ subject { JIRA::Resource::HasOneExample.new(client, attrs: { 'deadbeef' => { 'id' => '123' } }) }
539
518
 
540
- it "returns an instance for a has one relationship" do
519
+ it 'returns an instance for a has one relationship' do
541
520
  expect(subject.deadbeef.class).to eq(JIRA::Resource::Deadbeef)
542
521
  expect(subject.deadbeef.id).to eq('123')
543
522
  end
544
523
 
545
- it "returns nil when resource attribute is nonexistent" do
524
+ it 'returns nil when resource attribute is nonexistent' do
546
525
  subject = JIRA::Resource::HasOneExample.new(client)
547
526
  expect(subject.deadbeef).to be_nil
548
527
  end
549
528
 
550
- it "returns an instance with a different class name to the attribute name" do
551
- subject = JIRA::Resource::HasOneExample.new(client, :attrs => {'muffin' => {'id' => '123'}})
529
+ it 'returns an instance with a different class name to the attribute name' do
530
+ subject = JIRA::Resource::HasOneExample.new(client, attrs: { 'muffin' => { 'id' => '123' } })
552
531
  expect(subject.muffin.class).to eq(JIRA::Resource::Deadbeef)
553
532
  expect(subject.muffin.id).to eq('123')
554
533
  end
555
534
 
556
- it "allows the has_one attributes to be nested inside another attribute" do
557
- subject = JIRA::Resource::HasOneExample.new(client, :attrs => {'nested' => {'brunchmuffin' => {'id' => '123'}}})
535
+ it 'allows the has_one attributes to be nested inside another attribute' do
536
+ subject = JIRA::Resource::HasOneExample.new(client, attrs: { 'nested' => { 'brunchmuffin' => { 'id' => '123' } } })
558
537
  expect(subject.brunchmuffin.class).to eq(JIRA::Resource::Deadbeef)
559
538
  expect(subject.brunchmuffin.id).to eq('123')
560
539
  end
561
540
 
562
- it "allows it to be deeply nested" do
563
- subject = JIRA::Resource::HasOneExample.new(client, :attrs => {'nested' => {
564
- 'breakfastscone' => { 'breakfastscone' => {'id' => '123'} }
565
- }})
541
+ it 'allows it to be deeply nested' do
542
+ subject = JIRA::Resource::HasOneExample.new(client, attrs: { 'nested' => {
543
+ 'breakfastscone' => { 'breakfastscone' => { 'id' => '123' } }
544
+ } })
566
545
  expect(subject.breakfastscone.class).to eq(JIRA::Resource::Deadbeef)
567
546
  expect(subject.breakfastscone.id).to eq('123')
568
547
  end
569
548
 
570
- it "allows the attribute key to be specified" do
571
- subject = JIRA::Resource::HasOneExample.new(client, :attrs => {'irregularlyNamedThing' => {'id' => '123'}})
549
+ it 'allows the attribute key to be specified' do
550
+ subject = JIRA::Resource::HasOneExample.new(client, attrs: { 'irregularlyNamedThing' => { 'id' => '123' } })
572
551
  expect(subject.irregularly_named_thing.class).to eq(JIRA::Resource::Deadbeef)
573
552
  expect(subject.irregularly_named_thing.id).to eq('123')
574
553
  end
575
-
576
554
  end
577
555
 
578
- describe "belongs_to" do
579
-
556
+ describe 'belongs_to' do
580
557
  class JIRA::Resource::BelongsToExample < JIRA::Base
581
558
  belongs_to :deadbeef
582
559
  end
583
560
 
584
- let(:deadbeef) { JIRA::Resource::Deadbeef.new(client, :attrs => {'id' => "999"}) }
561
+ let(:deadbeef) { JIRA::Resource::Deadbeef.new(client, attrs: { 'id' => '999' }) }
585
562
 
586
- subject { JIRA::Resource::BelongsToExample.new(client, :attrs => {'id' => '123'}, :deadbeef => deadbeef) }
563
+ subject { JIRA::Resource::BelongsToExample.new(client, attrs: { 'id' => '123' }, deadbeef: deadbeef) }
587
564
 
588
- it "sets up an accessor for the belongs to relationship" do
565
+ it 'sets up an accessor for the belongs to relationship' do
589
566
  expect(subject.deadbeef).to eq(deadbeef)
590
567
  end
591
568
 
592
- it "raises an exception when initialized without a belongs_to instance" do
569
+ it 'raises an exception when initialized without a belongs_to instance' do
593
570
  expect(lambda {
594
- JIRA::Resource::BelongsToExample.new(client, :attrs => {'id' => '123'})
595
- }).to raise_exception(ArgumentError,"Required option :deadbeef missing")
571
+ JIRA::Resource::BelongsToExample.new(client, attrs: { 'id' => '123' })
572
+ }).to raise_exception(ArgumentError, 'Required option :deadbeef missing')
596
573
  end
597
574
 
598
- it "returns the right url" do
599
- allow(client).to receive(:options) { { :rest_base_path => "/foo" } }
600
- expect(subject.url).to eq("/foo/deadbeef/999/belongstoexample/123")
575
+ it 'returns the right url' do
576
+ allow(client).to receive(:options) { { rest_base_path: '/foo' } }
577
+ expect(subject.url).to eq('/foo/deadbeef/999/belongstoexample/123')
601
578
  end
602
579
 
603
- it "can be initialized with an instance or a key value" do
604
- allow(client).to receive(:options) { { :rest_base_path => "/foo" } }
605
- subject = JIRA::Resource::BelongsToExample.new(client, :attrs => {'id' => '123'}, :deadbeef_id => '987')
606
- expect(subject.url).to eq("/foo/deadbeef/987/belongstoexample/123")
580
+ it 'can be initialized with an instance or a key value' do
581
+ allow(client).to receive(:options) { { rest_base_path: '/foo' } }
582
+ subject = JIRA::Resource::BelongsToExample.new(client, attrs: { 'id' => '123' }, deadbeef_id: '987')
583
+ expect(subject.url).to eq('/foo/deadbeef/987/belongstoexample/123')
607
584
  end
608
-
609
585
  end
610
586
  end