jcinnamond-httparty 0.4.5

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