luigi-httparty 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) 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 +110 -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/parsers.rb +31 -0
  35. data/lib/httparty/request.rb +175 -0
  36. data/lib/httparty/response.rb +23 -0
  37. data/lib/httparty/version.rb +3 -0
  38. data/spec/fixtures/delicious.xml +23 -0
  39. data/spec/fixtures/empty.xml +0 -0
  40. data/spec/fixtures/google.html +3 -0
  41. data/spec/fixtures/twitter.json +1 -0
  42. data/spec/fixtures/twitter.xml +403 -0
  43. data/spec/fixtures/undefined_method_add_node_for_nil.xml +2 -0
  44. data/spec/httparty/cookie_hash_spec.rb +71 -0
  45. data/spec/httparty/request_spec.rb +244 -0
  46. data/spec/httparty/response_spec.rb +68 -0
  47. data/spec/httparty_spec.rb +328 -0
  48. data/spec/spec.opts +2 -0
  49. data/spec/spec_helper.rb +24 -0
  50. data/website/css/common.css +47 -0
  51. data/website/index.html +73 -0
  52. metadata +136 -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,244 @@
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 "#format" do
23
+ it "should return the correct parsing format" do
24
+ @request.format.should == :xml
25
+ end
26
+ end
27
+
28
+ describe 'http' do
29
+ it "should use ssl for port 443" do
30
+ request = HTTParty::Request.new(Net::HTTP::Get, 'https://api.foo.com/v1:443')
31
+ request.send(:http).use_ssl?.should == true
32
+ end
33
+
34
+ it 'should not use ssl for port 80' do
35
+ request = HTTParty::Request.new(Net::HTTP::Get, 'http://foobar.com')
36
+ request.send(:http).use_ssl?.should == false
37
+ end
38
+
39
+ it "should use ssl for https scheme" do
40
+ request = HTTParty::Request.new(Net::HTTP::Get, 'https://foobar.com')
41
+ request.send(:http).use_ssl?.should == true
42
+ end
43
+
44
+ it "should use basic auth when configured" do
45
+ @request.options[:basic_auth] = {:username => 'foobar', :password => 'secret'}
46
+ @request.send(:setup_raw_request)
47
+ @request.instance_variable_get(:@raw_request)['authorization'].should_not be_nil
48
+ end
49
+
50
+ context "when setting timeout" do
51
+ it "does nothing if the timeout option is a string" do
52
+ http = mock("http", :null_object => true)
53
+ http.should_not_receive(:open_timeout=)
54
+ http.should_not_receive(:read_timeout=)
55
+ Net::HTTP.stub(:new => http)
56
+
57
+ request = HTTParty::Request.new(Net::HTTP::Get, 'https://foobar.com', {:timeout => "five seconds"})
58
+ request.send(:http)
59
+ end
60
+
61
+ it "sets the timeout to 5 seconds" do
62
+ @request.options[:timeout] = 5
63
+ @request.send(:http).open_timeout.should == 5
64
+ @request.send(:http).read_timeout.should == 5
65
+ end
66
+ end
67
+ end
68
+
69
+ describe '#format_from_mimetype' do
70
+ it 'should handle text/xml' do
71
+ ["text/xml", "text/xml; charset=iso8859-1"].each do |ct|
72
+ @request.send(:format_from_mimetype, ct).should == :xml
73
+ end
74
+ end
75
+
76
+ it 'should handle application/xml' do
77
+ ["application/xml", "application/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 text/json' do
83
+ ["text/json", "text/json; charset=iso8859-1"].each do |ct|
84
+ @request.send(:format_from_mimetype, ct).should == :json
85
+ end
86
+ end
87
+
88
+ it 'should handle application/json' do
89
+ ["application/json", "application/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 text/javascript' do
95
+ ["text/javascript", "text/javascript; charset=iso8859-1"].each do |ct|
96
+ @request.send(:format_from_mimetype, ct).should == :json
97
+ end
98
+ end
99
+
100
+ it 'should handle application/javascript' do
101
+ ["application/javascript", "application/javascript; charset=iso8859-1"].each do |ct|
102
+ @request.send(:format_from_mimetype, ct).should == :json
103
+ end
104
+ end
105
+ end
106
+
107
+ describe 'parsing responses' do
108
+ it 'should handle xml automatically' do
109
+ xml = %q[<books><book><id>1234</id><name>Foo Bar!</name></book></books>]
110
+ @request.options[:format] = :xml
111
+ @request.send(:parse_response, xml).should == {'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}}
112
+ end
113
+
114
+ it 'should handle json automatically' do
115
+ json = %q[{"books": {"book": {"name": "Foo Bar!", "id": "1234"}}}]
116
+ @request.options[:format] = :json
117
+ @request.send(:parse_response, json).should == {'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}}
118
+ end
119
+
120
+ it 'should handle yaml automatically' do
121
+ yaml = "books: \n book: \n name: Foo Bar!\n id: \"1234\"\n"
122
+ @request.options[:format] = :yaml
123
+ @request.send(:parse_response, yaml).should == {'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}}
124
+ end
125
+
126
+ it "should include any HTTP headers in the returned response" do
127
+ @request.options[:format] = :html
128
+ response = stub_response "Content"
129
+ response.initialize_http_header("key" => "value")
130
+
131
+ @request.perform.headers.should == { "key" => ["value"] }
132
+ end
133
+
134
+ describe 'with non-200 responses' do
135
+ it 'should return a valid object for 4xx response' do
136
+ stub_response '<foo><bar>yes</bar></foo>', 401
137
+ resp = @request.perform
138
+ resp.code.should == 401
139
+ resp.body.should == "<foo><bar>yes</bar></foo>"
140
+ resp['foo']['bar'].should == "yes"
141
+ end
142
+
143
+ it 'should return a valid object for 5xx response' do
144
+ stub_response '<foo><bar>error</bar></foo>', 500
145
+ resp = @request.perform
146
+ resp.code.should == 500
147
+ resp.body.should == "<foo><bar>error</bar></foo>"
148
+ resp['foo']['bar'].should == "error"
149
+ end
150
+ end
151
+ end
152
+
153
+ it "should not attempt to parse empty responses" do
154
+ stub_response "", 204
155
+
156
+ @request.options[:format] = :xml
157
+ @request.perform.should be_nil
158
+ end
159
+
160
+ it "should not fail for missing mime type" do
161
+ stub_response "Content for you"
162
+ @request.options[:format] = :html
163
+ @request.perform.should == 'Content for you'
164
+ end
165
+
166
+ describe "a request that redirects" do
167
+ before(:each) do
168
+ @redirect = stub_response("", 302)
169
+ @redirect['location'] = '/foo'
170
+
171
+ @ok = stub_response('<hash><foo>bar</foo></hash>', 200)
172
+ end
173
+
174
+ describe "once" do
175
+ before(:each) do
176
+ @http.stub!(:request).and_return(@redirect, @ok)
177
+ end
178
+
179
+ it "should be handled by GET transparently" do
180
+ @request.perform.should == {"hash" => {"foo" => "bar"}}
181
+ end
182
+
183
+ it "should be handled by POST transparently" do
184
+ @request.http_method = Net::HTTP::Post
185
+ @request.perform.should == {"hash" => {"foo" => "bar"}}
186
+ end
187
+
188
+ it "should be handled by DELETE transparently" do
189
+ @request.http_method = Net::HTTP::Delete
190
+ @request.perform.should == {"hash" => {"foo" => "bar"}}
191
+ end
192
+
193
+ it "should be handled by PUT transparently" do
194
+ @request.http_method = Net::HTTP::Put
195
+ @request.perform.should == {"hash" => {"foo" => "bar"}}
196
+ end
197
+
198
+ it "should keep track of cookies between redirects" do
199
+ @redirect['Set-Cookie'] = 'foo=bar; name=value; HTTPOnly'
200
+ @request.perform
201
+ @request.options[:headers]['Cookie'].should match(/foo=bar/)
202
+ @request.options[:headers]['Cookie'].should match(/name=value/)
203
+ end
204
+
205
+ it 'should update cookies with rediects' do
206
+ @request.options[:headers] = {'Cookie'=> 'foo=bar;'}
207
+ @redirect['Set-Cookie'] = 'foo=tar;'
208
+ @request.perform
209
+ @request.options[:headers]['Cookie'].should match(/foo=tar/)
210
+ end
211
+
212
+ it 'should keep cookies between rediects' do
213
+ @request.options[:headers] = {'Cookie'=> 'keep=me'}
214
+ @redirect['Set-Cookie'] = 'foo=tar;'
215
+ @request.perform
216
+ @request.options[:headers]['Cookie'].should match(/keep=me/)
217
+ end
218
+
219
+ it 'should make resulting request a get request if it not already' do
220
+ @request.http_method = Net::HTTP::Delete
221
+ @request.perform.should == {"hash" => {"foo" => "bar"}}
222
+ @request.http_method.should == Net::HTTP::Get
223
+ end
224
+ end
225
+
226
+ describe "infinitely" do
227
+ before(:each) do
228
+ @http.stub!(:request).and_return(@redirect)
229
+ end
230
+
231
+ it "should raise an exception" do
232
+ lambda { @request.perform }.should raise_error(HTTParty::RedirectionTooDeep)
233
+ end
234
+ end
235
+ end
236
+ end
237
+
238
+ describe HTTParty::Request, "with POST http method" do
239
+ it "should raise argument error if query is not a hash" do
240
+ lambda {
241
+ HTTParty::Request.new(Net::HTTP::Post, 'http://api.foo.com/v1', :format => :xml, :query => 'astring').perform
242
+ }.should raise_error(ArgumentError)
243
+ end
244
+ end
@@ -0,0 +1,68 @@
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
+
33
+ it "should inflect its body, code, and message" do
34
+ [:body, :code, :message].each do |method|
35
+ @response.respond_to?(method).should be true
36
+ end
37
+ end
38
+ end
39
+
40
+ it "should be able to set headers during initialization" do
41
+ response = HTTParty::Response.new({'foo' => 'bar'}, "{foo:'bar'}", 200, 'OK', {'foo' => 'bar'})
42
+ response.headers.should == {'foo' => 'bar'}
43
+ end
44
+
45
+ it "should send missing methods to delegate" do
46
+ response = HTTParty::Response.new({'foo' => 'bar'}, "{foo:'bar'}", 200, 'OK')
47
+ response['foo'].should == 'bar'
48
+ end
49
+
50
+ it "should be able to iterate delegate if it is array" do
51
+ response = HTTParty::Response.new([{'foo' => 'bar'}, {'foo' => 'baz'}], "[{foo:'bar'}, {foo:'baz'}]", 200, 'OK')
52
+ response.size.should == 2
53
+ lambda {
54
+ response.each { |item| }
55
+ }.should_not raise_error
56
+ end
57
+
58
+ xit "should allow hashes to be accessed with dot notation" do
59
+ response = HTTParty::Response.new({'foo' => 'bar'}, "{foo:'bar'}", 200, 'OK')
60
+ response.foo.should == 'bar'
61
+ end
62
+
63
+ xit "should allow nested hashes to be accessed with dot notation" do
64
+ response = HTTParty::Response.new({'foo' => {'bar' => 'baz'}}, "{foo: {bar:'baz'}}", 200, 'OK')
65
+ response.foo.should == {'bar' => 'baz'}
66
+ response.foo.bar.should == 'baz'
67
+ end
68
+ 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