jira-ruby 0.0.2

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.
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jira::Resource::BaseFactory do
4
+
5
+ class Jira::Resource::FooFactory < Jira::Resource::BaseFactory ; end
6
+ class Jira::Resource::Foo ; end
7
+
8
+ let(:client) { mock() }
9
+ subject { Jira::Resource::FooFactory.new(client) }
10
+
11
+ it "initializes correctly" do
12
+ subject.class.should == Jira::Resource::FooFactory
13
+ subject.client.should == client
14
+ subject.target_class.should == Jira::Resource::Foo
15
+ end
16
+
17
+ it "proxies all to the target class" do
18
+ Jira::Resource::Foo.should_receive(:all).with(client)
19
+ subject.all
20
+ end
21
+
22
+ it "proxies find to the target class" do
23
+ Jira::Resource::Foo.should_receive(:find).with(client, 'FOO')
24
+ subject.find('FOO')
25
+ end
26
+
27
+ it "returns the target class" do
28
+ subject.target_class.should == Jira::Resource::Foo
29
+ end
30
+
31
+ it "proxies build to the target class" do
32
+ attrs = mock()
33
+ Jira::Resource::Foo.should_receive(:build).with(client, attrs)
34
+ subject.build(attrs)
35
+ end
36
+ end
@@ -0,0 +1,292 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jira::Resource::Base do
4
+
5
+ class Jira::Resource::Deadbeef < Jira::Resource::Base ; end
6
+
7
+ let(:client) { mock() }
8
+ let(:attrs) { mock() }
9
+
10
+ subject { Jira::Resource::Deadbeef.new(client, :attrs => attrs) }
11
+
12
+ it "assigns the client and attrs" do
13
+ subject.client.should == client
14
+ subject.attrs.should == attrs
15
+ end
16
+
17
+ it "returns all the deadbeefs" do
18
+ response = mock()
19
+ response.should_receive(:body).and_return('[{"self":"http://deadbeef/","key":"FOO"}]')
20
+ client.should_receive(:get).with('/jira/rest/api/2/deadbeef').and_return(response)
21
+ Jira::Resource::Deadbeef.should_receive(:rest_base_path).and_return('/jira/rest/api/2/deadbeef')
22
+ deadbeefs = Jira::Resource::Deadbeef.all(client)
23
+ deadbeefs.length.should == 1
24
+ first = deadbeefs.first
25
+ first.class.should == Jira::Resource::Deadbeef
26
+ first.attrs['self'].should == 'http://deadbeef/'
27
+ first.attrs['key'].should == 'FOO'
28
+ first.expanded?.should be_false
29
+ end
30
+
31
+ it "finds a deadbeef by key" do
32
+ response = mock()
33
+ response.stub(:body).and_return('{"self":"http://deadbeef/","key":"FOO"}')
34
+ client.should_receive(:get).with('/jira/rest/api/2/deadbeef/FOO').and_return(response)
35
+ Jira::Resource::Deadbeef.should_receive(:rest_base_path).and_return('/jira/rest/api/2/deadbeef')
36
+ deadbeef = Jira::Resource::Deadbeef.find(client, 'FOO')
37
+ deadbeef.client.should == client
38
+ deadbeef.attrs['self'].should == 'http://deadbeef/'
39
+ deadbeef.attrs['key'].should == 'FOO'
40
+ deadbeef.expanded?.should be_true
41
+ end
42
+
43
+ it "builds a deadbeef" do
44
+ deadbeef = Jira::Resource::Deadbeef.build(client, 'key' => "FOO" )
45
+ deadbeef.expanded?.should be_false
46
+
47
+ deadbeef.client.should == client
48
+ deadbeef.attrs['key'].should == 'FOO'
49
+ end
50
+
51
+ it "returns the endpoint name" do
52
+ subject.class.endpoint_name.should == 'deadbeef'
53
+ end
54
+
55
+
56
+ describe "rest_base_path" do
57
+
58
+ before(:each) do
59
+ client.should_receive(:options).and_return(:rest_base_path => '/deadbeef/bar')
60
+ end
61
+
62
+ it "returns the rest_base_path" do
63
+ subject.rest_base_path.should == '/deadbeef/bar/deadbeef'
64
+ end
65
+
66
+ it "has a class method that returns the rest_base_path" do
67
+ subject.class.rest_base_path(client).should == '/deadbeef/bar/deadbeef'
68
+ end
69
+ end
70
+
71
+ it "parses json" do
72
+ described_class.parse_json('{"foo":"bar"}').should == {"foo" => "bar"}
73
+ end
74
+
75
+ describe "dynamic instance methods" do
76
+
77
+ let(:attrs) { {'foo' => 'bar', 'flum' => 'goo', 'object_id' => 'dummy'} }
78
+ subject { Jira::Resource::Deadbeef.new(client, :attrs => attrs) }
79
+
80
+ it "responds to each of the top level attribute names" do
81
+ subject.should respond_to(:foo)
82
+ subject.should respond_to('flum')
83
+ subject.should respond_to(:object_id)
84
+
85
+ subject.foo.should == 'bar'
86
+ subject.flum.should == 'goo'
87
+
88
+ # Should not override existing method names, but should still allow
89
+ # access to their values via the attrs[] hash
90
+ subject.object_id.should_not == 'dummy'
91
+ subject.attrs['object_id'].should == 'dummy'
92
+ end
93
+ end
94
+
95
+ describe "fetch" do
96
+
97
+ subject { Jira::Resource::Deadbeef.new(client, :attrs => {'key' => 'FOO'}) }
98
+
99
+ describe "not cached" do
100
+
101
+ before(:each) do
102
+ response = mock()
103
+ response.stub(:body).and_return('{"self":"http://deadbeef/","key":"FOO"}')
104
+ client.should_receive(:get).with('/jira/rest/api/2/deadbeef/FOO').and_return(response)
105
+ Jira::Resource::Deadbeef.should_receive(:rest_base_path).and_return('/jira/rest/api/2/deadbeef')
106
+ end
107
+
108
+ it "sets expanded to true after fetch" do
109
+ subject.expanded?.should be_false
110
+ subject.fetch
111
+ subject.expanded?.should be_true
112
+ end
113
+
114
+ it "performs a fetch" do
115
+ subject.expanded?.should be_false
116
+ subject.fetch
117
+ subject.self.should == "http://deadbeef/"
118
+ subject.key.should == "FOO"
119
+ end
120
+
121
+ it "performs a fetch if already fetched and force flag is true" do
122
+ subject.expanded = true
123
+ subject.fetch(true)
124
+ end
125
+
126
+ end
127
+
128
+ describe "cached" do
129
+ it "doesn't perform a fetch if already fetched" do
130
+ subject.expanded = true
131
+ client.should_not_receive(:get)
132
+ subject.fetch
133
+ end
134
+ end
135
+
136
+ end
137
+
138
+ describe "save" do
139
+
140
+ let(:response) { mock() }
141
+
142
+ subject { Jira::Resource::Deadbeef.new(client) }
143
+
144
+ before(:each) do
145
+ subject.should_receive(:url).and_return('/foo/bar')
146
+ end
147
+
148
+ it "POSTs a new record" do
149
+ response.stub(:body => '{"id":"123"}')
150
+ subject.stub(:new_record? => true)
151
+ client.should_receive(:post).with('/foo/bar','{"foo":"bar"}').and_return(response)
152
+ subject.save("foo" => "bar").should be_true
153
+ subject.id.should == "123"
154
+ subject.expanded.should be_false
155
+ end
156
+
157
+ it "PUTs an existing record" do
158
+ response.stub(:body => nil)
159
+ subject.stub(:new_record? => false)
160
+ client.should_receive(:put).with('/foo/bar','{"foo":"bar"}').and_return(response)
161
+ subject.save("foo" => "bar").should be_true
162
+ subject.expanded.should be_false
163
+ end
164
+
165
+ it "merges attrs on save" do
166
+ response.stub(:body => nil)
167
+ client.should_receive(:post).with('/foo/bar','{"foo":{"fum":"dum"}}').and_return(response)
168
+ subject.attrs = {"foo" => {"bar" => "baz"}}
169
+ subject.save({"foo" => {"fum" => "dum"}})
170
+ subject.foo.should == {"bar" => "baz", "fum" => "dum"}
171
+ end
172
+
173
+ end
174
+
175
+ describe "set_attrs" do
176
+ it "merges hashes correctly when clobber is true (default)" do
177
+ subject.attrs = {"foo" => {"bar" => "baz"}}
178
+ subject.set_attrs({"foo" => {"fum" => "dum"}})
179
+ subject.foo.should == {"fum" => "dum"}
180
+ end
181
+
182
+ it "merges hashes correctly when clobber is false" do
183
+ subject.attrs = {"foo" => {"bar" => "baz"}}
184
+ subject.set_attrs({"foo" => {"fum" => "dum"}}, false)
185
+ subject.foo.should == {"bar" => "baz", "fum" => "dum"}
186
+ end
187
+ end
188
+
189
+ describe "delete" do
190
+
191
+ before(:each) do
192
+ client.should_receive(:delete).with('/foo/bar')
193
+ subject.stub(:url => '/foo/bar')
194
+ end
195
+
196
+ it "flags itself as deleted" do
197
+ subject.deleted?.should be_false
198
+ subject.delete
199
+ subject.deleted?.should be_true
200
+ end
201
+
202
+ it "sends a DELETE request" do
203
+ subject.delete
204
+ end
205
+
206
+ end
207
+
208
+ describe "new_record?" do
209
+
210
+ it "returns true for new_record? when new object" do
211
+ subject.attrs.stub(:[]).with('id').and_return(nil)
212
+ subject.new_record?.should be_true
213
+ end
214
+
215
+ it "returns false for new_record? when id is set" do
216
+ subject.attrs.stub(:[]).with('id').and_return('123')
217
+ subject.new_record?.should be_false
218
+ end
219
+
220
+ end
221
+
222
+ describe 'url' do
223
+ it "returns self as the URL if set" do
224
+ attrs.stub(:[]).with('self').and_return('http://foo/bar')
225
+ subject.url.should == "http://foo/bar"
226
+ end
227
+
228
+ it "generates the URL from key if self not set" do
229
+ attrs.stub(:[]).with('self').and_return(nil)
230
+ attrs.stub(:[]).with('key').and_return('FOO')
231
+ subject.stub(:rest_base_path => 'http://foo/bar')
232
+ subject.url.should == "http://foo/bar/FOO"
233
+ end
234
+
235
+ it "generates the URL from rest_base_path if self and key not set" do
236
+ attrs.stub(:[]).with('self').and_return(nil)
237
+ attrs.stub(:[]).with('key').and_return(nil)
238
+ subject.stub(:rest_base_path => 'http://foo/bar')
239
+ subject.url.should == "http://foo/bar"
240
+ end
241
+ end
242
+
243
+ it "returns the formatted attrs from to_s" do
244
+ subject.attrs.stub(:[]).with('foo').and_return('bar')
245
+ subject.attrs.stub(:[]).with('dead').and_return('beef')
246
+
247
+ subject.to_s.should match(/#<Jira::Resource::Deadbeef:\d+ @attrs=#{attrs.inspect}>/)
248
+ end
249
+
250
+ it "returns the key attribute" do
251
+ subject.class.key_attribute.should == :key
252
+ end
253
+
254
+ it "converts to json" do
255
+ subject.attrs.stub(:to_json => '{"foo":"bar","dead":"beef"}')
256
+
257
+ subject.to_json.should == '{"foo":"bar","dead":"beef"}'
258
+ end
259
+
260
+ describe "extract attrs from response" do
261
+
262
+ subject { Jira::Resource::Deadbeef.new(client, :attrs => {}) }
263
+
264
+ it "sets the attrs from a response" do
265
+ response = mock()
266
+ response.stub(:body).and_return('{"foo":"bar"}')
267
+
268
+ subject.set_attrs_from_response(response).should == {'foo' => 'bar'}
269
+ subject.foo.should == "bar"
270
+ end
271
+
272
+ it "doesn't clobber existing attrs not in response" do
273
+ response = mock()
274
+ response.stub(:body).and_return('{"foo":"bar"}')
275
+
276
+ subject.attrs = {'flum' => 'flar'}
277
+ subject.set_attrs_from_response(response).should == {'foo' => 'bar'}
278
+ subject.foo.should == "bar"
279
+ subject.flum.should == "flar"
280
+ end
281
+
282
+ it "handles nil response body" do
283
+ response = mock()
284
+ response.stub(:body).and_return(nil)
285
+
286
+ subject.attrs = {'flum' => 'flar'}
287
+ subject.set_attrs_from_response(response).should be_nil
288
+ subject.flum.should == 'flar'
289
+ end
290
+ end
291
+
292
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jira::Resource::HTTPError do
4
+
5
+ let(:response) {
6
+ response = mock("response")
7
+ response.stub(:code => 401)
8
+ response.stub(:message => "A MESSAGE WOO")
9
+ response
10
+ }
11
+ subject { described_class.new(response) }
12
+
13
+ it "takes the response object as an argument" do
14
+ subject.response.should == response
15
+ end
16
+
17
+ it "has a code method" do
18
+ subject.code.should == response.code
19
+ end
20
+
21
+ it "returns code and class from message" do
22
+ subject.message.should == response.message
23
+ end
24
+
25
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jira::Resource::ProjectFactory do
4
+
5
+ let(:client) { mock() }
6
+ subject { Jira::Resource::ProjectFactory.new(client) }
7
+
8
+ it "initializes correctly" do
9
+ subject.class.should == Jira::Resource::ProjectFactory
10
+ subject.client.should == client
11
+ end
12
+
13
+ end
@@ -0,0 +1,28 @@
1
+ {
2
+ "self": "http://localhost:2990/jira/rest/api/2/component/10001",
3
+ "id": "10001",
4
+ "name": "Test component",
5
+ "assigneeType": "PROJECT_DEFAULT",
6
+ "assignee": {
7
+ "self": "http://localhost:2990/jira/rest/api/2/user?username=admin",
8
+ "name": "admin",
9
+ "avatarUrls": {
10
+ "16x16": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10122",
11
+ "48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10122"
12
+ },
13
+ "displayName": "admin",
14
+ "active": true
15
+ },
16
+ "realAssigneeType": "PROJECT_DEFAULT",
17
+ "realAssignee": {
18
+ "self": "http://localhost:2990/jira/rest/api/2/user?username=admin",
19
+ "name": "admin",
20
+ "avatarUrls": {
21
+ "16x16": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10122",
22
+ "48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10122"
23
+ },
24
+ "displayName": "admin",
25
+ "active": true
26
+ },
27
+ "isAssigneeTypeValid": true
28
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "self": "http://localhost:2990/jira/rest/api/2/component/10000",
3
+ "id": "10000",
4
+ "name": "Cheesecake",
5
+ "description": "Description!",
6
+ "lead": {
7
+ "self": "http://localhost:2990/jira/rest/api/2/user?username=admin",
8
+ "name": "admin",
9
+ "avatarUrls": {
10
+ "16x16": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10122",
11
+ "48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10122"
12
+ },
13
+ "displayName": "admin",
14
+ "active": true
15
+ },
16
+ "assigneeType": "PROJECT_DEFAULT",
17
+ "assignee": {
18
+ "self": "http://localhost:2990/jira/rest/api/2/user?username=admin",
19
+ "name": "admin",
20
+ "avatarUrls": {
21
+ "16x16": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10122",
22
+ "48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10122"
23
+ },
24
+ "displayName": "admin",
25
+ "active": true
26
+ },
27
+ "realAssigneeType": "PROJECT_DEFAULT",
28
+ "realAssignee": {
29
+ "self": "http://localhost:2990/jira/rest/api/2/user?username=admin",
30
+ "name": "admin",
31
+ "avatarUrls": {
32
+ "16x16": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10122",
33
+ "48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10122"
34
+ },
35
+ "displayName": "admin",
36
+ "active": true
37
+ },
38
+ "isAssigneeTypeValid": true
39
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "self": "http://localhost:2990/jira/rest/api/2/component/10000",
3
+ "id": "10000",
4
+ "name": "Jammy",
5
+ "description": "Description!",
6
+ "lead": {
7
+ "self": "http://localhost:2990/jira/rest/api/2/user?username=admin",
8
+ "name": "admin",
9
+ "avatarUrls": {
10
+ "16x16": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10122",
11
+ "48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10122"
12
+ },
13
+ "displayName": "admin",
14
+ "active": true
15
+ },
16
+ "assigneeType": "PROJECT_DEFAULT",
17
+ "assignee": {
18
+ "self": "http://localhost:2990/jira/rest/api/2/user?username=admin",
19
+ "name": "admin",
20
+ "avatarUrls": {
21
+ "16x16": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10122",
22
+ "48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10122"
23
+ },
24
+ "displayName": "admin",
25
+ "active": true
26
+ },
27
+ "realAssigneeType": "PROJECT_DEFAULT",
28
+ "realAssignee": {
29
+ "self": "http://localhost:2990/jira/rest/api/2/user?username=admin",
30
+ "name": "admin",
31
+ "avatarUrls": {
32
+ "16x16": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10122",
33
+ "48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10122"
34
+ },
35
+ "displayName": "admin",
36
+ "active": true
37
+ },
38
+ "isAssigneeTypeValid": true
39
+ }