dbalatero-httparty 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/History +131 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Manifest +47 -0
  4. data/README.rdoc +54 -0
  5. data/Rakefile +48 -0
  6. data/bin/httparty +98 -0
  7. data/cucumber.yml +1 -0
  8. data/examples/aaws.rb +32 -0
  9. data/examples/basic.rb +11 -0
  10. data/examples/delicious.rb +37 -0
  11. data/examples/google.rb +16 -0
  12. data/examples/rubyurl.rb +14 -0
  13. data/examples/twitter.rb +31 -0
  14. data/examples/whoismyrep.rb +10 -0
  15. data/features/basic_authentication.feature +20 -0
  16. data/features/command_line.feature +7 -0
  17. data/features/deals_with_http_error_codes.feature +26 -0
  18. data/features/handles_multiple_formats.feature +34 -0
  19. data/features/steps/env.rb +15 -0
  20. data/features/steps/httparty_response_steps.rb +26 -0
  21. data/features/steps/httparty_steps.rb +15 -0
  22. data/features/steps/mongrel_helper.rb +55 -0
  23. data/features/steps/remote_service_steps.rb +47 -0
  24. data/features/supports_redirection.feature +22 -0
  25. data/httparty.gemspec +40 -0
  26. data/lib/httparty.rb +242 -0
  27. data/lib/httparty/cookie_hash.rb +9 -0
  28. data/lib/httparty/core_extensions.rb +29 -0
  29. data/lib/httparty/exceptions.rb +7 -0
  30. data/lib/httparty/module_inheritable_attributes.rb +25 -0
  31. data/lib/httparty/request.rb +200 -0
  32. data/lib/httparty/response.rb +18 -0
  33. data/lib/httparty/version.rb +3 -0
  34. data/spec/fixtures/delicious.xml +23 -0
  35. data/spec/fixtures/empty.xml +0 -0
  36. data/spec/fixtures/google.html +3 -0
  37. data/spec/fixtures/twitter.json +1 -0
  38. data/spec/fixtures/twitter.xml +403 -0
  39. data/spec/fixtures/undefined_method_add_node_for_nil.xml +2 -0
  40. data/spec/httparty/cookie_hash_spec.rb +38 -0
  41. data/spec/httparty/request_spec.rb +247 -0
  42. data/spec/httparty/response_spec.rb +62 -0
  43. data/spec/httparty_spec.rb +289 -0
  44. data/spec/spec.opts +3 -0
  45. data/spec/spec_helper.rb +21 -0
  46. data/website/css/common.css +47 -0
  47. data/website/index.html +74 -0
  48. metadata +132 -0
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <Entities total="0" results="0" page="1" page-size="25" href="https://s3-sandbox.parature.com/api/v1/5578/5633/Account" />
@@ -0,0 +1,38 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../spec_helper'))
2
+
3
+ describe HTTParty::CookieHash do
4
+ before(:each) do
5
+ @cookie_hash = HTTParty::CookieHash.new
6
+ end
7
+
8
+ describe "#add_cookies" do
9
+ it "should add new key/value pairs to the hash" do
10
+ @cookie_hash.add_cookies(:foo => "bar")
11
+ @cookie_hash.add_cookies(:rofl => "copter")
12
+ @cookie_hash.length.should eql(2)
13
+ end
14
+
15
+ it "should overwrite any existing key" do
16
+ @cookie_hash.add_cookies(:foo => "bar")
17
+ @cookie_hash.add_cookies(:foo => "copter")
18
+ @cookie_hash.length.should eql(1)
19
+ @cookie_hash[:foo].should eql("copter")
20
+ end
21
+ end
22
+
23
+ # The regexen are required because Hashes aren't ordered, so a test against
24
+ # a hardcoded string was randomly failing.
25
+ describe "#to_cookie_string" do
26
+ before(:each) do
27
+ @cookie_hash.add_cookies(:foo => "bar")
28
+ @cookie_hash.add_cookies(:rofl => "copter")
29
+ @s = @cookie_hash.to_cookie_string
30
+ end
31
+
32
+ it "should format the key/value pairs, delimited by semi-colons" do
33
+ @s.should match(/foo=bar/)
34
+ @s.should match(/rofl=copter/)
35
+ @s.should match(/^\w+=\w+; \w+=\w+$/)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,247 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ module RequestStubbable
4
+ def stub_response(body, code = 200)
5
+ unless @http
6
+ @http = Net::HTTP.new('localhost', 80)
7
+ @request.stub!(:http).and_return(@http)
8
+ @request.stub!(:uri).and_return(URI.parse("http://foo.com/foobar"))
9
+ end
10
+
11
+ response = Net::HTTPResponse::CODE_TO_OBJ[code.to_s].new("1.1", code, body)
12
+ response.stub!(:body).and_return(body)
13
+
14
+ @http.stub!(:request).and_return(response)
15
+ response
16
+ end
17
+ end
18
+
19
+ describe HTTParty::Request do
20
+ include RequestStubbable
21
+
22
+ before do
23
+ @request = HTTParty::Request.new(Net::HTTP::Get, 'http://api.foo.com/v1', :format => :xml)
24
+ end
25
+
26
+ describe "#format" do
27
+ it "should return the correct parsing format" do
28
+ @request.format.should == :xml
29
+ end
30
+ end
31
+
32
+ describe 'http' do
33
+ it "should use ssl for port 443" do
34
+ request = HTTParty::Request.new(Net::HTTP::Get, 'https://api.foo.com/v1:443')
35
+ request.send(:http).use_ssl?.should == true
36
+ end
37
+
38
+ it 'should not use ssl for port 80' do
39
+ request = HTTParty::Request.new(Net::HTTP::Get, 'http://foobar.com')
40
+ request.send(:http).use_ssl?.should == false
41
+ end
42
+
43
+ it "should use ssl for https scheme" do
44
+ request = HTTParty::Request.new(Net::HTTP::Get, 'https://foobar.com')
45
+ request.send(:http).use_ssl?.should == true
46
+ end
47
+
48
+ it "should use basic auth when configured" do
49
+ @request.options[:basic_auth] = {:username => 'foobar', :password => 'secret'}
50
+ @request.send(:setup_raw_request)
51
+ @request.instance_variable_get(:@raw_request)['authorization'].should_not be_nil
52
+ end
53
+ end
54
+
55
+ describe '#format_from_mimetype' do
56
+ it 'should handle text/xml' do
57
+ ["text/xml", "text/xml; charset=iso8859-1"].each do |ct|
58
+ @request.send(:format_from_mimetype, ct).should == :xml
59
+ end
60
+ end
61
+
62
+ it 'should handle application/xml' do
63
+ ["application/xml", "application/xml; charset=iso8859-1"].each do |ct|
64
+ @request.send(:format_from_mimetype, ct).should == :xml
65
+ end
66
+ end
67
+
68
+ it 'should handle text/json' do
69
+ ["text/json", "text/json; charset=iso8859-1"].each do |ct|
70
+ @request.send(:format_from_mimetype, ct).should == :json
71
+ end
72
+ end
73
+
74
+ it 'should handle application/json' do
75
+ ["application/json", "application/json; charset=iso8859-1"].each do |ct|
76
+ @request.send(:format_from_mimetype, ct).should == :json
77
+ end
78
+ end
79
+
80
+ it 'should handle text/javascript' do
81
+ ["text/javascript", "text/javascript; charset=iso8859-1"].each do |ct|
82
+ @request.send(:format_from_mimetype, ct).should == :json
83
+ end
84
+ end
85
+
86
+ it 'should handle application/javascript' do
87
+ ["application/javascript", "application/javascript; charset=iso8859-1"].each do |ct|
88
+ @request.send(:format_from_mimetype, ct).should == :json
89
+ end
90
+ end
91
+ end
92
+
93
+ describe 'parsing responses' do
94
+ it 'should handle xml automatically' do
95
+ xml = %q[<books><book><id>1234</id><name>Foo Bar!</name></book></books>]
96
+ @request.options[:format] = :xml
97
+ @request.send(:parse_response, xml).should == {'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}}
98
+ end
99
+
100
+ it 'should handle json automatically' do
101
+ json = %q[{"books": {"book": {"name": "Foo Bar!", "id": "1234"}}}]
102
+ @request.options[:format] = :json
103
+ @request.send(:parse_response, json).should == {'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}}
104
+ end
105
+
106
+ it 'should handle yaml automatically' do
107
+ yaml = "books: \n book: \n name: Foo Bar!\n id: \"1234\"\n"
108
+ @request.options[:format] = :yaml
109
+ @request.send(:parse_response, yaml).should == {'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}}
110
+ end
111
+
112
+ it "should include any HTTP headers in the returned response" do
113
+ @request.options[:format] = :html
114
+ response = stub_response "Content"
115
+ response.initialize_http_header("key" => "value")
116
+
117
+ @request.perform.headers.should == { "key" => ["value"] }
118
+ end
119
+
120
+ describe 'with non-200 responses' do
121
+ it 'should return a valid object for 4xx response' do
122
+ stub_response '<foo><bar>yes</bar></foo>', 401
123
+ resp = @request.perform
124
+ resp.code.should == 401
125
+ resp.body.should == "<foo><bar>yes</bar></foo>"
126
+ resp['foo']['bar'].should == "yes"
127
+ end
128
+
129
+ it 'should return a valid object for 5xx response' do
130
+ stub_response '<foo><bar>error</bar></foo>', 500
131
+ resp = @request.perform
132
+ resp.code.should == 500
133
+ resp.body.should == "<foo><bar>error</bar></foo>"
134
+ resp['foo']['bar'].should == "error"
135
+ end
136
+ end
137
+ end
138
+
139
+ it "should not attempt to parse empty responses" do
140
+ stub_response "", 204
141
+
142
+ @request.options[:format] = :xml
143
+ @request.perform.should be_nil
144
+ end
145
+
146
+ it "should not fail for missing mime type" do
147
+ stub_response "Content for you"
148
+ @request.options[:format] = :html
149
+ @request.perform.should == 'Content for you'
150
+ end
151
+
152
+ describe "a request that redirects" do
153
+ before(:each) do
154
+ @redirect = stub_response("", 302)
155
+ @redirect['location'] = '/foo'
156
+
157
+ @ok = stub_response('<hash><foo>bar</foo></hash>', 200)
158
+ end
159
+
160
+ describe "once" do
161
+ before(:each) do
162
+ @http.stub!(:request).and_return(@redirect, @ok)
163
+ end
164
+
165
+ it "should be handled by GET transparently" do
166
+ @request.perform.should == {"hash" => {"foo" => "bar"}}
167
+ end
168
+
169
+ it "should be handled by POST transparently" do
170
+ @request.http_method = Net::HTTP::Post
171
+ @request.perform.should == {"hash" => {"foo" => "bar"}}
172
+ end
173
+
174
+ it "should be handled by DELETE transparently" do
175
+ @request.http_method = Net::HTTP::Delete
176
+ @request.perform.should == {"hash" => {"foo" => "bar"}}
177
+ end
178
+
179
+ it "should be handled by PUT transparently" do
180
+ @request.http_method = Net::HTTP::Put
181
+ @request.perform.should == {"hash" => {"foo" => "bar"}}
182
+ end
183
+ end
184
+
185
+ describe "infinitely" do
186
+ before(:each) do
187
+ @http.stub!(:request).and_return(@redirect)
188
+ end
189
+
190
+ it "should raise an exception" do
191
+ lambda { @request.perform }.should raise_error(HTTParty::RedirectionTooDeep)
192
+ end
193
+ end
194
+ end
195
+ end
196
+
197
+ describe HTTParty::Request, "with POST http method" do
198
+ it "should raise argument error if query is not a hash" do
199
+ lambda {
200
+ HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', :format => :xml, :query => 'astring').perform
201
+ }.should raise_error(ArgumentError)
202
+ end
203
+ end
204
+
205
+ describe HTTParty::Request, "with multipart http method" do
206
+ TEMP_FILE = "tmp_foo.txt"
207
+
208
+ def create_temp_file!
209
+ File.open(TEMP_FILE, "w") { |fp| fp << "testjlkdsjfkldkfds" }
210
+ end
211
+
212
+ def remove_temp_file!
213
+ File.delete(TEMP_FILE)
214
+ end
215
+
216
+ include RequestStubbable
217
+
218
+ [Net::HTTP::Post::Multipart, Net::HTTP::Put::Multipart].each do |klass|
219
+ it "should require at least one file to be attached with #{klass}" do
220
+ lambda {
221
+ request = HTTParty::Request.new(klass,
222
+ 'http://api.foo.com/v1',
223
+ :multipart => {})
224
+ request.perform
225
+ }.should raise_error(ArgumentError)
226
+ end
227
+
228
+ it "should allow multipart as a valid option with #{klass}" do
229
+ stub_response "Foo"
230
+
231
+ lambda {
232
+ create_temp_file!
233
+ request = HTTParty::Request.new(klass,
234
+ 'http://api.foo.com/v1',
235
+ :multipart => {
236
+ 'file' => {
237
+ :path => TEMP_FILE,
238
+ :type => 'text/plain'
239
+ }
240
+ })
241
+
242
+ request.perform
243
+ remove_temp_file!
244
+ }.should_not raise_error
245
+ end
246
+ end
247
+ end
@@ -0,0 +1,62 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe HTTParty::Response do
4
+ describe "initialization" do
5
+ before do
6
+ @response_object = {'foo' => 'bar'}
7
+ @body = "{foo:'bar'}"
8
+ @code = '200'
9
+ @message = 'OK'
10
+ @response = HTTParty::Response.new(@response_object, @body, @code, @message)
11
+ end
12
+
13
+ it "should set delegate" do
14
+ @response.delegate.should == @response_object
15
+ end
16
+
17
+ it "should set body" do
18
+ @response.body.should == @body
19
+ end
20
+
21
+ it "should set code" do
22
+ @response.code.should.to_s == @code
23
+ end
24
+
25
+ it "should set code as a Fixnum" do
26
+ @response.code.should be_an_instance_of(Fixnum)
27
+ end
28
+
29
+ it "should set body" do
30
+ @response.body.should == @body
31
+ end
32
+ end
33
+
34
+ it "should be able to set headers during initialization" do
35
+ response = HTTParty::Response.new({'foo' => 'bar'}, "{foo:'bar'}", 200, 'OK', {'foo' => 'bar'})
36
+ response.headers.should == {'foo' => 'bar'}
37
+ end
38
+
39
+ it "should send missing methods to delegate" do
40
+ response = HTTParty::Response.new({'foo' => 'bar'}, "{foo:'bar'}", 200, 'OK')
41
+ response['foo'].should == 'bar'
42
+ end
43
+
44
+ it "should be able to iterate delegate if it is array" do
45
+ response = HTTParty::Response.new([{'foo' => 'bar'}, {'foo' => 'baz'}], "[{foo:'bar'}, {foo:'baz'}]", 200, 'OK')
46
+ response.size.should == 2
47
+ lambda {
48
+ response.each { |item| }
49
+ }.should_not raise_error
50
+ end
51
+
52
+ xit "should allow hashes to be accessed with dot notation" do
53
+ response = HTTParty::Response.new({'foo' => 'bar'}, "{foo:'bar'}", 200, 'OK')
54
+ response.foo.should == 'bar'
55
+ end
56
+
57
+ xit "should allow nested hashes to be accessed with dot notation" do
58
+ response = HTTParty::Response.new({'foo' => {'bar' => 'baz'}}, "{foo: {bar:'baz'}}", 200, 'OK')
59
+ response.foo.should == {'bar' => 'baz'}
60
+ response.foo.bar.should == 'baz'
61
+ end
62
+ end
@@ -0,0 +1,289 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
+
3
+ describe HTTParty do
4
+ before(:each) do
5
+ @klass = Class.new
6
+ @klass.instance_eval { include HTTParty }
7
+ end
8
+
9
+ describe "base uri" do
10
+ before(:each) do
11
+ @klass.base_uri('api.foo.com/v1')
12
+ end
13
+
14
+ it "should have reader" do
15
+ @klass.base_uri.should == 'http://api.foo.com/v1'
16
+ end
17
+
18
+ it 'should have writer' do
19
+ @klass.base_uri('http://api.foobar.com')
20
+ @klass.base_uri.should == 'http://api.foobar.com'
21
+ end
22
+
23
+ it 'should not modify the parameter during assignment' do
24
+ uri = 'http://api.foobar.com'
25
+ @klass.base_uri(uri)
26
+ uri.should == 'http://api.foobar.com'
27
+ end
28
+ end
29
+
30
+ describe "#normalize_base_uri" do
31
+ it "should add http if not present for non ssl requests" do
32
+ uri = HTTParty.normalize_base_uri('api.foobar.com')
33
+ uri.should == 'http://api.foobar.com'
34
+ end
35
+
36
+ it "should add https if not present for ssl requests" do
37
+ uri = HTTParty.normalize_base_uri('api.foo.com/v1:443')
38
+ uri.should == 'https://api.foo.com/v1:443'
39
+ end
40
+
41
+ it "should not remove https for ssl requests" do
42
+ uri = HTTParty.normalize_base_uri('https://api.foo.com/v1:443')
43
+ uri.should == 'https://api.foo.com/v1:443'
44
+ end
45
+
46
+ it 'should not modify the parameter' do
47
+ uri = 'http://api.foobar.com'
48
+ HTTParty.normalize_base_uri(uri)
49
+ uri.should == 'http://api.foobar.com'
50
+ end
51
+ end
52
+
53
+ describe "headers" do
54
+ it "should default to empty hash" do
55
+ @klass.headers.should == {}
56
+ end
57
+
58
+ it "should be able to be updated" do
59
+ init_headers = {:foo => 'bar', :baz => 'spax'}
60
+ @klass.headers init_headers
61
+ @klass.headers.should == init_headers
62
+ end
63
+ end
64
+
65
+ describe "cookies" do
66
+ def expect_cookie_header(s)
67
+ HTTParty::Request.should_receive(:new) \
68
+ .with(anything, anything, hash_including({ :headers => { "cookie" => s } })) \
69
+ .and_return(mock("mock response", :perform => nil))
70
+ end
71
+
72
+ it "should not be in the headers by default" do
73
+ HTTParty::Request.stub!(:new).and_return(stub(nil, :perform => nil))
74
+ @klass.get("")
75
+ @klass.headers.keys.should_not include("cookie")
76
+ end
77
+
78
+ it "should raise an ArgumentError if passed a non-Hash" do
79
+ lambda do
80
+ @klass.cookies("nonsense")
81
+ end.should raise_error(ArgumentError)
82
+ end
83
+
84
+ it "should allow a cookie to be specified with a one-off request" do
85
+ expect_cookie_header "type=snickerdoodle"
86
+ @klass.get("", :cookies => { :type => "snickerdoodle" })
87
+ end
88
+
89
+ describe "when a cookie is set at the class level" do
90
+ before(:each) do
91
+ @klass.cookies({ :type => "snickerdoodle" })
92
+ end
93
+
94
+ it "should include that cookie in the request" do
95
+ expect_cookie_header "type=snickerdoodle"
96
+ @klass.get("")
97
+ end
98
+
99
+ it "should pass the proper cookies when requested multiple times" do
100
+ 2.times do
101
+ expect_cookie_header "type=snickerdoodle"
102
+ @klass.get("")
103
+ end
104
+ end
105
+
106
+ it "should allow the class defaults to be overridden" do
107
+ expect_cookie_header "type=chocolate_chip"
108
+
109
+ @klass.get("", :cookies => { :type => "chocolate_chip" })
110
+ end
111
+ end
112
+
113
+ describe "in a class with multiple methods that use different cookies" do
114
+ before(:each) do
115
+ @klass.instance_eval do
116
+ def first_method
117
+ get("first_method", :cookies => { :first_method_cookie => "foo" })
118
+ end
119
+
120
+ def second_method
121
+ get("second_method", :cookies => { :second_method_cookie => "foo" })
122
+ end
123
+ end
124
+ end
125
+
126
+ it "should not allow cookies used in one method to carry over into other methods" do
127
+ expect_cookie_header "first_method_cookie=foo"
128
+ @klass.first_method
129
+
130
+ expect_cookie_header "second_method_cookie=foo"
131
+ @klass.second_method
132
+ end
133
+ end
134
+ end
135
+
136
+ describe "default params" do
137
+ it "should default to empty hash" do
138
+ @klass.default_params.should == {}
139
+ end
140
+
141
+ it "should be able to be updated" do
142
+ new_defaults = {:foo => 'bar', :baz => 'spax'}
143
+ @klass.default_params new_defaults
144
+ @klass.default_params.should == new_defaults
145
+ end
146
+ end
147
+
148
+ describe "basic http authentication" do
149
+ it "should work" do
150
+ @klass.basic_auth 'foobar', 'secret'
151
+ @klass.default_options[:basic_auth].should == {:username => 'foobar', :password => 'secret'}
152
+ end
153
+ end
154
+
155
+ describe "format" do
156
+ it "should allow xml" do
157
+ @klass.format :xml
158
+ @klass.default_options[:format].should == :xml
159
+ end
160
+
161
+ it "should allow json" do
162
+ @klass.format :json
163
+ @klass.default_options[:format].should == :json
164
+ end
165
+
166
+ it "should allow yaml" do
167
+ @klass.format :yaml
168
+ @klass.default_options[:format].should == :yaml
169
+ end
170
+
171
+ it "should allow plain" do
172
+ @klass.format :plain
173
+ @klass.default_options[:format].should == :plain
174
+ end
175
+
176
+ it 'should not allow funky format' do
177
+ lambda do
178
+ @klass.format :foobar
179
+ end.should raise_error(HTTParty::UnsupportedFormat)
180
+ end
181
+
182
+ it 'should only print each format once with an exception' do
183
+ lambda do
184
+ @klass.format :foobar
185
+ end.should raise_error(HTTParty::UnsupportedFormat, "Must be one of: html, json, plain, xml, yaml")
186
+ end
187
+ end
188
+
189
+ describe "with explicit override of automatic redirect handling" do
190
+
191
+ it "should fail with redirected GET" do
192
+ lambda do
193
+ @klass.get('/foo', :no_follow => true)
194
+ end.should raise_error(HTTParty::RedirectionTooDeep)
195
+ end
196
+
197
+ it "should fail with redirected POST" do
198
+ lambda do
199
+ @klass.post('/foo', :no_follow => true)
200
+ end.should raise_error(HTTParty::RedirectionTooDeep)
201
+ end
202
+
203
+ it "should fail with redirected DELETE" do
204
+ lambda do
205
+ @klass.delete('/foo', :no_follow => true)
206
+ end.should raise_error(HTTParty::RedirectionTooDeep)
207
+ end
208
+
209
+ it "should fail with redirected PUT" do
210
+ lambda do
211
+ @klass.put('/foo', :no_follow => true)
212
+ end.should raise_error(HTTParty::RedirectionTooDeep)
213
+ end
214
+ end
215
+
216
+ describe "with multiple class definitions" do
217
+ before(:each) do
218
+ @klass.instance_eval do
219
+ base_uri "http://first.com"
220
+ default_params :one => 1
221
+ end
222
+
223
+ @additional_klass = Class.new
224
+ @additional_klass.instance_eval do
225
+ include HTTParty
226
+ base_uri "http://second.com"
227
+ default_params :two => 2
228
+ end
229
+ end
230
+
231
+ it "should not run over each others options" do
232
+ @klass.default_options.should == { :base_uri => 'http://first.com', :default_params => { :one => 1 } }
233
+ @additional_klass.default_options.should == { :base_uri => 'http://second.com', :default_params => { :two => 2 } }
234
+ end
235
+ end
236
+
237
+ describe "#get" do
238
+ it "should be able to get html" do
239
+ stub_http_response_with('google.html')
240
+ HTTParty.get('http://www.google.com').should == file_fixture('google.html')
241
+ end
242
+
243
+ it "should be able parse response type json automatically" do
244
+ stub_http_response_with('twitter.json')
245
+ tweets = HTTParty.get('http://twitter.com/statuses/public_timeline.json')
246
+ tweets.size.should == 20
247
+ tweets.first['user'].should == {
248
+ "name" => "Pyk",
249
+ "url" => nil,
250
+ "id" => "7694602",
251
+ "description" => nil,
252
+ "protected" => false,
253
+ "screen_name" => "Pyk",
254
+ "followers_count" => 1,
255
+ "location" => "Opera Plaza, California",
256
+ "profile_image_url" => "http://static.twitter.com/images/default_profile_normal.png"
257
+ }
258
+ end
259
+
260
+ it "should be able parse response type xml automatically" do
261
+ stub_http_response_with('twitter.xml')
262
+ tweets = HTTParty.get('http://twitter.com/statuses/public_timeline.xml')
263
+ tweets['statuses'].size.should == 20
264
+ tweets['statuses'].first['user'].should == {
265
+ "name" => "Magic 8 Bot",
266
+ "url" => nil,
267
+ "id" => "17656026",
268
+ "description" => "ask me a question",
269
+ "protected" => "false",
270
+ "screen_name" => "magic8bot",
271
+ "followers_count" => "90",
272
+ "profile_image_url" => "http://s3.amazonaws.com/twitter_production/profile_images/65565851/8ball_large_normal.jpg",
273
+ "location" => nil
274
+ }
275
+ end
276
+
277
+ it "should not get undefined method add_node for nil class for the following xml" do
278
+ stub_http_response_with('undefined_method_add_node_for_nil.xml')
279
+ result = HTTParty.get('http://foobar.com')
280
+ result.should == {"Entities"=>{"href"=>"https://s3-sandbox.parature.com/api/v1/5578/5633/Account", "results"=>"0", "total"=>"0", "page_size"=>"25", "page"=>"1"}}
281
+ end
282
+
283
+ it "should parse empty response fine" do
284
+ stub_http_response_with('empty.xml')
285
+ result = HTTParty.get('http://foobar.com')
286
+ result.should == nil
287
+ end
288
+ end
289
+ end