httparty 0.4.3 → 0.5.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.
- data/.gitignore +6 -0
- data/History +35 -1
- data/Manifest +1 -4
- data/README.rdoc +54 -0
- data/Rakefile +76 -48
- data/VERSION +1 -0
- data/bin/httparty +33 -22
- data/examples/basic.rb +1 -1
- data/examples/custom_parsers.rb +67 -0
- data/features/steps/env.rb +1 -0
- data/features/steps/httparty_response_steps.rb +2 -2
- data/features/steps/httparty_steps.rb +6 -2
- data/features/steps/mongrel_helper.rb +2 -1
- data/features/steps/remote_service_steps.rb +5 -0
- data/features/supports_timeout_option.feature +12 -0
- data/httparty.gemspec +100 -13
- data/lib/httparty/cookie_hash.rb +16 -3
- data/lib/httparty/core_extensions.rb +9 -3
- data/lib/httparty/exceptions.rb +5 -2
- data/lib/httparty/module_inheritable_attributes.rb +3 -3
- data/lib/httparty/parser.rb +140 -0
- data/lib/httparty/request.rb +92 -50
- data/lib/httparty/response.rb +1 -1
- data/lib/httparty/version.rb +1 -1
- data/lib/httparty.rb +110 -52
- data/spec/httparty/cookie_hash_spec.rb +43 -10
- data/spec/httparty/parser_spec.rb +154 -0
- data/spec/httparty/request_spec.rb +149 -10
- data/spec/httparty/response_spec.rb +1 -1
- data/spec/httparty_spec.rb +210 -39
- data/spec/spec.opts +1 -2
- data/spec/spec_helper.rb +7 -4
- data/website/index.html +35 -36
- metadata +81 -36
- data/README +0 -36
- data/setup.rb +0 -1585
- data/spec/hash_spec.rb +0 -49
- data/spec/string_spec.rb +0 -27
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
|
2
2
|
|
|
3
3
|
describe HTTParty::Request do
|
|
4
4
|
def stub_response(body, code = 200)
|
|
@@ -18,7 +18,20 @@ describe HTTParty::Request do
|
|
|
18
18
|
before do
|
|
19
19
|
@request = HTTParty::Request.new(Net::HTTP::Get, 'http://api.foo.com/v1', :format => :xml)
|
|
20
20
|
end
|
|
21
|
-
|
|
21
|
+
|
|
22
|
+
describe "initialization" do
|
|
23
|
+
it "sets parser to HTTParty::Parser" do
|
|
24
|
+
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com')
|
|
25
|
+
request.parser.should == HTTParty::Parser
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "sets parser to the optional parser" do
|
|
29
|
+
my_parser = lambda {}
|
|
30
|
+
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com', :parser => my_parser)
|
|
31
|
+
request.parser.should == my_parser
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
22
35
|
describe "#format" do
|
|
23
36
|
it "should return the correct parsing format" do
|
|
24
37
|
@request.format.should == :xml
|
|
@@ -30,10 +43,74 @@ describe HTTParty::Request do
|
|
|
30
43
|
request = HTTParty::Request.new(Net::HTTP::Get, 'https://api.foo.com/v1:443')
|
|
31
44
|
request.send(:http).use_ssl?.should == true
|
|
32
45
|
end
|
|
33
|
-
|
|
46
|
+
|
|
34
47
|
it 'should not use ssl for port 80' do
|
|
35
48
|
request = HTTParty::Request.new(Net::HTTP::Get, 'http://foobar.com')
|
|
36
|
-
|
|
49
|
+
request.send(:http).use_ssl?.should == false
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "uses ssl for https scheme with default port" do
|
|
53
|
+
request = HTTParty::Request.new(Net::HTTP::Get, 'https://foobar.com')
|
|
54
|
+
request.send(:http).use_ssl?.should == true
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "uses ssl for https scheme regardless of port" do
|
|
58
|
+
request = HTTParty::Request.new(Net::HTTP::Get, 'https://foobar.com:123456')
|
|
59
|
+
request.send(:http).use_ssl?.should == true
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
context "PEM certificates" do
|
|
63
|
+
before do
|
|
64
|
+
OpenSSL::X509::Certificate.stub(:new)
|
|
65
|
+
OpenSSL::PKey::RSA.stub(:new)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
context "when scheme is https" do
|
|
69
|
+
before do
|
|
70
|
+
@request.stub!(:uri).and_return(URI.parse("https://google.com"))
|
|
71
|
+
pem = :pem_contents
|
|
72
|
+
@cert = mock("OpenSSL::X509::Certificate")
|
|
73
|
+
@key = mock("OpenSSL::PKey::RSA")
|
|
74
|
+
OpenSSL::X509::Certificate.should_receive(:new).with(pem).and_return(@cert)
|
|
75
|
+
OpenSSL::PKey::RSA.should_receive(:new).with(pem).and_return(@key)
|
|
76
|
+
|
|
77
|
+
@request.options[:pem] = pem
|
|
78
|
+
@pem_http = @request.send(:http)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "should use a PEM certificate when provided" do
|
|
82
|
+
@pem_http.cert.should == @cert
|
|
83
|
+
@pem_http.key.should == @key
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "should verify the certificate when provided" do
|
|
87
|
+
@pem_http = @request.send(:http)
|
|
88
|
+
@pem_http.verify_mode.should == OpenSSL::SSL::VERIFY_PEER
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context "when scheme is not https" do
|
|
93
|
+
it "does not assign a PEM" do
|
|
94
|
+
http = Net::HTTP.new('google.com')
|
|
95
|
+
http.should_not_receive(:cert=)
|
|
96
|
+
http.should_not_receive(:key=)
|
|
97
|
+
Net::HTTP.stub(:new => http)
|
|
98
|
+
|
|
99
|
+
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com')
|
|
100
|
+
request.options[:pem] = :pem_contents
|
|
101
|
+
request.send(:http)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "should not verify a certificate if scheme is not https" do
|
|
105
|
+
http = Net::HTTP.new('google.com')
|
|
106
|
+
Net::HTTP.stub(:new => http)
|
|
107
|
+
|
|
108
|
+
request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com')
|
|
109
|
+
request.options[:pem] = :pem_contents
|
|
110
|
+
http = request.send(:http)
|
|
111
|
+
http.verify_mode.should == OpenSSL::SSL::VERIFY_NONE
|
|
112
|
+
end
|
|
113
|
+
end
|
|
37
114
|
end
|
|
38
115
|
|
|
39
116
|
it "should use basic auth when configured" do
|
|
@@ -41,8 +118,26 @@ describe HTTParty::Request do
|
|
|
41
118
|
@request.send(:setup_raw_request)
|
|
42
119
|
@request.instance_variable_get(:@raw_request)['authorization'].should_not be_nil
|
|
43
120
|
end
|
|
121
|
+
|
|
122
|
+
context "when setting timeout" do
|
|
123
|
+
it "does nothing if the timeout option is a string" do
|
|
124
|
+
http = mock("http", :null_object => true)
|
|
125
|
+
http.should_not_receive(:open_timeout=)
|
|
126
|
+
http.should_not_receive(:read_timeout=)
|
|
127
|
+
Net::HTTP.stub(:new => http)
|
|
128
|
+
|
|
129
|
+
request = HTTParty::Request.new(Net::HTTP::Get, 'https://foobar.com', {:timeout => "five seconds"})
|
|
130
|
+
request.send(:http)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "sets the timeout to 5 seconds" do
|
|
134
|
+
@request.options[:timeout] = 5
|
|
135
|
+
@request.send(:http).open_timeout.should == 5
|
|
136
|
+
@request.send(:http).read_timeout.should == 5
|
|
137
|
+
end
|
|
138
|
+
end
|
|
44
139
|
end
|
|
45
|
-
|
|
140
|
+
|
|
46
141
|
describe '#format_from_mimetype' do
|
|
47
142
|
it 'should handle text/xml' do
|
|
48
143
|
["text/xml", "text/xml; charset=iso8859-1"].each do |ct|
|
|
@@ -79,6 +174,15 @@ describe HTTParty::Request do
|
|
|
79
174
|
@request.send(:format_from_mimetype, ct).should == :json
|
|
80
175
|
end
|
|
81
176
|
end
|
|
177
|
+
|
|
178
|
+
it "returns nil for an unrecognized mimetype" do
|
|
179
|
+
@request.send(:format_from_mimetype, "application/atom+xml").should be_nil
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it "returns nil when using a default parser" do
|
|
183
|
+
@request.options[:parser] = lambda {}
|
|
184
|
+
@request.send(:format_from_mimetype, "text/json").should be_nil
|
|
185
|
+
end
|
|
82
186
|
end
|
|
83
187
|
|
|
84
188
|
describe 'parsing responses' do
|
|
@@ -87,7 +191,7 @@ describe HTTParty::Request do
|
|
|
87
191
|
@request.options[:format] = :xml
|
|
88
192
|
@request.send(:parse_response, xml).should == {'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}}
|
|
89
193
|
end
|
|
90
|
-
|
|
194
|
+
|
|
91
195
|
it 'should handle json automatically' do
|
|
92
196
|
json = %q[{"books": {"book": {"name": "Foo Bar!", "id": "1234"}}}]
|
|
93
197
|
@request.options[:format] = :json
|
|
@@ -107,9 +211,8 @@ describe HTTParty::Request do
|
|
|
107
211
|
|
|
108
212
|
@request.perform.headers.should == { "key" => ["value"] }
|
|
109
213
|
end
|
|
110
|
-
|
|
111
|
-
describe 'with non-200 responses' do
|
|
112
214
|
|
|
215
|
+
describe 'with non-200 responses' do
|
|
113
216
|
it 'should return a valid object for 4xx response' do
|
|
114
217
|
stub_response '<foo><bar>yes</bar></foo>', 401
|
|
115
218
|
resp = @request.perform
|
|
@@ -125,7 +228,6 @@ describe HTTParty::Request do
|
|
|
125
228
|
resp.body.should == "<foo><bar>error</bar></foo>"
|
|
126
229
|
resp['foo']['bar'].should == "error"
|
|
127
230
|
end
|
|
128
|
-
|
|
129
231
|
end
|
|
130
232
|
end
|
|
131
233
|
|
|
@@ -135,7 +237,7 @@ describe HTTParty::Request do
|
|
|
135
237
|
@request.options[:format] = :xml
|
|
136
238
|
@request.perform.should be_nil
|
|
137
239
|
end
|
|
138
|
-
|
|
240
|
+
|
|
139
241
|
it "should not fail for missing mime type" do
|
|
140
242
|
stub_response "Content for you"
|
|
141
243
|
@request.options[:format] = :html
|
|
@@ -173,6 +275,43 @@ describe HTTParty::Request do
|
|
|
173
275
|
@request.http_method = Net::HTTP::Put
|
|
174
276
|
@request.perform.should == {"hash" => {"foo" => "bar"}}
|
|
175
277
|
end
|
|
278
|
+
|
|
279
|
+
it "should be handled by HEAD transparently" do
|
|
280
|
+
@request.http_method = Net::HTTP::Head
|
|
281
|
+
@request.perform.should == {"hash" => {"foo" => "bar"}}
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
it "should be handled by OPTIONS transparently" do
|
|
285
|
+
@request.http_method = Net::HTTP::Options
|
|
286
|
+
@request.perform.should == {"hash" => {"foo" => "bar"}}
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
it "should keep track of cookies between redirects" do
|
|
290
|
+
@redirect['Set-Cookie'] = 'foo=bar; name=value; HTTPOnly'
|
|
291
|
+
@request.perform
|
|
292
|
+
@request.options[:headers]['Cookie'].should match(/foo=bar/)
|
|
293
|
+
@request.options[:headers]['Cookie'].should match(/name=value/)
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
it 'should update cookies with rediects' do
|
|
297
|
+
@request.options[:headers] = {'Cookie'=> 'foo=bar;'}
|
|
298
|
+
@redirect['Set-Cookie'] = 'foo=tar;'
|
|
299
|
+
@request.perform
|
|
300
|
+
@request.options[:headers]['Cookie'].should match(/foo=tar/)
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
it 'should keep cookies between rediects' do
|
|
304
|
+
@request.options[:headers] = {'Cookie'=> 'keep=me'}
|
|
305
|
+
@redirect['Set-Cookie'] = 'foo=tar;'
|
|
306
|
+
@request.perform
|
|
307
|
+
@request.options[:headers]['Cookie'].should match(/keep=me/)
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
it 'should make resulting request a get request if it not already' do
|
|
311
|
+
@request.http_method = Net::HTTP::Delete
|
|
312
|
+
@request.perform.should == {"hash" => {"foo" => "bar"}}
|
|
313
|
+
@request.http_method.should == Net::HTTP::Get
|
|
314
|
+
end
|
|
176
315
|
end
|
|
177
316
|
|
|
178
317
|
describe "infinitely" do
|
data/spec/httparty_spec.rb
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'spec_helper')
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
class CustomParser
|
|
4
|
+
def self.parse(body)
|
|
5
|
+
return {:sexy => true}
|
|
6
|
+
end
|
|
7
|
+
end
|
|
2
8
|
|
|
3
9
|
describe HTTParty do
|
|
4
10
|
before(:each) do
|
|
@@ -6,6 +12,20 @@ describe HTTParty do
|
|
|
6
12
|
@klass.instance_eval { include HTTParty }
|
|
7
13
|
end
|
|
8
14
|
|
|
15
|
+
describe "AllowedFormats deprecated" do
|
|
16
|
+
before do
|
|
17
|
+
Kernel.stub(:warn)
|
|
18
|
+
end
|
|
19
|
+
it "warns with a deprecation message" do
|
|
20
|
+
Kernel.should_receive(:warn).with("Deprecated: Use HTTParty::Parser::SupportedFormats")
|
|
21
|
+
HTTParty::AllowedFormats
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "returns HTTPart::Parser::SupportedFormats" do
|
|
25
|
+
HTTParty::AllowedFormats.should == HTTParty::Parser::SupportedFormats
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
9
29
|
describe "base uri" do
|
|
10
30
|
before(:each) do
|
|
11
31
|
@klass.base_uri('api.foo.com/v1')
|
|
@@ -14,7 +34,7 @@ describe HTTParty do
|
|
|
14
34
|
it "should have reader" do
|
|
15
35
|
@klass.base_uri.should == 'http://api.foo.com/v1'
|
|
16
36
|
end
|
|
17
|
-
|
|
37
|
+
|
|
18
38
|
it 'should have writer' do
|
|
19
39
|
@klass.base_uri('http://api.foobar.com')
|
|
20
40
|
@klass.base_uri.should == 'http://api.foobar.com'
|
|
@@ -26,18 +46,18 @@ describe HTTParty do
|
|
|
26
46
|
uri.should == 'http://api.foobar.com'
|
|
27
47
|
end
|
|
28
48
|
end
|
|
29
|
-
|
|
49
|
+
|
|
30
50
|
describe "#normalize_base_uri" do
|
|
31
51
|
it "should add http if not present for non ssl requests" do
|
|
32
52
|
uri = HTTParty.normalize_base_uri('api.foobar.com')
|
|
33
53
|
uri.should == 'http://api.foobar.com'
|
|
34
54
|
end
|
|
35
|
-
|
|
55
|
+
|
|
36
56
|
it "should add https if not present for ssl requests" do
|
|
37
57
|
uri = HTTParty.normalize_base_uri('api.foo.com/v1:443')
|
|
38
58
|
uri.should == 'https://api.foo.com/v1:443'
|
|
39
59
|
end
|
|
40
|
-
|
|
60
|
+
|
|
41
61
|
it "should not remove https for ssl requests" do
|
|
42
62
|
uri = HTTParty.normalize_base_uri('https://api.foo.com/v1:443')
|
|
43
63
|
uri.should == 'https://api.foo.com/v1:443'
|
|
@@ -49,17 +69,55 @@ describe HTTParty do
|
|
|
49
69
|
uri.should == 'http://api.foobar.com'
|
|
50
70
|
end
|
|
51
71
|
end
|
|
52
|
-
|
|
72
|
+
|
|
53
73
|
describe "headers" do
|
|
74
|
+
def expect_headers(header={})
|
|
75
|
+
HTTParty::Request.should_receive(:new) \
|
|
76
|
+
.with(anything, anything, hash_including({ :headers => header })) \
|
|
77
|
+
.and_return(mock("mock response", :perform => nil))
|
|
78
|
+
end
|
|
79
|
+
|
|
54
80
|
it "should default to empty hash" do
|
|
55
81
|
@klass.headers.should == {}
|
|
56
82
|
end
|
|
57
|
-
|
|
83
|
+
|
|
58
84
|
it "should be able to be updated" do
|
|
59
85
|
init_headers = {:foo => 'bar', :baz => 'spax'}
|
|
60
86
|
@klass.headers init_headers
|
|
61
87
|
@klass.headers.should == init_headers
|
|
62
88
|
end
|
|
89
|
+
|
|
90
|
+
it "uses the class headers when sending a request" do
|
|
91
|
+
expect_headers(:foo => 'bar')
|
|
92
|
+
@klass.headers(:foo => 'bar')
|
|
93
|
+
@klass.get('')
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it "overwrites class headers when passing in headers" do
|
|
97
|
+
expect_headers(:baz => 'spax')
|
|
98
|
+
@klass.headers(:foo => 'bar')
|
|
99
|
+
@klass.get('', :headers => {:baz => 'spax'})
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context "with cookies" do
|
|
103
|
+
it 'utilizes the class-level cookies' do
|
|
104
|
+
expect_headers(:foo => 'bar', 'cookie' => 'type=snickerdoodle')
|
|
105
|
+
@klass.headers(:foo => 'bar')
|
|
106
|
+
@klass.cookies(:type => 'snickerdoodle')
|
|
107
|
+
@klass.get('')
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it 'adds cookies to the headers' do
|
|
111
|
+
expect_headers(:foo => 'bar', 'cookie' => 'type=snickerdoodle')
|
|
112
|
+
@klass.headers(:foo => 'bar')
|
|
113
|
+
@klass.get('', :cookies => {:type => 'snickerdoodle'})
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it 'adds optional cookies to the optional headers' do
|
|
117
|
+
expect_headers(:baz => 'spax', 'cookie' => 'type=snickerdoodle')
|
|
118
|
+
@klass.get('', :cookies => {:type => 'snickerdoodle'}, :headers => {:baz => 'spax'})
|
|
119
|
+
end
|
|
120
|
+
end
|
|
63
121
|
end
|
|
64
122
|
|
|
65
123
|
describe "cookies" do
|
|
@@ -96,6 +154,13 @@ describe HTTParty do
|
|
|
96
154
|
@klass.get("")
|
|
97
155
|
end
|
|
98
156
|
|
|
157
|
+
it "should pass the proper cookies when requested multiple times" do
|
|
158
|
+
2.times do
|
|
159
|
+
expect_cookie_header "type=snickerdoodle"
|
|
160
|
+
@klass.get("")
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
99
164
|
it "should allow the class defaults to be overridden" do
|
|
100
165
|
expect_cookie_header "type=chocolate_chip"
|
|
101
166
|
|
|
@@ -125,47 +190,82 @@ describe HTTParty do
|
|
|
125
190
|
end
|
|
126
191
|
end
|
|
127
192
|
end
|
|
128
|
-
|
|
193
|
+
|
|
129
194
|
describe "default params" do
|
|
130
195
|
it "should default to empty hash" do
|
|
131
196
|
@klass.default_params.should == {}
|
|
132
197
|
end
|
|
133
|
-
|
|
198
|
+
|
|
134
199
|
it "should be able to be updated" do
|
|
135
200
|
new_defaults = {:foo => 'bar', :baz => 'spax'}
|
|
136
201
|
@klass.default_params new_defaults
|
|
137
202
|
@klass.default_params.should == new_defaults
|
|
138
203
|
end
|
|
139
204
|
end
|
|
140
|
-
|
|
205
|
+
|
|
141
206
|
describe "basic http authentication" do
|
|
142
207
|
it "should work" do
|
|
143
208
|
@klass.basic_auth 'foobar', 'secret'
|
|
144
209
|
@klass.default_options[:basic_auth].should == {:username => 'foobar', :password => 'secret'}
|
|
145
210
|
end
|
|
146
211
|
end
|
|
147
|
-
|
|
212
|
+
|
|
213
|
+
describe "parser" do
|
|
214
|
+
let(:parser) do
|
|
215
|
+
Proc.new{ |data, format| CustomParser.parse(data) }
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
it "should set parser options" do
|
|
219
|
+
@klass.parser parser
|
|
220
|
+
@klass.default_options[:parser].should == parser
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
it "should be able parse response with custom parser" do
|
|
224
|
+
@klass.parser parser
|
|
225
|
+
FakeWeb.register_uri(:get, 'http://twitter.com/statuses/public_timeline.xml', :body => 'tweets')
|
|
226
|
+
custom_parsed_response = @klass.get('http://twitter.com/statuses/public_timeline.xml')
|
|
227
|
+
custom_parsed_response[:sexy].should == true
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
it "raises UnsupportedFormat when the parser cannot handle the format" do
|
|
231
|
+
@klass.format :json
|
|
232
|
+
class MyParser < HTTParty::Parser
|
|
233
|
+
SupportedFormats = {}
|
|
234
|
+
end
|
|
235
|
+
expect do
|
|
236
|
+
@klass.parser MyParser
|
|
237
|
+
end.to raise_error(HTTParty::UnsupportedFormat)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
it 'does not validate format whe custom parser is a proc' do
|
|
241
|
+
expect do
|
|
242
|
+
@klass.format :json
|
|
243
|
+
@klass.parser lambda {|body, format|}
|
|
244
|
+
end.to_not raise_error(HTTParty::UnsupportedFormat)
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
148
248
|
describe "format" do
|
|
149
249
|
it "should allow xml" do
|
|
150
250
|
@klass.format :xml
|
|
151
251
|
@klass.default_options[:format].should == :xml
|
|
152
252
|
end
|
|
153
|
-
|
|
253
|
+
|
|
154
254
|
it "should allow json" do
|
|
155
255
|
@klass.format :json
|
|
156
256
|
@klass.default_options[:format].should == :json
|
|
157
257
|
end
|
|
158
|
-
|
|
258
|
+
|
|
159
259
|
it "should allow yaml" do
|
|
160
260
|
@klass.format :yaml
|
|
161
261
|
@klass.default_options[:format].should == :yaml
|
|
162
262
|
end
|
|
163
|
-
|
|
263
|
+
|
|
164
264
|
it "should allow plain" do
|
|
165
265
|
@klass.format :plain
|
|
166
266
|
@klass.default_options[:format].should == :plain
|
|
167
267
|
end
|
|
168
|
-
|
|
268
|
+
|
|
169
269
|
it 'should not allow funky format' do
|
|
170
270
|
lambda do
|
|
171
271
|
@klass.format :foobar
|
|
@@ -175,9 +275,21 @@ describe HTTParty do
|
|
|
175
275
|
it 'should only print each format once with an exception' do
|
|
176
276
|
lambda do
|
|
177
277
|
@klass.format :foobar
|
|
178
|
-
end.should raise_error(HTTParty::UnsupportedFormat, "Must be one of: json, plain,
|
|
278
|
+
end.should raise_error(HTTParty::UnsupportedFormat, "':foobar' Must be one of: html, json, plain, xml, yaml")
|
|
179
279
|
end
|
|
180
280
|
|
|
281
|
+
it 'sets the default parser' do
|
|
282
|
+
@klass.default_options[:parser].should be_nil
|
|
283
|
+
@klass.format :json
|
|
284
|
+
@klass.default_options[:parser].should == HTTParty::Parser
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
it 'does not reset parser to the default parser' do
|
|
288
|
+
my_parser = lambda {}
|
|
289
|
+
@klass.parser my_parser
|
|
290
|
+
@klass.format :json
|
|
291
|
+
@klass.parser.should == my_parser
|
|
292
|
+
end
|
|
181
293
|
end
|
|
182
294
|
|
|
183
295
|
describe "with explicit override of automatic redirect handling" do
|
|
@@ -205,8 +317,20 @@ describe HTTParty do
|
|
|
205
317
|
@klass.put('/foo', :no_follow => true)
|
|
206
318
|
end.should raise_error(HTTParty::RedirectionTooDeep)
|
|
207
319
|
end
|
|
320
|
+
|
|
321
|
+
it "should fail with redirected HEAD" do
|
|
322
|
+
lambda do
|
|
323
|
+
@klass.head('/foo', :no_follow => true)
|
|
324
|
+
end.should raise_error(HTTParty::RedirectionTooDeep)
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
it "should fail with redirected OPTIONS" do
|
|
328
|
+
lambda do
|
|
329
|
+
@klass.options('/foo', :no_follow => true)
|
|
330
|
+
end.should raise_error(HTTParty::RedirectionTooDeep)
|
|
331
|
+
end
|
|
208
332
|
end
|
|
209
|
-
|
|
333
|
+
|
|
210
334
|
describe "with multiple class definitions" do
|
|
211
335
|
before(:each) do
|
|
212
336
|
@klass.instance_eval do
|
|
@@ -227,57 +351,104 @@ describe HTTParty do
|
|
|
227
351
|
@additional_klass.default_options.should == { :base_uri => 'http://second.com', :default_params => { :two => 2 } }
|
|
228
352
|
end
|
|
229
353
|
end
|
|
230
|
-
|
|
354
|
+
|
|
355
|
+
describe "two child classes inheriting from one parent" do
|
|
356
|
+
before(:each) do
|
|
357
|
+
@parent = Class.new do
|
|
358
|
+
include HTTParty
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
@child1 = Class.new(@parent)
|
|
362
|
+
@child2 = Class.new(@parent)
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
it "does not modify each others inherited attributes" do
|
|
366
|
+
@child1.default_params :joe => "alive"
|
|
367
|
+
@child2.default_params :joe => "dead"
|
|
368
|
+
|
|
369
|
+
@child1.default_options.should == { :default_params => {:joe => "alive"} }
|
|
370
|
+
@child2.default_options.should == { :default_params => {:joe => "dead"} }
|
|
371
|
+
|
|
372
|
+
@parent.default_options.should == { }
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
231
376
|
describe "#get" do
|
|
232
377
|
it "should be able to get html" do
|
|
233
378
|
stub_http_response_with('google.html')
|
|
234
379
|
HTTParty.get('http://www.google.com').should == file_fixture('google.html')
|
|
235
380
|
end
|
|
236
|
-
|
|
381
|
+
|
|
237
382
|
it "should be able parse response type json automatically" do
|
|
238
383
|
stub_http_response_with('twitter.json')
|
|
239
384
|
tweets = HTTParty.get('http://twitter.com/statuses/public_timeline.json')
|
|
240
385
|
tweets.size.should == 20
|
|
241
386
|
tweets.first['user'].should == {
|
|
242
|
-
"name" => "Pyk",
|
|
243
|
-
"url" => nil,
|
|
244
|
-
"id" => "7694602",
|
|
245
|
-
"description" => nil,
|
|
246
|
-
"protected" => false,
|
|
247
|
-
"screen_name" => "Pyk",
|
|
248
|
-
"followers_count" => 1,
|
|
249
|
-
"location" => "Opera Plaza, California",
|
|
387
|
+
"name" => "Pyk",
|
|
388
|
+
"url" => nil,
|
|
389
|
+
"id" => "7694602",
|
|
390
|
+
"description" => nil,
|
|
391
|
+
"protected" => false,
|
|
392
|
+
"screen_name" => "Pyk",
|
|
393
|
+
"followers_count" => 1,
|
|
394
|
+
"location" => "Opera Plaza, California",
|
|
250
395
|
"profile_image_url" => "http://static.twitter.com/images/default_profile_normal.png"
|
|
251
396
|
}
|
|
252
397
|
end
|
|
253
|
-
|
|
398
|
+
|
|
254
399
|
it "should be able parse response type xml automatically" do
|
|
255
400
|
stub_http_response_with('twitter.xml')
|
|
256
401
|
tweets = HTTParty.get('http://twitter.com/statuses/public_timeline.xml')
|
|
257
402
|
tweets['statuses'].size.should == 20
|
|
258
403
|
tweets['statuses'].first['user'].should == {
|
|
259
|
-
"name" => "Magic 8 Bot",
|
|
260
|
-
"url" => nil,
|
|
261
|
-
"id" => "17656026",
|
|
262
|
-
"description" => "ask me a question",
|
|
263
|
-
"protected" => "false",
|
|
264
|
-
"screen_name" => "magic8bot",
|
|
265
|
-
"followers_count" => "90",
|
|
266
|
-
"profile_image_url" => "http://s3.amazonaws.com/twitter_production/profile_images/65565851/8ball_large_normal.jpg",
|
|
404
|
+
"name" => "Magic 8 Bot",
|
|
405
|
+
"url" => nil,
|
|
406
|
+
"id" => "17656026",
|
|
407
|
+
"description" => "ask me a question",
|
|
408
|
+
"protected" => "false",
|
|
409
|
+
"screen_name" => "magic8bot",
|
|
410
|
+
"followers_count" => "90",
|
|
411
|
+
"profile_image_url" => "http://s3.amazonaws.com/twitter_production/profile_images/65565851/8ball_large_normal.jpg",
|
|
267
412
|
"location" => nil
|
|
268
413
|
}
|
|
269
414
|
end
|
|
270
|
-
|
|
415
|
+
|
|
271
416
|
it "should not get undefined method add_node for nil class for the following xml" do
|
|
272
417
|
stub_http_response_with('undefined_method_add_node_for_nil.xml')
|
|
273
418
|
result = HTTParty.get('http://foobar.com')
|
|
274
419
|
result.should == {"Entities"=>{"href"=>"https://s3-sandbox.parature.com/api/v1/5578/5633/Account", "results"=>"0", "total"=>"0", "page_size"=>"25", "page"=>"1"}}
|
|
275
420
|
end
|
|
276
|
-
|
|
421
|
+
|
|
277
422
|
it "should parse empty response fine" do
|
|
278
423
|
stub_http_response_with('empty.xml')
|
|
279
424
|
result = HTTParty.get('http://foobar.com')
|
|
280
|
-
result.should
|
|
425
|
+
result.should be_nil
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
it "should accept http URIs" do
|
|
429
|
+
stub_http_response_with('google.html')
|
|
430
|
+
lambda do
|
|
431
|
+
HTTParty.get('http://google.com')
|
|
432
|
+
end.should_not raise_error(HTTParty::UnsupportedURIScheme)
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
it "should accept https URIs" do
|
|
436
|
+
stub_http_response_with('google.html')
|
|
437
|
+
lambda do
|
|
438
|
+
HTTParty.get('https://google.com')
|
|
439
|
+
end.should_not raise_error(HTTParty::UnsupportedURIScheme)
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
it "should raise an ArgumentError on URIs that are not http or https" do
|
|
443
|
+
lambda do
|
|
444
|
+
HTTParty.get("file:///there_is_no_party_on/my/filesystem")
|
|
445
|
+
end.should raise_error(HTTParty::UnsupportedURIScheme)
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
it "should raise an InvalidURIError on URIs that can't be parsed at all" do
|
|
449
|
+
lambda do
|
|
450
|
+
HTTParty.get("It's the one that says 'Bad URI'")
|
|
451
|
+
end.should raise_error(URI::InvalidURIError)
|
|
281
452
|
end
|
|
282
453
|
end
|
|
283
454
|
end
|
data/spec/spec.opts
CHANGED
data/spec/spec_helper.rb
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
require 'rubygems'
|
|
2
|
-
gem 'rspec'
|
|
3
|
-
require 'spec'
|
|
4
1
|
require File.join(File.dirname(__FILE__), '..', 'lib', 'httparty')
|
|
2
|
+
gem 'rspec', '1.2.9'
|
|
3
|
+
gem 'fakeweb'
|
|
4
|
+
require 'spec/autorun'
|
|
5
|
+
require 'fakeweb'
|
|
6
|
+
|
|
7
|
+
FakeWeb.allow_net_connect = false
|
|
5
8
|
|
|
6
9
|
def file_fixture(filename)
|
|
7
10
|
open(File.join(File.dirname(__FILE__), 'fixtures', "#{filename.to_s}")).read
|
|
@@ -18,4 +21,4 @@ def stub_http_response_with(filename)
|
|
|
18
21
|
http_request.stub!(:perform_actual_request).and_return(response)
|
|
19
22
|
|
|
20
23
|
HTTParty::Request.should_receive(:new).and_return(http_request)
|
|
21
|
-
end
|
|
24
|
+
end
|