curb-fu 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,179 @@
1
+ module CurbFu
2
+ module Response
3
+ class Base
4
+ attr_accessor :status, :body, :headers
5
+
6
+ def initialize(status, headers, body)
7
+ @status = status
8
+ set_response_type(status)
9
+ @body = body
10
+ @headers = headers.is_a?(String) ? parse_headers(headers) : headers
11
+ end
12
+
13
+ def success?
14
+ self.is_a?(CurbFu::Response::Success)
15
+ end
16
+
17
+ def redirect?
18
+ self.is_a?(CurbFu::Response::Redirection)
19
+ end
20
+
21
+ def failure?
22
+ !(success? || redirect?)
23
+ end
24
+
25
+ def server_fail?
26
+ self.is_a?(CurbFu::Response::ServerError)
27
+ end
28
+
29
+ def client_fail?
30
+ self.is_a?(CurbFu::Response::ClientError)
31
+ end
32
+
33
+ def parse_headers(header_string)
34
+ header_lines = header_string.split($/)
35
+ header_lines.shift
36
+ header_lines.inject({}) do |hsh, line|
37
+ whole_enchillada, key, value = /^(.*?):\s*(.*)$/.match(line.chomp).to_a
38
+ hsh[key] = value unless whole_enchillada.nil?
39
+ hsh
40
+ end
41
+ end
42
+
43
+ def to_hash
44
+ { :status => status, :body => body, :headers => headers }
45
+ end
46
+
47
+ def set_response_type(status)
48
+ case status
49
+ when 100..199 then
50
+ self.extend CurbFu::Response::Information
51
+ case self.status
52
+ when 101 then self.extend CurbFu::Response::Continue
53
+ when 102 then self.extend CurbFu::Response::SwitchProtocl
54
+ end
55
+ when 200..299 then
56
+ self.extend CurbFu::Response::Success
57
+ case self.status
58
+ when 200 then self.extend CurbFu::Response::OK
59
+ when 201 then self.extend CurbFu::Response::Created
60
+ when 202 then self.extend CurbFu::Response::Accepted
61
+ when 203 then self.extend CurbFu::Response::NonAuthoritativeInformation
62
+ when 204 then self.extend CurbFu::Response::NoContent
63
+ when 205 then self.extend CurbFu::Response::ResetContent
64
+ when 206 then self.extend CurbFu::Response::PartialContent
65
+ end
66
+ when 300..399 then
67
+ self.extend CurbFu::Response::Redirection
68
+ case self.status
69
+ when 300 then self.extend CurbFu::Response::MultipleChoice
70
+ when 301 then self.extend CurbFu::Response::MovedPermanently
71
+ when 302 then self.extend CurbFu::Response::Found
72
+ when 303 then self.extend CurbFu::Response::SeeOther
73
+ when 304 then self.extend CurbFu::Response::NotModified
74
+ when 305 then self.extend CurbFu::Response::UseProxy
75
+ when 307 then self.extend CurbFu::Response::TemporaryRedirect
76
+ end
77
+ when 400..499 then
78
+ self.extend CurbFu::Response::ClientError
79
+ case self.status
80
+ when 400 then self.extend CurbFu::Response::BadRequest
81
+ when 401 then self.extend CurbFu::Response::Unauthorized
82
+ when 402 then self.extend CurbFu::Response::PaymentRequired
83
+ when 403 then self.extend CurbFu::Response::Forbidden
84
+ when 404 then self.extend CurbFu::Response::NotFound
85
+ when 405 then self.extend CurbFu::Response::MethodNotAllowed
86
+ when 406 then self.extend CurbFu::Response::NotAcceptable
87
+ when 407 then self.extend CurbFu::Response::ProxyAuthenticationRequired
88
+ when 408 then self.extend CurbFu::Response::RequestTimeOut
89
+ when 409 then self.extend CurbFu::Response::Conflict
90
+ when 410 then self.extend CurbFu::Response::Gone
91
+ when 411 then self.extend CurbFu::Response::LengthRequired
92
+ when 412 then self.extend CurbFu::Response::PreconditionFailed
93
+ when 413 then self.extend CurbFu::Response::RequestEntityTooLarge
94
+ when 414 then self.extend CurbFu::Response::RequestURITooLong
95
+ when 415 then self.extend CurbFu::Response::UnsupportedMediaType
96
+ when 416 then self.extend CurbFu::Response::UnsupportedMediaType
97
+ when 417 then self.extend CurbFu::Response::ExpectationFailed
98
+ end
99
+ when 500..599 then
100
+ self.extend CurbFu::Response::ServerError
101
+ case self.status
102
+ when 500 then self.extend CurbFu::Response::InternalServerError
103
+ when 501 then self.extend CurbFu::Response::NotImplemented
104
+ when 502 then self.extend CurbFu::Response::BadGateway
105
+ when 503 then self.extend CurbFu::Response::ServiceUnavailable
106
+ when 504 then self.extend CurbFu::Response::GatewayTimeOut
107
+ when 505 then self.extend CurbFu::Response::VersionNotSupported
108
+ end
109
+ else
110
+ self.extend CurbFu::Response::UnknownResponse
111
+ end
112
+ end
113
+
114
+ class << self
115
+ def from_rack_response(rack)
116
+ raise ArgumentError.new("Rack response may not be nil") if rack.nil?
117
+ response = self.new(rack.status, rack.headers, rack.body)
118
+ end
119
+
120
+ def from_curb_response(curb)
121
+ response = self.new(curb.response_code, curb.header_str, curb.body_str)
122
+ response
123
+ end
124
+
125
+ def from_hash(hash)
126
+ return nil if hash.nil?
127
+ self.new(hash[:status], hash[:headers], hash[:body])
128
+ end
129
+ end
130
+ end
131
+
132
+ module Information; end
133
+ module Continue; def self.to_i; 100; end; end
134
+ module SwitchProtocl; end
135
+ module Success; def self.to_i; 200; end; end
136
+ module OK; def self.to_i; 200; end; end
137
+ module Created; def self.to_i; 201; end; end
138
+ module Accepted; def self.to_i; 202; end; end
139
+ module NonAuthoritativeInformation; end
140
+ module NoContent; end
141
+ module ResetContent; end
142
+ module PartialContent; end
143
+ module Redirection; end # 3xx
144
+ module MultipleChoice; end # 300
145
+ module MovedPermanently; end # 301
146
+ module Found; def self.to_i; 302; end; end
147
+ module SeeOther; end # 303
148
+ module NotModified; end # 304
149
+ module UseProxy; end # 305
150
+ module TemporaryRedirect; end # 307
151
+ module ClientError; end # 4xx
152
+ module BadRequest; end # 400
153
+ module Unauthorized; end # 401
154
+ module PaymentRequired; end # 402
155
+ module Forbidden; end # 403
156
+ module NotFound; def self.to_i; 404; end; end
157
+ module MethodNotAllowed; end # 405
158
+ module NotAcceptable; end # 406
159
+ module ProxyAuthenticationRequired; end # 407
160
+ module RequestTimeOut; end # 408
161
+ module Conflict; end # 409
162
+ module Gone; def self.to_i; 410; end; end
163
+ module LengthRequired; end # 411
164
+ module PreconditionFailed; end # 412
165
+ module RequestEntityTooLarge; end # 413
166
+ module RequestURITooLong; end # 414
167
+ module UnsupportedMediaType; end # 415
168
+ module RequestedRangeNotSatisfiable; end # 416
169
+ module ExpectationFailed; end # 417
170
+ module ServerError; end # 5xx
171
+ module InternalServerError; def self.to_i; 500; end; end
172
+ module NotImplemented; end # 501
173
+ module BadGateway; end # 502
174
+ module ServiceUnavailable; def self.to_i; 503; end; end
175
+ module GatewayTimeOut; end # 504
176
+ module VersionNotSupported; end # 505
177
+ module UnknownResponse; end
178
+ end
179
+ end
@@ -0,0 +1,6 @@
1
+ require 'curb-fu/test/server'
2
+ require 'curb-fu/test/request_logger'
3
+
4
+ module CurbFu
5
+ module Test; end
6
+ end
@@ -0,0 +1,31 @@
1
+ module CurbFu
2
+ module Test
3
+ class RequestLogger
4
+ class << self
5
+ def entries(host)
6
+ @entries ||= {}
7
+ @entries[host] ||= []
8
+ end
9
+
10
+ def log(env)
11
+ req = Rack::Request.new(env)
12
+ url = env['PATH_INFO']
13
+ post_params = req.POST
14
+ host = env['HTTP_HOST'] || env['SERVER_NAME']
15
+ entries(host) << { :url => url, :params => post_params }
16
+ end
17
+ def requested?(host, url, params = nil)
18
+ url_found = (url.is_a?(String)) ?
19
+ !entries(host).find { |entry| entry[:url] == url }.nil? :
20
+ !entries(host).find { |entry| entry[:url] =~ url }.nil?
21
+ if params.nil?
22
+ return url_found
23
+ else
24
+ params_found = !entries(host).find { |entry| entry[:params] == params }.nil?
25
+ url_found && params_found
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ require 'rack'
2
+
3
+ module CurbFu
4
+ module Test
5
+ class Server
6
+ def self.serve(&blk)
7
+ Rack::Builder.app do
8
+ run lambda { |env|
9
+ CurbFu::Test::RequestLogger.log(env)
10
+ yield(env)
11
+ }
12
+ end
13
+ end
14
+
15
+ def self.error!(message)
16
+ puts message
17
+ raise StandardError, message
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1 @@
1
+ asdf
@@ -0,0 +1,100 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+ require 'curb-fu/core_ext'
3
+
4
+ describe "module inclusion" do
5
+ it "should include appropriate InstanceMethods" do
6
+ class Tester
7
+ include CurbFu::ObjectExtensions
8
+ end
9
+
10
+ Tester.new.should respond_to(:to_param)
11
+ end
12
+ it "should not overwrite a pre-existing method named :to_param" do
13
+ class TesterWithToParam
14
+ def to_param
15
+ "hooray, to_param!"
16
+ end
17
+ end
18
+
19
+ TesterWithToParam.send(:include, CurbFu::ObjectExtensions)
20
+ TesterWithToParam.new.to_param.should == "hooray, to_param!"
21
+ end
22
+ it "should not overwrite the pre-existing method even if it comes from a module" do
23
+ module ActsLikeRails
24
+ def to_param
25
+ "foo"
26
+ end
27
+ end
28
+ class TesterWithModule
29
+ include ActsLikeRails
30
+ end
31
+ TesterWithModule.send(:include, CurbFu::ObjectExtensions)
32
+ TesterWithModule.new.to_param.should == "foo"
33
+ end
34
+ end
35
+
36
+ describe String do
37
+ it "should respond_to #to_param" do
38
+ "".should respond_to(:to_param)
39
+ end
40
+ describe "to_param" do
41
+ it "should return itself as the value for the passed-in name" do
42
+ "foo".to_param("quux").should == "quux=foo"
43
+ end
44
+ it "should be CGI escaped" do
45
+ "Whee, some 'unsafe' uri things".to_param("safe").should == "safe=Whee%2C+some+%27unsafe%27+uri+things"
46
+ end
47
+ end
48
+ end
49
+
50
+ describe Hash do
51
+ it "should respond to #to_param" do
52
+ {}.should respond_to(:to_param)
53
+ end
54
+ describe "to_param" do
55
+ it "should collect its keys and values into parameter pairs, prepending the provided prefix" do
56
+ {
57
+ "kraplach" => "messy",
58
+ "zebot" => 2003
59
+ }.to_param("things").should == "things[kraplach]=messy&things[zebot]=2003"
60
+ end
61
+ it "should handle having an array as one of its parameters" do
62
+ result = {
63
+ "vielleicht" => "perhaps",
64
+ "ratings" => [5, 3, 5, 2, 4]
65
+ }.to_param("things")
66
+ result.split('&').size.should == 6
67
+ result.should =~ /things\[vielleicht\]=perhaps/
68
+ result.should =~ /things\[ratings\]\[\]=5/
69
+ result.should =~ /things\[ratings\]\[\]=3/
70
+ result.should =~ /things\[ratings\]\[\]=5/
71
+ result.should =~ /things\[ratings\]\[\]=2/
72
+ result.should =~ /things\[ratings\]\[\]=4/
73
+ end
74
+ end
75
+ end
76
+
77
+ describe Array do
78
+ it "should respond_to #to_param" do
79
+ [].should respond_to(:to_param)
80
+ end
81
+ describe "to_param" do
82
+ it "should join each element, prepending a provided key prefix" do
83
+ [1, 23, 5].to_param("magic_numbers").should == ["magic_numbers[]=1", "magic_numbers[]=23", "magic_numbers[]=5"].join("&")
84
+ end
85
+ it "should call to_param on each element, too" do
86
+ [1, 23, {"barkley" => 5}].to_param("magic_numbers").should == "magic_numbers[]=1&magic_numbers[]=23&magic_numbers[][barkley]=5"
87
+ end
88
+ end
89
+ end
90
+
91
+ describe Integer do
92
+ it "should respond_to #to_param" do
93
+ 1.should respond_to(:to_param)
94
+ end
95
+ describe "to_param" do
96
+ it "should return a stringified version of itself, using the provided key" do
97
+ 5.to_param("fixnum").should == "fixnum=5"
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,37 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe "CurbFu::Entity" do
4
+ before(:each) do
5
+ @entity = CurbFu::Entity.new
6
+ @entity.data = {
7
+ :zoltan => "Space Emperor!",
8
+ "em-dashes" => "more space=good"
9
+ }
10
+ end
11
+
12
+ describe "to_request_data" do
13
+ it "should be able to convert parameters into json" do
14
+ @entity.content_type = :json
15
+
16
+ JSON.parse(@entity.to_request_data).should include("zoltan" => "Space Emperor!", "em-dashes" => "more space=good")
17
+ end
18
+ it "should be able to convert parameters into 'XML'" do
19
+ pending "We need to choose an xml library"
20
+
21
+ @entity.content_type = "application/xml"
22
+
23
+ @entity.to_request_data.should == "XML"
24
+ end
25
+ it "should be able to convert parameters into form_url_encoding" do
26
+ @entity.content_type = :form
27
+
28
+ @entity.to_request_data.split('&').sort.should == ["em-dashes=more+space%3Dgood","zoltan=Space+Emperor%21"]
29
+ end
30
+ it "should not attempt to coerce plain text into the requested format" do
31
+ @entity.content_type = :json
32
+ @entity.data = "{\"my_own\": \"data\"}"
33
+
34
+ @entity.to_request_data.should == "{\"my_own\": \"data\"}"
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,240 @@
1
+ require File.dirname(__FILE__) + '/../../../spec_helper'
2
+ require 'curb'
3
+
4
+ def regex_for_url_with_params(url, *params)
5
+ regex = '^' + url.gsub('/','\/').gsub('.','\.')
6
+ regex += '\?' unless params.empty?
7
+
8
+ unless params.empty?
9
+ param_possibilities = params.join('|')
10
+ regex += params.inject([]) { |list, param| list << "(#{param_possibilities})" }.join('&')
11
+ end
12
+ regex += '$'
13
+ Regexp.new(regex)
14
+ end
15
+
16
+ class TestHarness
17
+ extend CurbFu::Request::Base
18
+
19
+ def self.create_post_fields(*args) # testing interface to private method #create_post_fields
20
+ super(*args)
21
+ end
22
+
23
+ def self.create_put_fields(*args) # testing interface to private method #create_put_fields
24
+ super(*args)
25
+ end
26
+ end
27
+
28
+ describe CurbFu::Request::Base do
29
+ describe "build_url" do
30
+ it "should return a string if a string parameter is given" do
31
+ TestHarness.build_url("http://www.cliffsofinsanity.com").should == "http://www.cliffsofinsanity.com"
32
+ end
33
+ it "should return a built url with just a hostname if only the hostname is given" do
34
+ TestHarness.build_url(:host => "poisonedwine.com").should == "http://poisonedwine.com"
35
+ end
36
+ it "should return a built url with hostname and port if port is also given" do
37
+ TestHarness.build_url(:host => "www2.giantthrowingrocks.com", :port => 8080).
38
+ should == "http://www2.giantthrowingrocks.com:8080"
39
+ end
40
+ it "should return a built url with hostname, port, and path if all are given" do
41
+ TestHarness.build_url(:host => "spookygiantburningmonk.org", :port => 3000, :path => '/standing/in/a/wheelbarrow.aspx').
42
+ should == "http://spookygiantburningmonk.org:3000/standing/in/a/wheelbarrow.aspx"
43
+ end
44
+ it 'should append a query string if a query params hash is given' do
45
+ TestHarness.build_url('http://navyseals.mil', :swim_speed => '2knots').
46
+ should == 'http://navyseals.mil?swim_speed=2knots'
47
+ end
48
+ it 'should append a query string if a query string is given' do
49
+ TestHarness.build_url('http://chocolatecheese.com','?nuts=true').
50
+ should == 'http://chocolatecheese.com?nuts=true'
51
+ end
52
+ end
53
+
54
+ describe "get" do
55
+ it "should get the google" do
56
+ @mock_curb = mock(Curl::Easy, :headers= => nil, :headers => {}, :header_str => "", :response_code => 200, :body_str => 'yeeeah', :timeout= => nil, :http_get => nil)
57
+ Curl::Easy.should_receive(:new).with('http://www.google.com').and_return(@mock_curb)
58
+
59
+ TestHarness.get("http://www.google.com")
60
+ end
61
+ it "should return a 404 code correctly" do
62
+ mock_curb = mock(Object, :http_get => nil)
63
+ TestHarness.stub!(:build).and_return(mock_curb)
64
+ mock_response = mock(CurbFu::Response::NotFound, :status => 404)
65
+ CurbFu::Response::Base.stub!(:from_curb_response).and_return(mock_response)
66
+
67
+ TestHarness.get("http://www.google.com/ponies_and_pirates").should == mock_response
68
+ end
69
+ it "should append query parameters" do
70
+ @mock_curb = mock(Curl::Easy, :headers= => nil, :headers => {}, :header_str => "", :response_code => 200, :body_str => 'yeeeah', :timeout= => nil, :http_get => nil)
71
+ Curl::Easy.should_receive(:new).with(regex_for_url_with_params('http://www.google.com', 'search=MSU\+vs\+UNC', 'limit=200')).and_return(@mock_curb)
72
+ TestHarness.get('http://www.google.com', { :search => 'MSU vs UNC', :limit => 200 })
73
+ end
74
+
75
+ describe "with_hash" do
76
+ it "should get google from {:host => \"www.google.com\", :port => 80}" do
77
+ @mock_curb = mock(Curl::Easy, :headers= => nil, :headers => {}, :header_str => "", :response_code => 200, :body_str => 'yeeeah', :timeout= => nil, :http_get => nil)
78
+ Curl::Easy.should_receive(:new).with('http://www.google.com:80').and_return(@mock_curb)
79
+
80
+ TestHarness.get({:host => "www.google.com", :port => 80})
81
+ end
82
+ it "should set authorization username and password if provided" do
83
+ @mock_curb = mock(Curl::Easy, :headers= => nil, :headers => {}, :header_str => "", :response_code => 200, :body_str => 'yeeeah', :timeout= => nil, :http_get => nil, :http_auth_types= => nil)
84
+ Curl::Easy.stub!(:new).and_return(@mock_curb)
85
+ @mock_curb.should_receive(:userpwd=).with("agent:donttellanyone")
86
+
87
+ TestHarness.get({:host => "secret.domain.com", :port => 80, :username => "agent", :password => "donttellanyone"})
88
+ end
89
+ it "should append parameters to the url" do
90
+ @mock_curb = mock(Curl::Easy, :headers= => nil, :headers => {}, :header_str => "", :response_code => 200, :body_str => 'yeeeah', :timeout= => nil, :http_get => nil)
91
+ Curl::Easy.should_receive(:new).with(regex_for_url_with_params('http://www.google.com', 'search=MSU\+vs\+UNC', 'limit=200')).and_return(@mock_curb)
92
+ TestHarness.get({ :host => 'www.google.com' }, { :search => 'MSU vs UNC', :limit => 200 })
93
+ end
94
+ end
95
+ end
96
+
97
+ describe "post" do
98
+ before(:each) do
99
+ @mock_curb = mock(Curl::Easy, :headers= => nil, :headers => {}, :header_str => "", :response_code => 200, :body_str => 'yeeeah', :timeout= => nil)
100
+ Curl::Easy.stub!(:new).and_return(@mock_curb)
101
+ end
102
+
103
+ it "should send each parameter to Curb#http_post" do
104
+ @mock_q = Curl::PostField.content('q','derek')
105
+ @mock_r = Curl::PostField.content('r','matt')
106
+ TestHarness.stub!(:create_post_fields).and_return([@mock_q,@mock_r])
107
+
108
+ @mock_curb.should_receive(:http_post).with(@mock_q,@mock_r)
109
+
110
+ response = TestHarness.post(
111
+ {:host => "google.com", :port => 80, :path => "/search"},
112
+ { 'q' => 'derek', 'r' => 'matt' })
113
+ end
114
+ end
115
+
116
+ describe "post_file" do
117
+ it "should set encoding to multipart/form-data" do
118
+ @cc = mock(Curl::PostField)
119
+ Curl::PostField.stub!(:file).and_return(@cc)
120
+ mock_curl = mock(Object, :http_post => nil)
121
+ mock_curl.should_receive(:multipart_form_post=).with(true)
122
+ TestHarness.stub!(:build).and_return(mock_curl)
123
+ CurbFu::Response::Base.stub!(:from_curb_response)
124
+
125
+ TestHarness.post_file('http://example.com', {'gelato' => 'peanut butter'}, 'cc_pic' => '/images/credit_card.jpg')
126
+ end
127
+ it "should post with file fields" do
128
+ @cc = mock(Curl::PostField)
129
+ Curl::PostField.should_receive(:file).and_return(@cc)
130
+ mock_curl = mock(Object, :multipart_form_post= => nil, :http_post => nil)
131
+ TestHarness.stub!(:build).and_return(mock_curl)
132
+ CurbFu::Response::Base.stub!(:from_curb_response)
133
+
134
+ TestHarness.post_file('http://example.com', {'gelato' => 'peanut butter'}, 'cc_pic' => '/images/credit_card.jpg')
135
+ end
136
+ it "should offer more debug information about CurlErrInvalidPostField errors" do
137
+ @cc = mock(Curl::PostField)
138
+ Curl::PostField.should_receive(:file).and_return(@cc)
139
+ mock_curl = mock(Object, :multipart_form_post= => nil)
140
+ mock_curl.stub!(:http_post).and_raise(Curl::Err::InvalidPostFieldError)
141
+ TestHarness.stub!(:build).and_return(mock_curl)
142
+ CurbFu::Response::Base.stub!(:from_curb_response)
143
+
144
+ lambda { TestHarness.post_file('http://example.com', {'gelato' => 'peanut butter'}, 'cc_pic' => '/images/credit_card.jpg') }.
145
+ should raise_error(Curl::Err::InvalidPostFieldError)
146
+ end
147
+ end
148
+
149
+ describe "put" do
150
+ before(:each) do
151
+ @mock_curb = mock(Curl::Easy, :headers= => nil, :headers => {}, :header_str => "", :response_code => 200, :body_str => 'yeeeah', :timeout= => nil)
152
+ Curl::Easy.stub!(:new).and_return(@mock_curb)
153
+ end
154
+
155
+ it "should send each parameter to Curb#http_put" do
156
+ Curl::Easy.should_receive(:new).with('http://google.com:80/search?q=derek&r=matt').and_return(@mock_curb)
157
+ @mock_curb.should_receive(:http_put)
158
+
159
+ response = TestHarness.put(
160
+ {:host => "google.com", :port => 80, :path => "/search"},
161
+ { 'q' => 'derek', 'r' => 'matt' })
162
+ end
163
+ end
164
+
165
+ describe "create_post_fields" do
166
+ it "should return the params if params is a string" do
167
+ TestHarness.create_post_fields("my awesome data that I'm sending to you").
168
+ should == "my awesome data that I'm sending to you"
169
+ end
170
+ it "should convert hash items into Curl::PostFields" do
171
+ Curl::PostField.should_receive(:content).with('us','obama')
172
+ Curl::PostField.should_receive(:content).with('de','merkel')
173
+ TestHarness.create_post_fields(:us => 'obama', :de => 'merkel')
174
+ end
175
+ it "should handle params that contain arrays" do
176
+ Curl::PostField.should_receive(:content).with('q','derek,matt')
177
+
178
+ TestHarness.create_post_fields('q' => ['derek','matt'])
179
+ end
180
+ it "should handle params that contain any non-Array or non-String data" do
181
+ Curl::PostField.should_receive(:content).with('q','1')
182
+
183
+ TestHarness.create_post_fields('q' => 1)
184
+ end
185
+ it "should return an array of Curl::PostFields" do
186
+ TestHarness.create_post_fields(:ice_cream => 'chocolate', :beverage => 'water').each do |field|
187
+ field.should be_a_kind_of(Curl::PostField)
188
+ end
189
+ end
190
+ end
191
+
192
+ describe "create_put_fields" do
193
+ it "should return the params if params is a string" do
194
+ TestHarness.create_put_fields("my awesome data that I'm sending to you").
195
+ should == "my awesome data that I'm sending to you"
196
+ end
197
+
198
+ it 'should handle multiple parameters' do
199
+ TestHarness.create_put_fields(:rock => 'beatles', :rap => '2pac').
200
+ should == "rock=beatles&rap=2pac"
201
+ end
202
+
203
+ it "should handle params that contain arrays" do
204
+ TestHarness.create_put_fields('q' => ['derek','matt']).
205
+ should == "q=derek,matt"
206
+ end
207
+
208
+ it "should handle params that contain any non-Array or non-String data" do
209
+ TestHarness.create_put_fields('q' => 1).should == "q=1"
210
+ end
211
+ end
212
+
213
+ describe "global_headers" do
214
+ it "should use any global headers for every request" do
215
+ TestHarness.global_headers = {
216
+ 'X-Http-Modern-Parlance' => 'Transmogrify'
217
+ }
218
+
219
+ mock_curl = mock(Object, :timeout= => 'sure', :http_get => 'uhuh', :response_code => 200, :header_str => 'yep: sure', :body_str => 'ok')
220
+ Curl::Easy.stub!(:new).and_return(mock_curl)
221
+ mock_curl.should_receive(:headers=).with('X-Http-Modern-Parlance' => 'Transmogrify')
222
+ TestHarness.get('http://example.com')
223
+ end
224
+ it "should not keep temporary headers from previous requests" do
225
+ TestHarness.global_headers = {
226
+ 'X-Http-Political-Party' => 'republican'
227
+ }
228
+
229
+ mock_curl = mock(Object, :timeout= => 'sure', :http_get => 'uhuh', :response_code => 200, :header_str => 'yep: sure', :body_str => 'ok')
230
+ Curl::Easy.stub!(:new).and_return(mock_curl)
231
+ mock_curl.stub!(:headers=)
232
+
233
+ TestHarness.get(:host => 'example.com', :headers => { 'Content-Type' => 'cash/dollars' })
234
+
235
+ mock_curl.should_not_receive(:headers=).with(hash_including('Content-Type' => 'cash/dollars'))
236
+ TestHarness.get('http://example.com')
237
+ TestHarness.global_headers.should_not include('Content-Type' => 'cash/dollars') # leave no trace!
238
+ end
239
+ end
240
+ end