pezra-resourceful 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require 'resourceful'
3
+
4
+ describe Resourceful do
5
+
6
+ describe 'setting headers' do
7
+ before do
8
+ @http = Resourceful::HttpAccessor.new
9
+ @resource = @http.resource("http://localhost:42682/header")
10
+ end
11
+
12
+ it 'should handle "Content-Type"' do
13
+ resp = @resource.post("asdf", :content_type => 'foo/bar')
14
+
15
+ header = YAML.load(resp.body)
16
+
17
+ header.should have_key('CONTENT_TYPE')
18
+ header['CONTENT_TYPE'].should == 'foo/bar'
19
+
20
+ end
21
+
22
+ end
23
+ end
24
+
@@ -0,0 +1,12 @@
1
+
2
+ require File.dirname(__FILE__) + '/../spec_helper'
3
+ require 'resourceful'
4
+
5
+ describe Resourceful do
6
+
7
+ describe "redirects" do
8
+
9
+ end
10
+
11
+ end
12
+
@@ -0,0 +1,84 @@
1
+
2
+ require File.dirname(__FILE__) + '/../spec_helper'
3
+ require 'resourceful'
4
+
5
+ describe Resourceful do
6
+
7
+ describe "working with a resource" do
8
+ before do
9
+ @http = Resourceful::HttpAccessor.new
10
+ @resource = @http.resource('http://localhost:3000/')
11
+ end
12
+
13
+ it 'should make the original uri available' do
14
+ @resource.effective_uri.should == 'http://localhost:3000/'
15
+ @resource.uri.should == 'http://localhost:3000/'
16
+ end
17
+
18
+ it 'should set the user agent string on the default header' do
19
+ @resource.default_header.should have_key('User-Agent')
20
+ @resource.default_header['User-Agent'].should == Resourceful::RESOURCEFUL_USER_AGENT_TOKEN
21
+ end
22
+
23
+ describe "GET" do
24
+
25
+ it "should be performable on a resource and return a response" do
26
+ response = @resource.get
27
+ response.should be_kind_of(Resourceful::Response)
28
+ end
29
+
30
+ end
31
+
32
+ describe "POST" do
33
+
34
+ it "should be performable on a resource and return a response" do
35
+ response = @resource.post
36
+ response.should be_kind_of(Resourceful::Response)
37
+ end
38
+
39
+ it "should require Content-Type be set if a body is provided" do
40
+ lambda {
41
+ @resource.post("some text")
42
+ }.should raise_error(Resourceful::MissingContentType)
43
+ end
44
+
45
+ end
46
+
47
+ describe "PUT" do
48
+
49
+ it "should be performable on a resource and return a response" do
50
+ response = @resource.put(nil)
51
+ response.should be_kind_of(Resourceful::Response)
52
+ end
53
+
54
+ it "should require Content-Type be set if a body is provided" do
55
+ lambda {
56
+ @resource.put("some text")
57
+ }.should raise_error(Resourceful::MissingContentType)
58
+ end
59
+
60
+ it "should require an entity-body to be set" do
61
+ lambda {
62
+ @resource.put()
63
+ }.should raise_error(ArgumentError)
64
+ end
65
+
66
+ it "should allow the entity-body to be nil" do
67
+ lambda {
68
+ @resource.put(nil)
69
+ }.should_not raise_error(ArgumentError)
70
+ end
71
+ end
72
+
73
+ describe "DELETE" do
74
+
75
+ it "should be performable on a resource and return a response" do
76
+ response = @resource.delete
77
+ response.should be_kind_of(Resourceful::Response)
78
+ end
79
+
80
+ end
81
+
82
+
83
+ end
84
+ end
@@ -0,0 +1,44 @@
1
+ describe 'redirect', :shared => true do
2
+ it 'should be followed by default on GET' do
3
+ resp = @resource.get
4
+ resp.should be_instance_of(Resourceful::Response)
5
+ resp.should be_ok
6
+ resp.header['Content-Type'].should == ['text/plain']
7
+ end
8
+
9
+ %w{PUT POST}.each do |method|
10
+ it "should not be followed by default on #{method}" do
11
+ resp = @resource.send(method.downcase.intern, nil, :content_type => 'text/plain' )
12
+ resp.should be_redirect
13
+ end
14
+
15
+ it "should redirect on #{method.to_s.upcase} if the redirection callback returns true" do
16
+ @resource.on_redirect { true }
17
+ resp = @resource.send(method.downcase.intern, nil, :content_type => 'text/plain' )
18
+ resp.should be_ok
19
+ end
20
+
21
+ it "should not follow redirect on #{method.to_s.upcase} if the redirection callback returns false" do
22
+ @resource.on_redirect { false }
23
+ resp = @resource.send(method.downcase.intern, nil, :content_type => 'text/plain' )
24
+ resp.should be_redirect
25
+ end
26
+ end
27
+
28
+ it "should not be followed by default on DELETE" do
29
+ resp = @resource.delete
30
+ resp.should be_redirect
31
+ end
32
+
33
+ it "should redirect on DELETE if vthe redirection callback returns true" do
34
+ @resource.on_redirect { true }
35
+ resp = @resource.delete
36
+ resp.should be_ok
37
+ end
38
+
39
+ it "should not redirect on DELETE if the redirection callback returns false" do
40
+ resp = @resource.delete
41
+ resp.should be_redirect
42
+ end
43
+ end
44
+
@@ -0,0 +1,89 @@
1
+
2
+ require 'rubygems'
3
+ require 'fakeweb'
4
+
5
+ $LOAD_PATH << File.join(File.dirname(__FILE__), "..", "lib")
6
+ require 'resourceful'
7
+
8
+ describe "Caching" do
9
+
10
+ before do
11
+ FakeWeb.allow_net_connect = false
12
+ FakeWeb.clean_registry
13
+
14
+ @http = Resourceful::HttpAccessor.new(:cache_manager => Resourceful::InMemoryCacheManager.new)
15
+ if ENV['SPEC_LOGGING']
16
+ @http.logger = Resourceful::StdOutLogger.new
17
+ end
18
+ end
19
+
20
+ describe "should cache" do
21
+
22
+ before do
23
+ FakeWeb.register_uri(:get, "http://example.com/cache",
24
+ [{:body => "Original response", :cache_control => "private,max-age=15"},
25
+ {:body => "Overrode cached response"}]
26
+ )
27
+
28
+ @resource = @http.resource("http://example.com/cache")
29
+ end
30
+
31
+ it "should cache the response" do
32
+ resp = @resource.get
33
+ resp.body.should == "Original response"
34
+
35
+ resp = @resource.get
36
+ resp.body.should == "Original response"
37
+ end
38
+
39
+ end
40
+
41
+ describe "updating headers" do
42
+ before do
43
+ FakeWeb.register_uri(:get, "http://example.com/override",
44
+ [{:body => "Original response", :cache_control => "private,max-age=0", :x_updateme => "foo"},
45
+ {:body => "Overrode cached response", :status => 304, :x_updateme => "bar"} ]
46
+ )
47
+
48
+ @resource = @http.resource("http://example.com/override")
49
+ end
50
+
51
+ it "should update headers from the 304" do
52
+ resp = @resource.get
53
+ resp.headers['X-Updateme'].should == ["foo"]
54
+
55
+ resp = @resource.get
56
+ resp.headers['X-Updateme'].should == ["bar"]
57
+ resp.headers['Cache-Control'].should == ["private,max-age=0"]
58
+ end
59
+
60
+ end
61
+
62
+ describe "updating expiration" do
63
+ before do
64
+ FakeWeb.register_uri(:get, "http://example.com/timeout",
65
+ [{:body => "Original response", :cache_control => "private,max-age=1"},
66
+ {:body => "cached response", :cache_control => "private,max-age=1"}]
67
+ )
68
+
69
+ @resource = @http.resource("http://example.com/timeout")
70
+ end
71
+
72
+ it "should refresh the expiration timer" do
73
+ resp = @resource.get
74
+ resp.should_not be_stale
75
+
76
+ sleep 2
77
+
78
+ resp.should be_stale
79
+
80
+ resp = @resource.get
81
+ resp.should_not be_stale
82
+
83
+ resp = @resource.get
84
+ end
85
+
86
+ end
87
+
88
+
89
+ end
@@ -0,0 +1,378 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname + 'spec_helper'
3
+ require 'resourceful'
4
+
5
+ require Pathname(__FILE__).dirname + 'acceptance_shared_specs'
6
+
7
+
8
+ describe Resourceful do
9
+
10
+ describe 'working with a resource' do
11
+ before do
12
+ @accessor = Resourceful::HttpAccessor.new
13
+ end
14
+
15
+ it 'should set additional headers on the #get' do
16
+ resource = @accessor.resource('http://localhost:3000/echo_header')
17
+ resp = resource.get(:foo => :bar)
18
+ resp.should be_instance_of(Resourceful::Response)
19
+ resp.code.should == 200
20
+ resp.body.should =~ /"HTTP_FOO"=>"bar"/
21
+ end
22
+
23
+ it 'should take an optional default header for reads' do
24
+ resource = @accessor.resource('http://localhost:3000/echo_header', :foo => :bar)
25
+ resp = resource.get
26
+ resp.should be_instance_of(Resourceful::Response)
27
+ resp.code.should == 200
28
+ resp.body.should =~ /"HTTP_FOO"=>"bar"/
29
+ end
30
+
31
+ it 'should take an optional default header for writes' do
32
+ resource = @accessor.resource('http://localhost:3000/echo_header', :foo => :bar)
33
+ resp = resource.post("data", :content_type => 'text/plain')
34
+ resp.should be_instance_of(Resourceful::Response)
35
+ resp.code.should == 200
36
+ resp.body.should =~ /"HTTP_FOO"=>"bar"/
37
+ end
38
+
39
+ it 'should override the default header with any set on a read action' do
40
+ resource = @accessor.resource('http://localhost:3000/echo_header', :foo => :bar)
41
+ resp = resource.get(:foo => :baz)
42
+ resp.should be_instance_of(Resourceful::Response)
43
+ resp.code.should == 200
44
+ resp.body.should =~ /"HTTP_FOO"=>"baz"/
45
+ end
46
+
47
+ it 'should override the default header with any set on a write action' do
48
+ resource = @accessor.resource('http://localhost:3000/echo_header', :foo => :bar)
49
+ resp = resource.post("data", :foo => :baz, :content_type => 'text/plain')
50
+ resp.should be_instance_of(Resourceful::Response)
51
+ resp.code.should == 200
52
+ resp.body.should =~ /"HTTP_FOO"=>"baz"/
53
+ end
54
+
55
+ describe 'redirecting' do
56
+
57
+ describe 'registering callback' do
58
+ before do
59
+ @resource = @accessor.resource('http://localhost:3000/redirect/301?http://localhost:3000/get')
60
+ end
61
+
62
+ it 'should allow a callback to be registered' do
63
+ @resource.should respond_to(:on_redirect)
64
+ end
65
+
66
+ it 'should perform a redirect if the callback is true' do
67
+ @resource.on_redirect { true }
68
+ @resource.get.should be_successful
69
+ end
70
+
71
+ it 'should not perform the redirect if the callback returns false' do
72
+ @resource.on_redirect { false }
73
+ @resource.get
74
+ @resource.get.should be_redirect
75
+ end
76
+ end
77
+
78
+ describe 'permanent redirect' do
79
+ before do
80
+ @redirect_code = 301
81
+ @resource = @accessor.resource('http://localhost:3000/redirect/301?http://localhost:3000/get')
82
+ end
83
+
84
+ it_should_behave_like 'redirect'
85
+
86
+ it 'should change the effective uri of the resource' do
87
+ @resource.get
88
+ @resource.effective_uri.should == 'http://localhost:3000/get'
89
+ end
90
+ end
91
+
92
+ describe 'temporary redirect' do
93
+ before do
94
+ @redirect_code = 302
95
+ @resource = @accessor.resource('http://localhost:3000/redirect/302?http://localhost:3000/get')
96
+ end
97
+
98
+ it_should_behave_like 'redirect'
99
+
100
+ it 'should not change the effective uri of the resource' do
101
+ @resource.get
102
+ @resource.effective_uri.should == 'http://localhost:3000/redirect/302?http://localhost:3000/get'
103
+ end
104
+
105
+ describe '303 See Other' do
106
+ before do
107
+ @redirect_code = 303
108
+ @resource = @accessor.resource('http://localhost:3000/redirect/303?http://localhost:3000/method')
109
+ @resource.on_redirect { true }
110
+ end
111
+
112
+ it 'should GET the redirected resource, regardless of the initial method' do
113
+ resp = @resource.delete
114
+ resp.code.should == 200
115
+ resp.body.should == 'GET'
116
+ end
117
+ end
118
+ end
119
+
120
+ end
121
+
122
+ describe 'caching' do
123
+ before do
124
+ @accessor = Resourceful::HttpAccessor.new(:cache_manager => Resourceful::InMemoryCacheManager.new)
125
+ end
126
+
127
+ it 'should use the cached response' do
128
+ resource = @accessor.resource('http://localhost:3000/get')
129
+ resp = resource.get
130
+ resp.authoritative?.should be_true
131
+
132
+ resp2 = resource.get
133
+ resp2.authoritative?.should be_false
134
+
135
+ resp2.should == resp
136
+ end
137
+
138
+ it 'should not store the representation if the server says not to' do
139
+ resource = @accessor.resource('http://localhost:3000/header?{Vary:%20*}')
140
+ resp = resource.get
141
+ resp.authoritative?.should be_true
142
+ resp.should_not be_cachable
143
+
144
+ resp2 = resource.get
145
+ resp2.should_not == resp
146
+ end
147
+
148
+ it 'should use the cached version of the representation if it has not expired' do
149
+ in_an_hour = (Time.now + (60*60)).httpdate
150
+ uri = URI.escape("http://localhost:3000/header?{Expire: \"#{in_an_hour}\"}")
151
+
152
+ resource = @accessor.resource(uri)
153
+ resp = resource.get
154
+ resp.should be_authoritative
155
+
156
+ resp2 = resource.get
157
+ resp2.should_not be_authoritative
158
+ resp2.should == resp
159
+ end
160
+
161
+ it 'should revalidate the cached response if it has expired' do
162
+ an_hour_ago = (Time.now - (60*60)).httpdate
163
+ uri = URI.escape("http://localhost:3000/header?{Expire: \"#{an_hour_ago}\"}")
164
+
165
+ resource = @accessor.resource(uri)
166
+ resp = resource.get
167
+ resp.should be_authoritative
168
+ resp.should be_expired
169
+
170
+ resp2 = resource.get
171
+ resp2.should be_authoritative
172
+ end
173
+
174
+ it 'should provide the cached version if the server responds with a 304 not modified' do
175
+ in_an_hour = (Time.now + (60*60)).httpdate
176
+ uri = URI.escape("http://localhost:3000/modified?#{in_an_hour}")
177
+
178
+ resource = @accessor.resource(uri)
179
+ resp = resource.get
180
+ resp.should be_authoritative
181
+
182
+ resp2 = resource.get(:cache_control => "max-age=0")
183
+ resp2.should be_authoritative
184
+ resp2.should == resp
185
+ end
186
+
187
+ it 'should not use a cached document for a resource that has been posted to' do
188
+ resource = @accessor.resource('http://localhost:3000/get')
189
+ resp = resource.get
190
+ resp.authoritative?.should be_true
191
+
192
+ resource.post("foo", :content_type => 'text/plain')
193
+
194
+ resp2 = resource.get
195
+ resp2.should_not == resp
196
+ end
197
+
198
+ describe 'Server provided Cache-Control' do
199
+
200
+ it 'should cache anything with "Cache-Control: public"' do
201
+ uri = URI.escape('http://localhost:3000/header?{Cache-Control: public}')
202
+ resource = @accessor.resource(uri)
203
+ resp = resource.get
204
+ resp.authoritative?.should be_true
205
+
206
+ resp2 = resource.get
207
+ resp2.authoritative?.should be_false
208
+
209
+ resp2.should == resp
210
+ end
211
+
212
+ it 'should cache anything with "Cache-Control: private"' do
213
+ uri = URI.escape('http://localhost:3000/header?{Cache-Control: private}')
214
+ resource = @accessor.resource(uri)
215
+ resp = resource.get
216
+ resp.should be_authoritative
217
+
218
+ resp2 = resource.get
219
+ resp2.should_not be_authoritative
220
+
221
+ resp2.should == resp
222
+ end
223
+
224
+ it 'should cache but revalidate anything with "Cache-Control: no-cache"' do
225
+ uri = URI.escape('http://localhost:3000/header?{Cache-Control: no-cache}')
226
+ resource = @accessor.resource(uri)
227
+ resp = resource.get
228
+ resp.authoritative?.should be_true
229
+
230
+ resp2 = resource.get
231
+ resp2.authoritative?.should be_true
232
+ end
233
+
234
+ it 'should revalidate anything that is older than "Cache-Control: max-age" value' do
235
+
236
+ uri = URI.escape('http://localhost:3000/header?{Cache-Control: max-age=1, Date: "Mon, 04 Aug 2008 18:00:00 GMT"}')
237
+ resource = @accessor.resource(uri)
238
+ resp = resource.get
239
+ resp.authoritative?.should be_true
240
+
241
+ resp.expired?.should be_true
242
+
243
+ resp2 = resource.get
244
+ resp2.authoritative?.should be_true
245
+ end
246
+
247
+ it 'should cache but revalidate anything with "Cache-Control: must-revalidate"' do
248
+ uri = URI.escape('http://localhost:3000/header?{Cache-Control: must-revalidate}')
249
+ resource = @accessor.resource(uri)
250
+ resp = resource.get
251
+ resp.authoritative?.should be_true
252
+
253
+ resp2 = resource.get
254
+ resp2.authoritative?.should be_true
255
+ end
256
+
257
+ it 'should not cache anything with "Cache-Control: no-store"' do
258
+ uri = URI.escape('http://localhost:3000/header?{Cache-Control: no-store}')
259
+ resource = @accessor.resource(uri)
260
+ resp = resource.get
261
+ resp.authoritative?.should be_true
262
+
263
+ resp2 = resource.get
264
+ resp2.authoritative?.should be_true
265
+ end
266
+
267
+
268
+ end
269
+
270
+ describe 'Client provided Cache-Control' do
271
+
272
+ it 'should revalidate anything that is older than "Cache-Control: max-age" value' do
273
+ a_minute_ago = (Time.now - 60).httpdate
274
+ uri = URI.escape("http://localhost:3000/header?{Cache-Control: max-age=120, Date: \"#{a_minute_ago}\"}")
275
+ resource = @accessor.resource(uri)
276
+ resp = resource.get
277
+ resp.authoritative?.should be_true
278
+
279
+ resp.expired?.should be_false
280
+
281
+ resp2 = resource.get({:cache_control => "max-age=1"})
282
+ resp2.authoritative?.should be_true
283
+ end
284
+
285
+ end
286
+
287
+ end
288
+
289
+ describe 'authorization' do
290
+ before do
291
+ @uri = 'http://localhost:3000/auth?basic'
292
+ end
293
+
294
+ it 'should automatically add authorization info to the request if its available'
295
+
296
+ it 'should not authenticate if no auth handlers are set' do
297
+ resource = @accessor.resource(@uri)
298
+ lambda {
299
+ resource.get
300
+ }.should raise_error(Resourceful::UnsuccessfulHttpRequestError)
301
+ end
302
+
303
+ it 'should not authenticate if no valid auth handlers are available' do
304
+ basic_handler = Resourceful::BasicAuthenticator.new('Not Test Auth', 'admin', 'secret')
305
+ @accessor.auth_manager.add_auth_handler(basic_handler)
306
+ resource = @accessor.resource(@uri)
307
+ lambda {
308
+ resource.get
309
+ }.should raise_error(Resourceful::UnsuccessfulHttpRequestError)
310
+ end
311
+
312
+ describe 'basic' do
313
+ before do
314
+ @uri = 'http://localhost:3000/auth?basic'
315
+ end
316
+
317
+ it 'should be able to authenticate basic auth' do
318
+ basic_handler = Resourceful::BasicAuthenticator.new('Test Auth', 'admin', 'secret')
319
+ @accessor.auth_manager.add_auth_handler(basic_handler)
320
+ resource = @accessor.resource(@uri)
321
+ resp = resource.get
322
+
323
+ resp.code.should == 200
324
+ end
325
+
326
+ it 'should not keep trying to authenticate with incorrect credentials' do
327
+ basic_handler = Resourceful::BasicAuthenticator.new('Test Auth', 'admin', 'well-known')
328
+ @accessor.auth_manager.add_auth_handler(basic_handler)
329
+ resource = @accessor.resource(@uri)
330
+
331
+ lambda {
332
+ resource.get
333
+ }.should raise_error(Resourceful::UnsuccessfulHttpRequestError)
334
+ end
335
+
336
+ end
337
+
338
+ describe 'digest' do
339
+ before do
340
+ @uri = 'http://localhost:3000/auth/digest'
341
+ end
342
+
343
+ it 'should be able to authenticate digest auth' do
344
+ pending
345
+ digest_handler = Resourceful::DigestAuthenticator.new('Test Auth', 'admin', 'secret')
346
+ @accessor.auth_manager.add_auth_handler(digest_handler)
347
+ resource = @accessor.resource(@uri)
348
+ resp = resource.get
349
+
350
+ resp.code.should == 200
351
+ end
352
+
353
+ end
354
+
355
+ end
356
+
357
+ describe 'error checking' do
358
+
359
+ it 'should raise InvalidResponse when response code is invalid'
360
+
361
+ describe 'client errors' do
362
+
363
+ it 'should raise when there is one'
364
+
365
+ end
366
+
367
+ describe 'server errors' do
368
+
369
+ it 'should raise when there is one'
370
+
371
+ end
372
+
373
+ end
374
+
375
+ end
376
+
377
+ end
378
+