jira-ruby 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
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